Search code examples
androidkotlinonsaveinstancestate

onSaveInstanceState() not being called when user presses home button


I ran into a frustrating issue while trying to preserve state through onSaveInstanceState() so I figured to offer up my scenario and answer my own question in order to help others. (The code is in Kotlin, but the concepts are the same)

I have multiple fragments that the user can switch through via on screen navigation. In order to remember where the user is, i am saving the location in onSaveInstanceState()

override fun onSaveInstanceState(savedInstanceState: Bundle?){
        super.onSaveInstanceState(savedInstanceState)
        Log.d(TAG, "whereAreWe ${appLocation.name}")
        with(savedInstanceState!!){
            putInt("whereAreWe", appLocation.ordinal)
            putString("questionStatistics", questionStatistics.toString())   
        }
    }

So then when the user rotates the screen or navigates back to the app from pressing the home button (in onCreate()):

      ....
      if(savedInstanceState == null){
            Log.d(TAG, "Opening Dashboard")
            appLocation = AppLocation.DASHBOARD
            supportFragmentManager.beginTransaction().replace(R.id.fragment_holder, DashboardFragment(), DashboardFragment.TAG).commit()
        }
        else {
            appLocation = AppLocation.values()[savedInstanceState.getInt("whereAreWe")]
            Log.d(TAG, "Opening Fragment: ${appLocation.name}")
            when (appLocation) {
                AppLocation.DASHBOARD -> supportFragmentManager.beginTransaction().replace(R.id.fragment_holder,
                        supportFragmentManager.findFragmentByTag(DashboardFragment.TAG),
                        DashboardFragment.TAG).commit()
  ......

And everything worked great when the user rotates the screen, their location was remembered and the app navigated them to the appropriate fragment.

BUT when the user pressed the home button on the phone, then navigated back to the app, onSaveInstanceState() was not being called, and since savedInstanceState was null, the user would be forced back to the main dashboard fragment.

I scoured online for a solution, but no scenario truly matched mine: where it worked for screen orientation changes, but not after pressing the home screen.


Solution

  • As it turns out, the issue was not with which Android version was being used, or how the code was written, the problem was in the manifest file. For some reason or another (copy paste, default setting), i had the tag noHistory marked as true for my activity.

    <activity android:name=".MainActivity" android:noHistory="true"></activity>
    

    I am not sure why i had that there but it was causing all sorts of problems. I switched to:

    <activity android:name=".MainActivity"></activity>
    

    Having the noHistory tag marked to true prevented onSaveInstanceState() from being called when the user pressed the home button (app goes to background) but still allowed for the state to be saved when screen orientation changes happened.

    I had never encountered this behavior before and other questions that had issues with onSaveInstanceState not being called never mentioned checking the manifest file for this tag, so hopefully this helps to clarify any issues for other folks.