13

I have an application where the entry point is let's say a "login/splash" Activity, where I need to pre-load fresh data from the server. This SplashActivity is declared as :

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

in my AndroidManifest.xml, after data is loaded, I keep some data on my custom Application class and I proceed to my MainActivity.

I am expecting, that after my Application is stopped by the OS or by the user (using Force Stop), and then later is re-started by the user, the entry point of my application to be SplashActivity again BUT the system skips the SplashActivity and displays the MainActivity.

QUESTION: is this the expected behaviour? If the entire process is stopped, shouldn't my application be started with SplashActivity? Can this be accomplished?

Ovidiu Latcu
  • 71,607
  • 15
  • 76
  • 84

2 Answers2

29

Actually, there are several problems that are addressed by this question and some of the answers to it:


To answer your original question, "Yes, this is the expected behaviour".

Android considers each Activity to be a separate self-contained entity. Android remembers the state of activities in the task stack and it has no problem killing your process (which contains all your activities) whenever it wants to, because it "knows" that it can always reconstruct your activities whenever it needs to. This concept, of course, breaks down when you have a complex application where you have dependencies between the activities and/or you have global data that you store in an Application class (or similar static/singleton place).

When Android kills your process it remembers the topmost activity in the task and when the user returns to the task it recreates the process and then recreates only the topmost activity in the task. In your case, MainActivity.

As an example, if your task stack looks like this:

StartActivity -> ActivityB -> ActivityC -> ActivityD

and your task goes to the background and Android kills the process, when the user returns to the task only ActivityD will be recreated. Once ActivityD is finished, Android will then recreate ActivityC. Once ActivityC is finished, Android will recreate ActivityB, etc. In short, the complete stack is not recreated when the user resumes the task.

There is no combination of manifest settings or Intent flags that will get you the behaviour that you want. It would be nice if Android offered something like that, but at the moment it does not.


You can determine if your process has been restarted by using a static (class) boolean variable in your Application-derived class (or in any other class). This variable will always have the value false when the process is restarted and you can then check the state of the variable from anywhere and reinitialize (reload your data) if necessary. Then you set the variable to true. It will remain true until the process is killed and recreated, even if all your activities finish. In this way you can initialize only when needed.

You can also use this as an indicator to restart your application from the SplashScreen. So in all your activities, in onCreate(), you can check the state of this boolean variable and if the application has been restarted you can simply redirect to the SplashScreen like this:

Intent intent = new Intent(this, SplashScreen.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

This will finish all the activities in the task and restart the SplashScreen at the root of the task.


Next, if you want to prevent having to download data every time the user returns to the application (when it was in the background and subsequently killed by the AndroidOS), you should store the data that you download in the private cache area and use that when the application is restarted. This prevents having to download the data repeatedly if your process is killed and restarted.


Another way of dealing with this would be to load your data in a Service. If you have a Service running in your process then Android is less likely to kill your process. You just need to make sure that you shut down your Service when the user is finished with your application.


I realize this answer is long-winded. Hopefully you can get something out of it.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • yes. thanks for your time on this. I was really convinced that once the process is stopped by the OS, the application will be restarted from the entry-point... because this is what happens when we STOP it... throug DDMS, or Settings->Applications. – Ovidiu Latcu Jun 28 '12 at 17:35
  • 2
    no, that's actually not true. What happens when you stop it is this: The debugger sends a signal to the process to kill it, so the process dies. Android sees this and says "Oh, there's a badly behaved activity in that application that caused it to die. So I am going to restart that process for the user, but before I do that, I'm going to remove that badly behaving activity from the stack". So what you see is the process restarted with your root activity. – David Wasser Jun 28 '12 at 18:47
  • 1
    thanks a billion to both of you... I have spent few days on similar problem http://stackoverflow.com/questions/11190469/android-app-crashes-suddenly-while-running... Question and your answer really helped a lot... – Amit Jun 29 '12 at 12:06
  • @DavidWasser... How I know why the android restarted my activity ? I have JNI code and a dozen theads to access that... App is restarting and I can't find out why ? please see my question at http://stackoverflow.com/questions/11190469/android-app-crashes-suddenly-while-running – Amit Jun 29 '12 at 12:08
0

It can be done like this:

1. SplashActivity will start no doubt every time.

2. Download the data and save the check(boolean) indicating the loading is done previously.You can use SharedPreferences.

3. Check the condition next time and start your MainActivity immediately.

Vineet Shukla
  • 23,865
  • 10
  • 55
  • 63
  • yes but once i set my "check" to true, when do I set it to "false"? – Ovidiu Latcu Jun 28 '12 at 11:07
  • regarding "1", how can you argument that Splash will start every time? somebody here is having the same problem, after application being restarted http://stackoverflow.com/questions/11190469/android-app-crashes-suddenly-while-running/11242705#11242705 – Ovidiu Latcu Jun 28 '12 at 11:08
  • do you need to download the data every time your app starts? – Vineet Shukla Jun 28 '12 at 11:08
  • yeah. and then keep it in Application, until app is re-started. – Ovidiu Latcu Jun 28 '12 at 11:13
  • the link says about the app restart and app restart means the activity which you have made the app launcher will get called. – Vineet Shukla Jun 28 '12 at 11:13
  • you said if the app is stopped by the OS and what about if the user stops? – Vineet Shukla Jun 28 '12 at 11:15
  • no, he says that not the `LAUNCHER` activity is started, instead the last "visible/used" Activity. – Ovidiu Latcu Jun 28 '12 at 11:15
  • doesn matter. if the Application is stoped, destroyed by os whatever, next time I start it, I want it to be started with `SplashActivity`. This does not happen, sometimes it is started using `MainActivity`. – Ovidiu Latcu Jun 28 '12 at 11:20