The android document of FLAG_ACTIVITY_NEW_TASK said :
When using this flag, if a task is already running for the activity you are now starting, then a new activity will not be started; instead, the current task will simply be brought to the front of the screen with the state it was last in.
I make an demo to implement this, There are two app: A and B. A contains activity A1, B contains activity B1, B2.
I follow the step :Home Screen(Application A icon) --> A1 (FLAG_ACTIVITY_NEW_TASK to start B1)--> B1 -->B2 --> Home Screen(Application B icon)--> , as my understanding, click the application B icon from launcher to launch the Activity B1 will use the FLAG_ACTIVITY_NEW_TASK, right? So it should bring the task started before to front, but unfortunately the fact is an new activity B1 is started and the B task stack is like this : (Bottom)B1 B2 B1.
How can i let the existed task brought to front when i click the application B icon in the launcher
A and B are two different apps, Right ?
That means both will execute as a separate process and behave as separate task.
so when you set FLAG_ACTIVITY_NEW_TASK to A it will create a separate task for A and make it as a root activity or brought to front the already existing instance of A.
When B is started from launcher, according to android normal launcher behavior it will start as a separate task and B will have separate stack.
Related
I have 3 activities:
A, B , C
A has singleInstance launchMode.
A is the main activity, which launches B, B launches C, then I press the home button and open the app again.
A is opened, but when A tries to launch B, the existing stack is opened instead (returns to existing C)
Is this the expected behaviour?
If A is singleInstance, when A launches B, Android automatically adds FLAG_ACTIVITY_NEW_INSTANCE to the Intent (because A is singleInstance) and because of that it creates a new task with B at the root of the task. Then B launches C. Andriod launches C into the same task as B (this is the normal behaviour). So now you have 2 tasks: One with just A in it, and another which has B at the root, with C on top of that.
Now you go back to the task containing A. When A launches B again, Android again adds FLAG_ACTIVITY_NEW_TASK to the Intent). Then, because FLAG_ACTIVITY_NEW_TASK is set, Android looks for an existing task that has B at the root. Since it finds one, it simple brings that task to the foreground in whatever state the task was in when that task went to the background. This is the normal and expected behaviour.
NOTE: This is just one more reason NOT to use the special launch modes singleInstance and singleTask, because they have lots of nasty, undocumented, misunderstood side-effects.
I've been reading doc regarding to launch modes and there is one thing I don't understard. The doc says that singleTask activity is always the root of the stack:
In contrast, "singleTask" and "singleInstance" activities can only
begin a task. They are always at the root of the activity stack.
Moreover, the device can hold only one instance of the activity at a
time — only one such task.
But: if you look at this part of doc at Figure 4, you see that when Activity 2 starts Activity Y (puts that task to foreground), Activity Y was already on the top of the task and will be on the top of the current task, not the root.
I tried this scenario in this simulation app and when I create singleTask activity, it always creates a new task. However, if the only instance already exists, it finishes all activities above this one so the only instance can be the root (and also the only activity in the task).
How could the Activity Y become on the top of the task above the Activity X?
Is there any other reason I'm missing?
PS: I also don't really understand the difference between Task and back stack.
As usual (sigh), the documentation is wrong. In the diagram you referenced, obviously Activity Y can't be defined as singleTask and yet be the top activity in a background task containing 2 activities.
When testing scenarios with special launch modes singleTask and singleInstance, please be aware that taskAffinity plays an important role in this behaviour, as taskAffinity takes priority over special launch modes.
Regarding the difference between "task" and "back stack":
A "task" is a stack of activities that can be manipulated as a whole group.
When you launch an application (assuming that it isn't currently running), Android creates a new task which is in the foreground and contains the root activity of the application you launched.
When that activity starts new activities, these new activities are added to current task (usually, although there are exceptions to this behaviour).
When you press the HOME button, the current task is moved from the foreground to the background.
When you show the list of "recents", what is displayed is the list of recent tasks, not the list of recent activities or list of recent applications.
When you select a task from the list of recent tasks, if that task is still active (still has live activities in it), the entire task (including all of its activities) will be brought from the background to the foreground.
Tasks can also be "stacked". When an activity in the current task starts an activity in a new task, the new task is stacked on top of the current task. This only serves to control what happens when the new task completes. In the usual case, when the new task completes (all of its activities have finished), Android will return the user to the previous task (ie: the task that started the completing task).
A "back stack" usually refers to a set of activities within a task. Each task has its own stack of activities. This is used to control what happens when the current activity (the one on top of the back stack) finishes. Normally Android returns the user to the activity that is directly underneath (below) the finishing activity in the back stack.
The Android code and documentation often refer to the "root" of a task (this is the activity that was used to start the task) and the "top" or "front" of a task (this is the activity that is currently being shown).
Actually, the documentation lies :-( Here's an example:
In contrast, "singleTask" and "singleInstance" activities can only
begin a task.
This statement is usually, but not always correct. For example, let's say I have 2 activities: A and B. A is the launch activity (ie: the one with ACTION=MAIN and CATEGORY=DEFAULT) and is defined with standard launch mode. B is defined with launchMode="singleTask". I start the application and Android creates an instance of A. In A I then do:
startActivity(new Intent(this, B.class));
This will create a new instance of activity B and put it on top of A in the same task. It will not create a new task with activity B as the root. The reason is that activity A and activity B have the same taskAffinity (by default all activities of an application have the same taskAffinity), and Android will ignore the launch mode of B in this case.
The documentation also says:
Moreover, the device can hold only one instance of the activity at a
time — only one such task.
Again, taskAffinity can break this behaviour. Assume again we have A, B and C, all with the same (default) taskAffinity. A and C have standard launch mode, B has launchMode="singleTask". If A starts B, the instance of B ends up not in a new task, but in the same task as A (see above). Now B starts C. Android creates an instance of C and puts it on top of B in the same task. Now C calls:
startActivity(new Intent(this, B.class));
Android creates a new instance of B and puts this on top of C in the task. There are now 2 instances of B and neither of them is the root activity of the task! This behaviour is also due to the fact that taskAffinity trumps launch mode.
There are 2 activities: A and B
if activity A is started then it will be always on top of activity B (if B exist)
if B is started and A is in foreground then B will go right under A
if A is going in background or is closed then(if B exist) B will be shown
each activity is running in its own task
In other words is there a simple way to start an activity right under the current activity so when that close then it will be shown
what is the simplest way to do this using manifest flags preferably
Start A inside new Task stack. Read docs for Intent.
Inside onCreate of A check Intent and open B.
Now you have new stack where B is above A, however and A and B were used before.
I was going through the documentation for single instance and was trying out few samples.
In one of my sample I have three activities: A->B->C ,
where B has android:launchMode="singleInstance" in manifest. Activity A and C has default launch mode.
Scenario:
After navigating to C via A and B (i.e A->B->C), back button press from Activity C takes to Activity A (C->A), but back button press from Activity A does not quit the app, rather brings the Activity B to front, then back button press from Activity B quits the app.
Question
Why does Activity B comes to foreground when back button is pressed from Activity A?
Other scenario:
Similarliy, from Activity C if user presses device Home button, and come back the app by long home press, C stays in foreground. But back button press flow takes C-> A -> quits the app. This time Activity B does not come to foreground.
After navigating from A->B you have 2 tasks: The first one contains A, the second one contains B. B is on top and A is below that.
Now when navigating from B->C Android launches activity C into the task containing A (it cannot launch it into the task containing B because B is defined as "singleInstance", so it launches it into a task that has the same "taskAffinity", in this case the task containing A). To do that, Android brings the task containing A to the front. Now you have 2 tasks: The task containing A and C in the front, and the second one containing B below that.
Now you press the BACK key, which finishes activity C and returns to the activity below that in the task, namely A. You still have 2 tasks: The one containing A in the front, and the one containing B below that.
Now you press the BACK key again. This finishes activity A (and thereby finishes the task that held A) and brings the previous task in the task stack to the front, namely the task containing B. You now have 1 task: the task containing B.
In your other scenario, after navigating from A->B->C, you start with 2 tasks: The task containing A and C in the front, and the second one containing B below that.
Now you press the HOME button. You now say that you "come back to the app by long press". This isn't exactly correct. You can't "come back to the app". You can only "return to a task". But you've got 2 different tasks: If you do a long press you should see the 2 tasks. They probably have the same icon (unless you've provided a different icon for activity B) so you may not be able to tell them apart. If you select the task that contains A and C, then that task will be brought to the front with activity C on top. If you now press the BACK key, activity C will finish and the activity under it, activity A will be shown. If you now press the BACK key again, activity A will be finished and you will be returned to the HOME screen. The task containing B is still in the list of recent tasks, but it is no longer in the task stack under your other task because when you press the HOME button it is like going back to zero. You start all over again. You have no active tasks, so all tasks are in a row, they aren't in a stack and there is no hierarchy.
Also, in your question you use the phrase "quits the app". This also isn't quite correct. The only thing that a BACK button press does is to finish the current activity. If the current activity is the only activity in a task, it also finishes that task. However, it doesn't "quit the app". Especially in your case, since your "app" actually exists in 2 separate tasks.
Hopefully this is clear.
From the doc
"singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such 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
I have doubt with android backstack , please consider the scenario I have two activities A and B in same app ,
start with A.
from A launch B using FLAG_ACTIVITY_NEW_TASK
from B launch A using FLAG_ACTIVITY_NEW_TASK
press Back button 3 times to return to home screen.
My question is how does the backstack work with this flag , is new task created every time and previous task is pushed to background or activity is created on top of same task.
My doubt is if first one is correct then does back button really remove the activity from top of the stack and if second is correct what is the use of that flag in correct sense.
Thanks in advance.
Regards,
Rohit
First of all, launching B using FLAG_ACTIVITY_NEW_TASK will NOT create a new task unless you have explicitly set android:taskAffinity in the manifest for B. The reason for this is that, by default, all Activities in your application have the same taskAffinity and taskAffinity overrides FLAG_ACTIVITY_NEW_TASK.
If you have set the taskAffinity of A and/or B so that they are different (or both empty), then it works like this:
User launches A from homescreen. You now have one task (let's call it TaskX)
A launches B with FLAG_ACTIVITY_NEW_TASK. You now have two tasks (let's call the new task TaskY). TaskX is pushed to the background and TaskY is in the foreground.
B launches A with FLAG_ACTIVITY_NEW_TASK. You still only have two tasks. B (in TaskY) launched A which created a new instance of A and put it in TaskX because the first instance of A has the same taskAffinity as the second instance of A). This also causes TaskX to come to the foreground and TaskY to go to the background.
Press "back". The second instance of A is removed from the stack and you go back to the first instance of A in TaskX. Pressing the "back" key goes back within the current task.
Press "back". The first instance of A is removed from the stack. TaskX is now empty as it has no activities in it. The previous task (TaskY) is brought to the foreground and B is resumed.
Press "back". The instance of B is removed from the stack. TaskY is now empty and the home screen is shown.