Anju
Anju

Reputation: 9479

registerForActivityResult not working when second activity orientation changes

I am calling activity B from activity A using the ActivityResultLauncher and setting the result from activity B when the task is done. This works perfectly if orientation is not changed. The problem is when I change orientation from activity B and then setting the result, then registerForActivityResult of activity A is not called. Could someone let me know, what could be the issue?

Note: I do not face this issue if I am using startActivityForResult and onActivityResult. I changed this to ActivityResultLauncher as startActivityForResult became deprecated.

activity A sample code:

private lateinit var launcher: ActivityResultLauncher<Intent>

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(layout)
    setLauncherResult()
}

private fun setLauncherResult() {
    launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
        if (result.resultCode == Activity.RESULT_OK) {
            //Do operations here
        }
}

 //On button click starting activity B using launcher
 val intent = Intent(activityA, activityB)
 launcher.launch(intent)

}

activity B sample code:

//setting result
val intent = Intent()
//set intent extras
setResult(Activity.RESULT_OK, intent)
finish()

Upvotes: 9

Views: 11518

Answers (3)

fattire
fattire

Reputation: 8923

Try moving the registerForActivityResult assignment of launcher to onCreateView() (override it if you haven't already). Putting it here, I'm not getting the "is attempting to register while current state is STARTED" RuntimeException in OnCreateView() as it would with onResume() or later. The advantage of OnCreateView() over OnCreate() seems to be that the launcher variable will get re-set on theme day/night changes as well as just orientation changes.

Also see the Configuration change & Process death section here for more discussion.

I know the official dox say it's safe to set it before anything else in the class, but theme changes broke .launch(), and this location appears to work for me.

Upvotes: 0

Mayur Gajra
Mayur Gajra

Reputation: 9093

Everytime orientation changes it calls onCreate and it resets your views & Other variables like launcher are re-assigned. So you can follow the example shown in official document here: https://developer.android.com/training/basics/intents/result#launch

And pull your launcher assignment out of onCreate as following (This worked for me):

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding


    private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
        if (result.resultCode == Activity.RESULT_OK) {
            //do your stuff here
            binding.tv.text = result.data?.getStringExtra("text")
        }
    }


    companion object {
        var number : Int = 0
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.tv.setOnClickListener {
            val intent = Intent(this, ActivityB::class.java)
            startForResult.launch(intent)
        }
    }
}

If you don't want that onCreate should be called again when orientation changes. Then in your Manifest you can add configChanges:

<activity android:name=".MainActivity"
            android:configChanges="orientation|screenSize">

Upvotes: 0

ΓDΛ
ΓDΛ

Reputation: 11110

You can save the value in onSaveInstanceState() and use setResult in onRestoreInstanceState().

Upvotes: 0

Related Questions