Android Singletask or Singleinstance Launch Mode

SingleInstance of Android launchMode

This one is pretty easy: taskAffinity trumps launchMode. This means, if you launch an Activity and that Activity has the same taskAffinity as other activities within a task, the special launchModes singleTask and singleInstance are ignored.

So unfortunately, the documentation isn't 100% correct, because there are some situations where singleInstance and singleTask launch modes do NOT behave the way they are documented.

In general, you should not be using the special launch modes singleTask or singleInstance as these come with a lot of side-effects that are not obvious. You shouldn't need these special launch modes unless you are implementing a HOME-screen replacement.

Android singleTask or singleInstance launch mode?

From the Application Fundamentals page of the Android dev guide:

By default, all the activities in an
application have an affinity for each
other — that is, there's a preference
for them all to belong to the same
task.

A "singleInstance" activity stands
alone as the only activity in its
task. If it starts another activity,
that activity will be launched into a
different task regardless of its
launch mode — as if
FLAG_ACTIVITY_NEW_TASK was in the
intent. In all other respects, the
"singleInstance" mode is identical to
"singleTask".

As noted above, there's never more
than one instance of a "singleTask" or
"singleInstance" activity, so that
instance is expected to handle all new
intents. A "singleInstance" activity
is always at the top of the stack
(since it is the only activity in the
task), so it is always in position to
handle the intent. However, a
"singleTask" activity may or may not
have other activities above it in the
stack. If it does, it is not in
position to handle the intent, and the
intent is dropped. (Even though the
intent is dropped, its arrival would
have caused the task to come to the
foreground, where it would remain.)

4 Activities in a Task

Since there is never more than one instance of the Activity with either launch mode, the back button will always take you to the existing instance of the Activity in your case.

An important difference is that "singleTask" doesn't require the creation of a new task for the new Activities being launched when something is selected. Nor will it have to remove that new task on the back button each time.

Since your Activity stack does all pertain to one user "task", and it doesn't sound like you have an intricate Intent structure where singleInstance may be beneficial to always handle them, I would suggest using the singleTask launch mode.

Here is a good blog post for more info, as well as credited for the image: Android Activities and Tasks series – An introduction to Android’s UI component model

Setting launchMode= singleTask vs setting activity launchMode= singleTop

I think your definition of singleTop and singleTask is a little off. SingleTop could produce a duplicate instance. Lets use your example, League > Team > Position > Player. If there is a button in the player screen that will take you to the league screen, it will become League > Team > Position > Player > League.

Whereas singleTask guarantees that only one instance of the activity can exist.

android - Two activities with launch modes as 'singleInstance'

I'll bold the answer to your question if you don't want to read the clarification.

When using launchMode="singleInstance", there's two things to keep in mind:

  • The Activity will always be created in a new task
  • All Activities launched from this Activity will be created in a separate task

As such, an Activity with launchMode of singleInstance will always be isolated in it's own task. There won't be another Activity inside of that task.

So with your example from your question of Activities A, B, C, and D:

  • Activity A launches Activity B
  • Activity B is launchMode="singleInstance" so it's on a new task
  • Activity B launches Activity C
  • Activity C is launched in the same task as Activity A
  • Activity C launches Activity D
  • Activity D is launchMode="singleInstance" so it's on a new task

From what happened here, you have one a task that stores the launchMode="standard" Activity A and Activity C. Activity B is in it's own task. Activity D is in it's own task.

Therefore, if you choose to Back out of these Activities, you'll notice that:

  • Activity D is backed and Activity C appears
  • Activity C is backed and Activity A appears

This happens because Activity C is on the same task as Activity A.

Also, Activity D definitely won't be in the same task as Activity B because Activity B's task is meant only for Activity B due to launchMode="singleInstance".

Keep in mind that there can be any number of tasks being held in the background at once. Just that if there's too many being held or if the system requires memory, it'll start destroying these background Activities across your multiple tasks.

Understanding Android Launch modes with splash screens

There are a number of things going on here, I'll try to address these:

First off, using launchMode="singleInstance" is problematic here, because you have not declared any taskAffinity for any of your activities. So your SplashActivity and your other activities have the same (default) taskAffinity which tells Android that all these activities want to run in the same task, which conflicts with your launch mode declaration of SplashActivity. This is bad, and you shouldn't do it. If you really want to have activities running in separate tasks, you should ensure that they have different taskAffinity so as not to cause confusion.

Secondly, you wrote:

This seems to work, but there is something that I don't understand.
Why is the second Splash ignoring the Intent to launch Login
activity?.
The logic tells me that a Login #2 should've launched.

What is happening here is this: When SplashActivity calls startActivity() to launch LoginActivity, the Intent used contains FLAG_ACTIVITY_NEW_TASK set (because SplashActivity is declared with launchMode="singleInstance" so it has to launch other activities into a new task), so Android looks for an existing task that has LoginActivity as its root Activity. If it didn't find one, it would simply launch a new instance of LoginActivity into a new task. However, in this case, it finds one (this is task #2 in your diagram), so instead, it just brings that task to the foreground without launching a new instance of LoginActivity.

This is the same behaviour as what happens when you have an app running, then press the HOME button and then click the app icon for that app again. Android doesn't launch a new instance of the app's root Activity in this case, it simply looks for an existing task that has the app's launch Activity as its root Activity and brings that task to the foreground in whatever state it was in.

My suggestion for you is as follows:

  • Get rid of the use of the special launch modes singleInstance and singleTask
  • Create a new BridgeActivity which is used as a bridge between the web browser and your app. This Activity should have the <intent-filter> for the browser Intent.
  • The BridgeActivity should check if it is the root Activity in its task. If it is not, it means that it has been launched into an existing task that was brought to the foreground and it can just quietly finish() in onCreate().
  • If BridgeActivity detects that it is the root of its task, it can launch SplashActivity (make sure to set FLAG_ACTIVITY_NEW_TASK) to begin a new task (since there obviously wasn't already an existing task of your app)
  • BridgeActivity should be declared so that it doesn't end up in the task stack history or in the list of recent tasks (noHistory="true" and excludeFromRecents="true")

Difference between singleTask and singleInstance

What is unclear from the docs ?

The "singleTask" and "singleInstance" modes also differ from each
other in only one respect: A "singleTask" activity allows other
activities to be part of its task. It's always at the root of its
task, but other activities (necessarily "standard" and "singleTop"
activities) can be launched into that task. A "singleInstance"
activity, on the other hand, permits no other activities to be part of
its task. It's the only activity in the task. If it starts another
activity, that activity is assigned to a different task — as if
FLAG_ACTIVITY_NEW_TASK was in the intent.

singleTask launch mode is not working

So it seems the issue is with device. On emulator and other devices with same android version singleTask works just fine.



Related Topics



Leave a reply



Submit