Familiar scenario: I have a Main activity that launches a Game activity when a button is pressed. If the user presses HOME, and then launches my applicatio
I understand where you are coming from but I think the os doesn't want to make any assumptions. Plus there is the issue where your app has been reclaimed because memory is need for something else. In that cause it would be starting over from your MainActivity.
Depending on how complicated your game is your can either save state in SharedPreferences or a SqlLite database in the onPause() method of your activity. Then onResume() you can restore the user to the last state, which may include "re-starting" your GameActivity.
Hope this helps!
Edit: And what I am saying is that's our responsibility as developers to show / guarantee to the user that the correct activity is displayed when coming back to the application. You application's memory always has the potential of being reclaimed and then android is going to re-start the activity that you have labeled with MAIN and LAUNCHER intents. By saving the state (the activity id) you can redirect them to that activity from main...
The simplest solution is to write a preference out during onPause or serialize your state out to a persistent file and then read this file during onResume in your main entry point Activity. This activity would rebuild the application state and re-launch the correct activity.
You're seeing this because you app may be killed by the OS on exit. You never know for sure so if you want true persistence of usage, ie go back to the last activity no matter what, you need to write your state to a persistent store.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
// Activity was brought to front and not created,
// Thus finishing this will get us to the last viewed activity
finish();
return;
}
// Regular activity creation code...
}
I solve the problem using the following activity stack in my application:
LaunchActivity -> MainActivtiy -> SomeSubActivtiy
LaunchActivtiy only verifies some parameters and launches MainActivtiy. It turned out, that MainActivity must be launched with
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
That combination of flags on MainActivity gives desired behaviour.
Oh, I think I've found the answer.
Because I was launching the app by using IntelliJ, it seems it launches the application in a different way than a user, clicking a home screen widget, would launch. It's explained in the answer to another SO question:
This is due to the intents being used to start the app being different. Eclipse starts an app using an intent with no action and no category. The Launcher starts an app using an intent with android.intent.action.MAIN action and android.intent.category.LAUNCHER category. The installer starts an app with the android.intent.action.MAIN action and no category.
Ref: App always starts fresh from root activity instead of resuming background state (Known Bug)
So I've manually killed the application in the phone, and relaunched it again from the home screen widget. Then opened the GameActivity, and pressed HOME. Now, when relaunching it the GameActivity is still visible and keeping its UI state as it was when I left it.
And I guess that the reason why a new instance of the activity was created when pressing the shortcut before was due to a different Intent being used for starting the activity.
I would highly recommend using isTaskRoot to check whether the activity should be finished instead of the FLAG_ACTIVITY_BROUGHT_TO_FRONT flag.
I liked Sachin's answer, but sometimes it gave me false-positives and I would finish the activity when I shouldn't. The reliable way I found to reproduce such a false positive is:
I started looking for ways to inspect my task's activity backstack and found answers using ActivityManager. This seemed like it could work, but this answer pointed out the existence of isTaskRoot, which is a simple, elegant way of detecting this which doesn't give false positives, doesn't require a special permission and doesn't use methods that docuemtation says are intended for debugging and task management apps and which are unsupported for this type of use.