When I call createMatch() on TurnBasedMultiplayerClient the task that it returns is false(task.isSuccessful) and the exception I get is com.google.android.gms.common.api.ApiException: 26502: CLIENT_RECONNECT_REQUIRED.
The documentation says that the GoogleApiClient is is in an inconsistent state but how do I reconnect it? I don't have a GoogleAPiClient object so I can't just call GoogleAPiClient.reconnect().
I'm using the default ui for selecting players:
private fun onStartMatchClicked() {
val allowAutoMatch = true
mTurnBasedMultiplayerClient = Games.getTurnBasedMultiplayerClient(this#MultiplayerActivity, clientAccount!!)
mTurnBasedMultiplayerClient!!.getSelectOpponentsIntent(1, 1, allowAutoMatch)
.addOnSuccessListener { intent -> startActivityForResult(intent, RC_SELECT_PLAYERS) }
}
Here's the onActivityResult method:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RC_SELECT_PLAYERS) {
if (resultCode != Activity.RESULT_OK) {
finish()
return
}
val invitees = data!!.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS)
// Get automatch criteria
var autoMatchCriteria: Bundle? = null
val minAutoPlayers = data.getIntExtra(Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0)
val maxAutoPlayers = data.getIntExtra(Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0)
autoMatchCriteria = RoomConfig.createAutoMatchCriteria(minAutoPlayers,
maxAutoPlayers, 0)
val tbmc = TurnBasedMatchConfig.builder()
.addInvitedPlayers(invitees)
.setAutoMatchCriteria(autoMatchCriteria).build()
mTurnBasedMultiplayerClient!!.createMatch(tbmc).addOnCompleteListener { task ->
if (task.isSuccessful) { //this is where I get the exception
match = task.result
} else {
// There was an error. Show the error.
var status = CommonStatusCodes.DEVELOPER_ERROR
val exception = task.exception
if (exception is ApiException) {
val apiException = exception as ApiException?
status = apiException!!.statusCode
}
handleError(status, exception)
}
}
}
}
Related
I'm trying to get a response inside the onActivityResult from an uri intent. However, it is always -1 as resultCode and null as Intent data.
private fun startMyFunction(call: MethodCall) {
val app: String? = call.argument("app")
val url: String? = call.argument("url")
try {
val uri = Uri.parse(url)
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.setPackage(app)
if (activity?.let { intent.resolveActivity(it.packageManager) } == null) {
this.success("activity_unavailable")
return
}
activity?.startActivityForResult(intent, requestCodeNumber)
} catch (ex: Exception) {
Log.e("my_app", ex.toString())
this.success("failed_to_open_app")
}
}
private fun success(o: String) {
if (!hasResponded) {
hasResponded = true
result?.success(o)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
if (requestCodeNumber == requestCode && result != null) {
Log.d("onActivityResult - response - ", data.toString())
if (data != null) {
try {
val response = data.getStringExtra("response")!!
this.success(response)
} catch (ex: Exception) {
this.success("invalid_response - Exception")
}
} else {
this.success("user_cancelled - Null data")
}
}
return true
}
I have read many of the similar situations here on StackOverflow, as well as on Google, but none of them have helped me in my case
For ref -
https://github.com/GJJ2019/upi_pay/blob/master/android/src/main/kotlin/com/drenther/upi_pay/UpiPayPlugin.kt
I have to solve following problem:
Calling an Intent from Flutter, waiting for finish the process of the Intent, and return the result to Flutter (call a card reader app trough intent, read the card, and return if the reading process is success or not).
The code in my Flutter app is:
Future<List<String>?> startActivityForResult(double amount, String operation)async {
const platform = const MethodChannel('reader');
try {
final String? result = await platform.invokeMethod('StartReading',<String, dynamic>{
"Amount" : amount,
"Operation" : operation,
"TransactionID" : Uuid().v1()
});
} on PlatformException catch (e) {
print('Error: ${e.message}');
}
}
code in MainActivity.kt:
class MainActivity: FlutterActivity() {
private val CHANNEL = "reader"
override fun configureFlutterEngine(#NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// Note: this method is invoked on the main thread.
call, result ->
var REQ_CODE: Int = 1;
var RES_CODE: Int = -1;
if (call.method == "StartReading") {
var JSON: JSONObject = JSONObject();
JSON.put("Amount", call.argument("Amount"));
JSON.put("Operation", call.argument("Operation"));
JSON.put("TransactionID",call.argument("TransactionID"));
var intent: Intent = Intent();
intent.component = ComponentName("co.reader.posterminal", "co.reader.posterminal.MainActivity");
intent.putExtra("POS_EMULATOR_EXTRA",JSON.toString());
startActivityForResult(intent, REQ_CODE);
onActivityResult(REQ_CODE,RES_CODE, intent);
} else {
result.notImplemented()
}
#Override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK ) {
if (requestCode == REQ_CODE) {
try {
var Result: String? = data?.getStringExtra("POS_EMULATOR_RESULT");
var JSONResult: JSONObject = JSONObject(Result);
result.success(Result);
} catch (e: Exception) {
Log.println(Log.ERROR,"Error: ",e.toString());
}
}
}
};
}
}
}
The reading process start well (startActivityForResult), reading process is also ok, but i don't get any result.
Can anybody solve, why?
On my app, users can save some notes with image. But, users can not save their notes without image. Thus image is compulsory to save their data. But ı want to change it. I want to allow them to save their note without image. How can ı do this ? This is my saveclcikbutton codes;
class TakeNotesActivity : AppCompatActivity() {
var selectedPicture: Uri? = null
var selectedBitmap: Bitmap? = null
private lateinit var db: FirebaseFirestore
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_take_notes)
auth = FirebaseAuth.getInstance()
db = FirebaseFirestore.getInstance()
}
fun putPictureClick(view: View) {
val popupMenu = PopupMenu(this, view)
val inflater = popupMenu.menuInflater
inflater.inflate(R.menu.secondmenu, popupMenu.menu)
popupMenu.show()
popupMenu.setOnMenuItemClickListener {
if (it.itemId == R.id.galleryImage) {
if (ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
1
)
} else {
val intentToGallery =
Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(intentToGallery, 2)
}
}
if (it.itemId == R.id.capturePhoto) {
if (ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.CAMERA),
10
)
} else {
openCamera()
}
}
if (it.itemId == R.id.cancel) {
Toast.makeText(applicationContext, "Canceled", Toast.LENGTH_LONG).show()
}
true
}
}
fun openCamera() {
val values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "New Picture")
values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera")
selectedPicture =
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
// Camera Intent
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, selectedPicture)
startActivityForResult(cameraIntent, 20)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == 1) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
val intentToGallery =
Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(intentToGallery, 2)
}
}
if (requestCode == 10) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openCamera()
} else {
Toast.makeText(this, "Permission Denied", Toast.LENGTH_LONG).show()
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 2 && resultCode == Activity.RESULT_OK && data != null) {
selectedPicture = data.data
try {
if (selectedPicture != null) {
if (Build.VERSION.SDK_INT >= 28) {
val source =
ImageDecoder.createSource(this.contentResolver, selectedPicture!!)
selectedBitmap = ImageDecoder.decodeBitmap(source)
imageButton.setImageBitmap(selectedBitmap)
} else {
selectedBitmap =
MediaStore.Images.Media.getBitmap(this.contentResolver, selectedPicture)
imageButton.setImageBitmap(selectedBitmap)
}
}
} catch (e: Exception) {
}
}
//called when image was captured from camera intent
if (requestCode == 20 && resultCode == Activity.RESULT_OK && data != null) {
imageButton.setImageURI(selectedPicture)
}
super.onActivityResult(requestCode, resultCode, data)
}
fun saveClick(view: View) {
//UUID -> Image Name
val uuid = UUID.randomUUID()
val imageName = "$uuid.jpg"
val storage = FirebaseStorage.getInstance()
val reference = storage.reference
val imagesReference = reference.child("images").child(imageName)
if (selectedPicture != null) {
imagesReference.putFile(selectedPicture!!).addOnSuccessListener { taskSnapshot ->
// take the picture link to save the database
val uploadedPictureReference =
FirebaseStorage.getInstance().reference.child("images").child(imageName)
uploadedPictureReference.downloadUrl.addOnSuccessListener { uri ->
val downloadUrl = uri.toString()
println(downloadUrl)
val noteMap = hashMapOf<String, Any>()
noteMap.put("downloadUrl", downloadUrl)
noteMap.put("userEmail", auth.currentUser!!.email.toString())
noteMap.put("noteTitle", titleText.text.toString())
noteMap.put("yourNote", noteText.text.toString())
noteMap.put("date", Timestamp.now())
db.collection("Notes").add(noteMap).addOnCompleteListener { task ->
if (task.isComplete && task.isSuccessful) {
finish()
}
}.addOnFailureListener { exception ->
Toast.makeText(
applicationContext,
exception.localizedMessage?.toString(),
Toast.LENGTH_LONG
).show()
}
}
}
}
}
}
I also try to add on saveClick fun the codes below but did not work. What should I do ?
fun saveClick(view: View) {
//UUID -> Image Name
val uuid = UUID.randomUUID()
val imageName = "$uuid.jpg"
val storage = FirebaseStorage.getInstance()
val reference = storage.reference
val imagesReference = reference.child("images").child(imageName)
if (selectedPicture != null) {
imagesReference.putFile(selectedPicture!!).addOnSuccessListener { taskSnapshot ->
// take the picture link to save the database
val uploadedPictureReference =
FirebaseStorage.getInstance().reference.child("images").child(imageName)
uploadedPictureReference.downloadUrl.addOnSuccessListener { uri ->
val downloadUrl = uri.toString()
println(downloadUrl)
val noteMap = hashMapOf<String, Any>()
noteMap.put("downloadUrl", downloadUrl)
noteMap.put("userEmail", auth.currentUser!!.email.toString())
noteMap.put("noteTitle", titleText.text.toString())
noteMap.put("yourNote", noteText.text.toString())
noteMap.put("date", Timestamp.now())
db.collection("Notes").add(noteMap).addOnCompleteListener { task ->
if (task.isComplete && task.isSuccessful) {
finish()
}
}.addOnFailureListener { exception ->
Toast.makeText(
applicationContext,
exception.localizedMessage?.toString(),
Toast.LENGTH_LONG
).show()
}
}
}
}else {
val noteMap = hashMapOf<String, Any>()
noteMap.put("userEmail", auth.currentUser!!.email.toString())
noteMap.put("noteTitle", titleText.text.toString())
noteMap.put("yourNote", noteText.text.toString())
noteMap.put("date", Timestamp.now())
db.collection("Notes").add(noteMap).addOnCompleteListener { task ->
if (task.isComplete && task.isSuccessful) {
finish()
}
}
}
}
}
So all your logic is basically wrapped up in that putFile success callback, which requires an image to be successfully stored and retrieved (?) before anything will be added to the database.
You need to break that logic up, so you can only run the parts you want to - like just running the database update part if you don't have an image, or running that part later once your image is successfully handled.
So really, you need a "store in database" function to handle the final writing - call that directly if you don't have an image, call it in the success callbacks if you do. I'm just going to pseudocode this but:
saveData(noteMap: Map) {
add note to DB
}
saveClick() {
create noteMap with basic, non-image details (email, title etc)
if image is null, call saveData(noteMap)
else do the image stuff:
onSuccess:
add the downloadUrl to noteMap
call saveData(noteMap)
}
I see you've made an edit with an else branch which creates the map sans url and writes it - you're basically almost there, just make it a function instead, and pass the map in!
I use Intent.ACTION_PICK to take picture from gallery.
I already success when implement both activity, but found problem when using fragment.
I need some help, please.
Here MainActivity.kt
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_NEW_CHAT -> {
val name: String = data?.getStringExtra(PARAM_NAME) ?: ""
val phone: String = data?.getStringExtra(PARAM_PHONE) ?: ""
checkNewChatUser(name, phone)
}
//TODO: I.5. Update Status Page
REQUEST_CODE_PHOTO -> statusUpdateFragment?.storeImage(data?.data)
}
}
}
Here StatusUpdateFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lay_progressbar.setOnTouchListener { v, event -> true }
btn_status.setOnClickListener { onUpdate() }
populateImage(context, imageUrl, img_status)
lay_status.setOnClickListener{
if(isAdded){
(activity as MainActivity).startNewActivity(REQUEST_CODE_PHOTO)
}
}
}
fun storeImage(imageUri: Uri?) {
if (imageUri != null && userId != null) {
//error message : Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
try {
Toast.makeText(activity, "Uploading...", Toast.LENGTH_SHORT).show()
lay_progressbar.visibility = View.VISIBLE
}
catch (e:Exception){
e.message
}
/*more code that i hide it...*/
}
}
Alhamdulillah, i already solved by Fahru.
MainActivity.kt : must add this at onActivityResult
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_NEW_CHAT -> {
val name: String = data?.getStringExtra(PARAM_NAME) ?: ""
val phone: String = data?.getStringExtra(PARAM_PHONE) ?: ""
checkNewChatUser(name, phone)
}
//TODO: I.5. Update Status Page
REQUEST_CODE_PHOTO -> statusUpdateFragment?.storeImage(data?.data,this)
}
}
}
StatusUpdateFragment.kt : must add context at storeImage
```
fun storeImage(imageUri: Uri?, context: Context) {
if (imageUri != null && userId != null) {
try {
Toast.makeText(context, "Uploading...", Toast.LENGTH_SHORT).show()
lay_progressbar.visibility = View.VISIBLE
}
catch (e:Exception){
e.message
}
//more code hidden
}
```
I would like to ask about why run app, avatar of FirebaseUser's profilePhoto will disappear?
But if just login or logout, avatar of FirebaseUser's profilePhoto can retain status.
If I picked one photo from mobile storage to avatar, then logout and login, avatar still the same. But run app, avatar will disappear, why?
class ProfileFragment : Fragment() {
companion object {
val TAG = ProfileFragment::class.java.simpleName
val instance by lazy {
ProfileFragment()
}
var user:FirebaseUser? = null
private val REQUEST_CODE_CHOOSE_AVATAR: Int = 200
// var userPhotoUrl:Uri? = null
}
private lateinit var viewModel: ProfileViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.profile_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
retainInstance = true
viewModel = ViewModelProviders.of(this).get(ProfileViewModel::class.java)
// TODO: Use the ViewModel
user = FirebaseAuth.getInstance().currentUser
// userPhotoUrl = user?.photoUrl
Picasso.get()
.load(user?.photoUrl)
.placeholder(R.mipmap.ic_launcher)
.transform(CropCircleTransformation())
.into(avatar_url)
name.text = user?.displayName
avatar_url.setOnClickListener {
val intent = Intent().apply {
type = "image/*"
action = Intent.ACTION_GET_CONTENT
action = Intent.ACTION_PICK
}
startActivityForResult(Intent.createChooser(intent,"Choose avatar"),REQUEST_CODE_CHOOSE_AVATAR)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_CHOOSE_AVATAR) {
if (resultCode == RESULT_OK) {
if (data != null) {
// val user = FirebaseAuth.getInstance().currentUser
val uri = data.data
val userProfileChangeRequest = UserProfileChangeRequest.Builder()
.setPhotoUri(uri)
.build()
user?.updateProfile(userProfileChangeRequest)
?.addOnCompleteListener {
if (it.isSuccessful) {
Picasso.get()
.load(user?.photoUrl)
.transform(CropCircleTransformation())
.into(avatar_url)
FirebaseFirestore.getInstance()
.collection("uploadedImages")
.whereEqualTo("uid",user?.uid)
.addSnapshotListener { querySnapshot, firebaseFirestoreException ->
if (querySnapshot != null && !querySnapshot.isEmpty) {
for (doc in querySnapshot.documents) {
Log.d(TAG, "uploadedImages's doc: ${doc.data}");
doc.data?.set("avatarUrl", user?.photoUrl.toString())
}
} else {
firebaseFirestoreException.toString()
}
}
FirebaseFirestore.getInstance()
.collection("userData")
.document(user!!.uid)
.update("avatarUrl", user!!.photoUrl.toString())
}
}
}
}
}
}
}
Login and logout, avatar still retain
Why re-run app avatar will disappear?
Have solved the problem.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_CHOOSE_AVATAR) {
if (resultCode == RESULT_OK) {
if (data != null) {
// val user = FirebaseAuth.getInstance().currentUser
val uri = data.data
val avatarRef = FirebaseStorage.getInstance().reference
.child("userAvatar")
.child(user!!.uid)
.child(uri.toString())
avatarRef.putFile(uri!!)
.continueWithTask {
if (!it.isSuccessful) {
it.exception?.let {
throw it
}
}
avatarRef.downloadUrl
}.addOnCompleteListener {
if (it.isSuccessful) {
val avatarDownloadUrl = it.result
val userProfileChangeRequest = UserProfileChangeRequest.Builder()
.setPhotoUri(avatarDownloadUrl)
.build()
user?.updateProfile(userProfileChangeRequest)
?.addOnCompleteListener { it1 ->
if (it1.isSuccessful) {
Picasso.get()
.load(user?.photoUrl)
.transform(CropCircleTransformation())
.into(avatar_url)