Reputation: 101
I use registerForActivityResult
just like :
package com.example.livedata
import android.Manifest
import android.app.Activity
import android.app.AlertDialog
import android.app.Dialog
import android.content.ActivityNotFoundException
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.view.View
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.example.livedata.databinding.ActivityAddBinding
import com.example.livedata.databinding.DialogCustomImageSelectionBinding
class AddActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var binding: ActivityAddBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAddBinding.inflate(layoutInflater)
setContentView(binding.root)
setupActionBar()
binding.photoAdd.setOnClickListener(this)
}
private fun setupActionBar() {
setSupportActionBar(binding.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
binding.toolbar.setNavigationOnClickListener { onBackPressed() }
}
override fun onClick(v: View?) {
if (v != null) {
when (v.id) {
R.id.photo_add -> {
imageDialog()
return
}
}
}
}
private fun imageDialog() {
val dialog = Dialog(this)
val dialogBinding: DialogCustomImageSelectionBinding =
DialogCustomImageSelectionBinding.inflate(layoutInflater)
dialog.setContentView(dialogBinding.root)
dialog.show()
dialogBinding.impCamera.setOnClickListener {
registerForActivityResult(ActivityResultContracts.TakePicturePreview()) {
if (it != null) {
Toast.makeText(this@AddActivity, "TakePicturePreview", Toast.LENGTH_SHORT).show()
}
}.launch(null).apply { arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA) }
dialog.dismiss()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
data?.let {
val bp = data.getParcelableExtra<Bitmap>("data")
binding.imageView.setImageBitmap(bp)
}
}
}
private fun showPermissions() {
AlertDialog.Builder(this).setMessage("Applay Permissions!")
.setPositiveButton("Go to Settings") { _, _ ->
try {
val intel = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts("package", packageName, null)
intel.data = uri
startActivity(intel)
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
}
}.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}.show()
}
}
But it do not work and throw an exception here :
2021-07-16 15:38:50.472 29885-29885/com.example.livedata E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.livedata, PID: 29885
java.lang.IllegalStateException: LifecycleOwner com.example.livedata.AddActivity@9fc53b9 is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
at androidx.activity.result.ActivityResultRegistry.register(ActivityResultRegistry.java:123)
at androidx.activity.ComponentActivity.registerForActivityResult(ComponentActivity.java:659)
at androidx.activity.ComponentActivity.registerForActivityResult(ComponentActivity.java:668)
at com.example.livedata.AddActivity.imageDialog$lambda-3(AddActivity.kt:68)
at com.example.livedata.AddActivity.lambda$N7K_EbTML-ycmUwpA7-i8b_L-Sw(Unknown Source:0)
at com.example.livedata.-$$Lambda$AddActivity$N7K_EbTML-ycmUwpA7-i8b_L-Sw.onClick(Unknown Source:4)
at android.view.View.performClick(View.java:7281)
at android.view.View.performClickInternal(View.java:7255)
at android.view.View.access$3600(View.java:828)
at android.view.View$PerformClick.run(View.java:27925)
at android.os.Handler.handleCallback(Handler.java:900)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8393)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
2021-07-16 15:38:50.539 1689-2062/? E/InputDispatcher: channel 'ba7a009 com.example.livedata/com.example.livedata.AddActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
How can I use the registerForActivityResult to accomplish this task instead of the deprecated method? All help is much appreciated.
Upvotes: 10
Views: 33256
Reputation: 125
Here is the Java Code version - Using ActivityResultLauncher
In Activity A : Launch Activity B, eg: if you using a Button View onSetClickListener
Button btn
= findViewById(enter button view id name here
)
Call the btn.setOnClickListener and place this code in the onClick()-method of the button
mStartForResult.launch(new Intent(MainActivity.this, DestinationActivity.class));
Call ActivityResultLauncher API and retrieve the result from Activity B using the Intent & the ResultCode.
`
ActivityResultLauncher<Intent>mStartForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),new ActivityResultCallback<ActivityResult>()
{
if(result.getResultCode()== Activity.RESULT_OK)
{
Intent intent = result.getData();
'enter your code here'
}
});
You may want to use shared preferences to save and retrieve data from ActivityB to A
In Activity B: Call the btn.setOnClickListener and place this code in the onClick()-method of the button:
`Intent intent = new Intent(DestinationActivity.this,MainActivity.class);`
intent.putExtra(EXTRA, `enter your input(int or String) here`);
setResult(RESULT_OK, intent);
finish();
Upvotes: 1
Reputation: 20197
You're trying to call registerForActivityResult
in a click listener. That's not going to work, because your Activity
might be destroyed and recreated before the result is delivered. The recreated Activity
won't have been registered to receive the result, because it only registers when you click the button, and the button was only clicked in the original Activity
.
To fix this, you need to call registerForActivityResult
unconditionally and store the result in a variable:
class MyActivity : AppCompatActivity() {
private val activityLauncher = registerForActivityResult(...
That way, the recreated Activity
will be registered to receive the result. Then use that activityLauncher
variable to launch it from the button click listener.
For more information, see the official guide.
Upvotes: 14
Reputation: 2846
Kotlin - Below code instead of startActivityForResult
deprecation this method gives the result itself and returns a value.
val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
when (result.resultCode) {
Activity.RESULT_OK -> {
// logic
}
else -> {
// logic
}
}
}
Upvotes: 2