Reputation: 7718
There are so many questions on SO related to this, but no such direct questions I could find.
My app has a main activity M, and a sub activity S.
M launchMode
is singleTask
because I only ever want one instance running and I want S to exist in the same task as M.
S launchMode
is standard
, because it can have many instances.
In S, there is an Up button which must always take the user to M.
There are two types of task stack (with S on top):
If the user presses Up in S, then the stack should become:
M (where M should be in the same state the user left it)
If the user presses Up in S, then the stack should become:
M (a new instance)
--
So how to construct the Intent
for the Up button...
In the first case, FLAG_ACTIVITY_CLEAR_TOP
should do the trick, but if we apply this to the second case then the user is dumped back in Home.
In the second case, FLAG_ACTIVITY_CLEAR_TASK
will do the trick, but if we apply this to the first case, we discover that M is finished and restarted.
One might also be tempted to try FLAG_ACTIVITY_NEW_TASK
, but then we find hitting Back from M will take the user to the screen where he/she hit Up.
Side note: how is this possible when M is singleTask
and the activities all have the same (default) task affinity?
So how to correctly construct the Up Intent
in this case?
Upvotes: 0
Views: 799
Reputation: 95618
You cannot construct an UP Intent
that will do what you want. Those things are mutually exclusive. What you could do is the following:
Change launch mode of M
to singleTop
In M.onCreate()
, check if M
is at the root of the task by using isTaskRoot()
. If it isn't the task root, have M
restart itself and clear the task as follows:
Intent relaunch = new Intent(this, M.class);
relauch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(relaunch);
In your UP Intent
, add the following flags: Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
.
This will ensure that if an instance of M
already exists in the task, it will clear everything on top of that instance and call onNewIntent()
on the existing instance.
If there isn't an existing instance of M
in the task, it will launch a new instance on top of the stack. This instance will recognize that it isn't the root activity and it will clear the task and relaunch itself.
Note: This will only work on Android 3.0 and above (API 11 or higher).
Upvotes: 1
Reputation: 7718
Here is a workaround/hack using a (Lollipop) deprecated API:
ActivityManager am = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
if (M_CLASS_NAME.equals(am.getRunningTasks(1).get(0).baseActivity.getClassName()) {
// we should be able to just clear top - because M is already running
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
else {
// okay to assume M is not running (because it is always root of task)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
Upvotes: 0