In my application there is an activity started using the FLAG_ACTIVITY_SINGLE_TOP and FLAG_ACTIVITY_CLEAR_TOP flags because I want to make sure that only one instance of that activity is at the top of the stack and all activities on top of the old instance are closed. So far so good.
Next I wanted to test if the activity restores correctly after being created more than once and successively destroyed. I take care to manually set the intent using Activity.setIntent()
when Activity.onNewIntent()
is called so that the most recent intent is returned by Activity.getIntent()
. In order to test that I activated the "Don't keep activities" option in the developer options, but the intent returned by Activity.getIntent()
when the activity is re-created is the very first intent that created it and not the most recent one.
This happens on JB and ICS, I haven't tested it on older versions. Am I doing something wrong or did I misunderstand something in the docs?
If you kill your app while it is in the foreground, this is not the same as when Android kills your app (which it will only do when your app is in the background). If you kill and then restart the app, it is like starting it all over again from scratch. There is no "restore" going on here. If you add logging to onCreate()
you should see that after you kill and restart your app, the Bundle
that is passed to onCreate()
is null.
Unfortunately it is pretty difficult to simulate what happens when Android kills your app.
EDIT: Added more stuff after OP's comment
Here's a concrete example for discussion purposes. First without the developer option "Don't keep activities":
ActivityA
is the root activity
- We start
ActivityA
ActivityA.onCreate()
is called
ActivityA
now starts ActivityB
ActivityB.onCreate()
is called (The activity stack now contains ActivityA
->ActivityB
)
ActivityB
starts ActivityA
with FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP
and an extra "foo"
ActivityA.onNewIntent()
gets called with the Intent
containing FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP
and an extra "foo"
ActivityB.onDestroy()
is called since the activity stack was cleared back to ActivityA
Now, let's do the exact same thing but enable the developer option "Don't keep activities" (I've highlighted in bold the stuff that is different from the previous scenario):
ActivityA
is the root activity
- We start
ActivityA
ActivityA.onCreate()
is called
ActivityA
now starts ActivityB
ActivityB.onCreate()
is called (The activity stack now contains ActivityA
->ActivityB
)
- Because
ActivityA
has stopped, Android destroys it and calls ActivityA.onDestroy()
- Note: The activity stack still contains
ActivityA
->ActivityB
, even though there is no instance of ActivityA
at the moment. Android remembers all the state
ActivityB
starts ActivityA
with FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP
and an extra "foo"
- Since Android has no instance of
ActivityA
to reactivate, it needs to create one, so it does and then...
ActivityA.onCreate()
is called with the same Intent
that it was called with when the original instance of ActivityA
was created (ie: LAUNCH intent with no flags and no extras)
ActivityA.onNewIntent()
gets called with the Intent
containing FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP
and an extra "foo"
ActivityB.onDestroy()
is called since the activity stack was cleared back to ActivityA
The important thing to note here is that Android always calls onCreate()
whenever it creates an activity instance. Think of it like the constructor of an Activity
. If Android has to recreate an instance of an Activity
because the process was killed or the activity was destroyed, then it will instantiate a new object, then call onCreate()
and then (if necessary) it will call onNewIntent()
.
When you call setIntent()
this doesn't actually change the Intent
that Android saves and restores. That only changes the in-memory Intent
that will be returned from a call to getIntent()
.
I hope this is clearer now. If not, please let me know.
Not sure if you've found a solution to this or not, but overriding the onNewIntent(Intent theNewIntent) method for the target activity & calling setIntent(theNewIntent) solved it for me.
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
/*
* This overrides the original intent.
*/
setIntent(intent);
}