Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Controlling Android Activity restart after a process stops

My app is running on a special device that is running a custom build of Android Gingerbread 2.3.7

There are conditions where the system will terminate my app. I assume that the device manufacturer considers these emergency situations where all third party apps should be immediately shut down so the device can do its primary tasks.

I can duplicate the behavior I see on the device using an emulator and in DDMS selecting my task and clicking the "Stop Process" button. Here is the behavior I see.

My app typically steps through four activities, Activity A launches activity B, B launches Activity C, and C launches activity D. So, when activity D is running on top, my stack is:

A - B - C - D

If at this point, the process is terminated, Activity D does not receive onPause() or an onStop() call. It has no opportunity to save its state.

After the process is dead, Android's ActivityManager starts a new task for my app and launches Activity C. I think this is standard Android behavior to restart crashed apps.

My question is can I control this restart behavior? If Android is going to restart my app, I need the activity stack restored, Activity C doesn't really make sense to be run stand alone (clicking the back button would exit the app and that doesn't make sense for this activity).

Can I prevent this restart? Can I have the restart start all my activities in sequence? Can I have the restart just start activity A?

I did find this interesting discussion which I believe explains why Activity C is restarted and not Activity D.

As far as when an activity is restarted -- if the process running the foreground activity goes away, the system will throw away that activity if it does not have a valid saved state for it (typically meaning it is paused and has given the system the result of onSaveInstanceState from before the pause). Once it has decided whether or not to throw away that activity, it will resume whatever activity is now at the top of the stack. If this is one of your activities -- either because you have another behind the one that crashed, or the one that crashed was somehow it the settled pause state -- then it will start your process again to show that top activity.

And some similar questions like Prevent Activity Stack from being Restored? and this interesting thread

like image 390
Michael Levy Avatar asked Mar 15 '14 20:03

Michael Levy


People also ask

How to restart an activity in Android?

How to restart an Activity in Android? This example demonstrates how do I restart an Activity in android. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main.xml. Step 3 − Add the following code ...

How do I pause an activity and restart it?

For most activities that are relatively simple, the activity will stop and restart just fine and you might only need to use onPause () to pause ongoing actions and disconnect from system resources. Figure 1. When the user leaves your activity, the system calls onStop () to stop the activity (1).

Why does my Android app keep restarting after screen orientation change?

On every single one android application project there is a by default configuration that is each and every time after rotating your android device and changing your screen orientation mode to landscape it will restart your whole android activity.

Why does my Android phone keep restarting itself?

Sometimes unwanted or corrupted files on your Android phone can cause a reboot loop to occur. In this case, 1. Remove the SD card and SIM from the device. 2. Now power off the device and boot it again (or) restart the device.


1 Answers

After a lot of experimenting, I opted for the approach hinted at in "Android Developers › Activity restart crash after OS kills it". One Q/A interchange there was:

Question:

"have stepped through the code and have seen what you are talking about. It calls onSaveInstanceState and saves the data in the Bundle. Will this Bundle information be available when the activity restarts after the OS kills the process?"

Answer:

"It's supposed to. You will get that Bundle in onCreate() and in onRestoreInstanceState(). onCreate() can be passed null for the Bundle, if there is no Bundle to restore. onRestoreInstanceState() is only called when there is a Bundle to restore."

I moved all the session data needed to recover after the app is killed into a serializable singleton.

In onSaveInstanceState() I put the serialized session data in to the savedInstanceState bundle

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    // save and restore session data to instance state to recover from task termination 
    savedInstanceState.putSerializable(SessionVariables.class.getName(), mSessionVariables);        
}

In onCreate() and onRestoreInstanceState() I test to see if my session singleton instance is valid. If it doesn't have valid data, I restore the session variables from the savedInstanceState bundle and put this restored object as my session variable singleton.

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    if (mSessionVariables.propertyThatShouldbeGood == null || mSessionVariables.propertyThatShouldbeGood .length() == 0)
    {
        // save and restore session data to instance state to recover from task termination
        Serializable serializedSessionVariables = savedInstanceState.getSerializable(SessionVariables.class.getName());

        if (serializedSessionVariables != null) {
            mSessionVariables = (SessionVariables) serializedSessionVariables;
            SessionVariables.putInstance(mSessionVariables);
        }
    }
}

Now when my task is killed, Android restores the previous activity from the stack. The onCreate() restores all the necessary session data from the saved instance state bundle.

The Back button also works fine at this point, so I was wrong Android not preserving the Activity stack. I think it just restores the back activities as needed (when you navigate back). If you don't navigate back, it doesn't create them. At least that is what it looked like in HierarchyViewer.

When my stack is A-B-C-D and the task is killed, Activity "C" is restored and "D" is lost. But, now "C" is in a healthy state and the user can easily navigate back to "D". Now, I could also start the "D" activity automatically from "C", I just haven't had time yet.

like image 161
Michael Levy Avatar answered Oct 06 '22 21:10

Michael Levy