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.
Related
As per the documentation of FLAG_ACTIVITY_MULTIPLE_TASK:
This flag is used to create a new task and launch an activity into it.
This flag is always paired with either FLAG_ACTIVITY_NEW_DOCUMENT or FLAG_ACTIVITY_NEW_TASK. In both cases these flags alone would search through existing tasks for ones matching this Intent.This flag is ignored if one of FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_NEW_DOCUMENT is not also set.
When paired with FLAG_ACTIVITY_MULTIPLE_TASK both of these behaviours are modified to skip the search for a matching task and unconditionally start a new task. When used with FLAG_ACTIVITY_NEW_TASK, a new task is always started to host the Activity for the Intent, regardless of whether there is already an existing task running the same thing.
Because the default system does not include graphical task management, you should not use this flag unless you provide some way for a user to return back to the tasks you have launched. See FLAG_ACTIVITY_NEW_DOCUMENT for details of this flag's use for creating new document tasks.
So this means that if I have an activity 1 which opens activity 2 with both of these flags, the 2 activities are opened in different stacks and are thus available as different tasks in recent.
However my question is to understand the behaviour of back button in this scenario.
ideally when activities are launched without any flags, pressing back on them destroys the activity and it is removed from the backstack. if there are no activities, the system exits the app but keeps the backstack with the last activity.
however in this case when i press back, 2 different beaviors are observed:
(Scenario: An app that launches Activity1 which launches Activity2 which launches Activity3 via startActivity(Intent(...).also{it.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_MULTIPLE_TASK}) )
if i just press back on Activity 3 , i move to Activity 2 . similarly when i press back on Activity 2, i move to Activity 1. and finally when i press back on Activity 1, i exit the app . however, i can see all the activities remain in recents and available to be opened. when i open any of them and press back, then this time, i just get exited from the app into homescreen. video sample
if i press recents on any of the activities while traversing forward, the back-press stops working, and instead i get exited from any of the activity in recents. video sample
So :
why is this behaviour?
Can we assume that if there is just 1 activity in a back-stack, it will show up in recents and not get destroyed, unless the user explicitly clears it from the recents?
Why Activities show a weak link to the caller activity in 1st case and going back to the parent back-stack when press back in 1st scenario?
I want to prevent user from leaving my app. I am trying to achieve this through home launcher activity/application and I don't understand android's behaviour. Pressing HOME first time always creates new activity in new task instead of moving the existing one to the foreground. When pressing HOME second time etc, nothing happens. See example:
I have a Login activity (A) and Settings activity (B). B is opened from A. A is set to be a launcher (LAUNCHER, DEFAULT, HOME categories).
A opens B
task T1: A -> B
HOME
another A is created into a new task (why?):
T1: A -> B
T2: A
A opens B (task T2)
T1: A -> B
T2: A -> B
HOME
nothing happens, why?
I get the same behaviour when A's launchMode is either singleTop, singleTask or standard. With singleInstance there is only one A, but the B gets alone in T1 and I don't want that.
Why there is always a new task created? All intents flags have always the FLAG_ACTIVITY_NEW_TASK flag set. Why does android do that?
Is it the same behaviour as posted here or here? I can't use that solution because android creates a new task so A will always be the root. (or how can I check that this is a second instance?)
I can't use singleInstance as posted here, because I don't want B to be alone (if A is visible, it is also the only activity and task (login purposes)). I tried to remove all other tasks through ActivityManager but getAppTasks() is for SDK >= 21, my min is 16.
I can't even use this solution because I never get intent with FLAG_ACTIVITY_BROUGHT_TO_FRONT flag. There is always FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
I've tried a lot of combinations with launchMode, clearTaskOnLaunch, noHistory, ... but nothing successful - always new task.
Any idea how to solve this? Running on Lollipop. Thank you.
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.
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.
I read the developers guide on android.com about Task and back stacks where it says:
Suppose, for example, that the current task (Task A) has three
activities in its stack—two under the current activity. The user
presses the HOME key, then starts a new application from the
application launcher. When the Home screen appears, Task A goes into
the background. When the new application starts, the system starts a
task for that application (Task B) with its own stack of activities.
After interacting with that application, the user returns Home again
and selects the application that originally started Task A. Now, Task
A comes to the foreground—all three activities in its stack are intact
and the activity at the top of the stack resumes.
It seems like every Task creates it own stack (back stack). Is my assumption is real or there's only one stack, usually a compiler has, like C?
The back stack can cross Task boundaries. When the launchmode for an activity is set to singleTask, the activity will be created in a new task.
Suppose activity B has launchmode=singleTask in the XML file. When activity A launches activity B, the latter will be in its own task. However, pressing the back key will bring the user back to activity A. So A and B are in the same back stack, but are in different tasks.
See the discussion of launchmode in the page http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html.
disclaimer: I have not verified if the documentation is correct.
I'd say that what they say is true! Every Task creates it own stack (back stack).