Android: Launch mode 'single instance' - android

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

Related

task and backstack on android

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.

How do child activities of a singleTask activity (Activity A) behave when (A) is activated from another Task

I have to be honest this is a question which is at present academic but I have searched extensively and cannot find anyone who describes the answer. It even caused me to have an awful night's sleep last night as it manifested itself in me dreaming about continually trying to find a white puppy but I was always unable to find the puppy. So you see, this is both technically and mentally a pretty serious issue.
So,
Let's say I have a Task stack of 3 activities, A, B, C. A has launch mode "singleTask", and let's make activities B and C launch mode "standard".
So, Task 1 is
A -> B -> C
Let's say I have a second Task which is composed of just 2 activities, X (the root activity with launch mode "standard") and a 2nd activity which is actually Activity A.
So, Task 2 is
X -> A
**Question :
When activity X invokes activity A (which is defined launch mode "singleTask", what happens to the children of activity A on Task stack 1 (ie B and C) ???
When I invoke activity A, from activity X, do I end up with back stack :
X -> A -> B -> C (ie activity C becomes displayed)
Or
X -> A (ie the previous children of Task A are removed from the front of the back stack)
Also, regardless of the answer above, if I were to "BACK" key all the way back through the stack for Task 2, what happens to the original Task 1's stack. Has it now become gobbled up by Task 2 and so no longer exists ?
I want to go for a big run today so the thought of another night searching for the white puppy is rather depressing.
Any response or a link would help.
The example given on the Android Dev section covers how ancestor activities of the "singleTask" activity are "merged" into the back stack of the Task which invokes the "singleTask" activity but unfortunately it does not describe what would happen to the children of the "singleTask" activity.
Many thanks in advance ladies and gents.
Paul.
**Question : When activity X invokes activity A (which is defined launch mode "singleTask", what happens to the children of activity A on Task stack 1 (ie B and C) ??? When I invoke activity A, from activity X, do I end up with back stack : X -> A -> B -> C (ie activity C becomes displayed)
Or X -> A (ie the previous children of Task A are removed from the
front of the back stack)
Neither would happen. Tasks are not mixed up, a activity may move to a task having same affinity.
So there would be two tasks now, Task 1 would have only activity A, and Task 2 would have only activity X. Activities B and C would be cleared from the Task 1.
Although, as discussed at the following links
1. Android: bug in launchMode=“singleTask”? -> activity stack not preserved,
2. Making activity singleTask destroys stack after returning? and
3. Issue 11160: Behaviour of launchMode=“singleTask” not as described,
if there is a bug then the Task 1 should has just brought to foreground with activities B and C.
if I were to "BACK" key all the way back through the stack for Task 2, what happens to the original Task 1's stack. Has it now become gobbled up by Task 2 and so no longer exists ?
So now the "Back" key behavior would be according to the new tasks, and as stated at Tasks and Back Stack
When the user presses the BACK button, the current activity is popped
from the top of the stack (the activity is destroyed) and the previous
activity resumes (the previous state of its UI is restored).
Activities in the stack are never rearranged, only pushed and popped
from the stack—pushed onto the stack when started by the current
activity and popped off when the user leaves it using the BACK button.
As such, the back stack operates as a "last in, first out" object
structure.
Hope, it helps.

Android - finish activity and exit app

I have an application which consists 3 activities - lets call them A, B & C.
From activity A You can get to activity B, from B to C and from C to A (By pressing the back button).
On activity A I have an exit button (I know it`s not recomandded on android, but a lot of users are asking for it, so I decided to add it).
Anyway the problem is that: activity B has a timer, when the timer is finished it starts an intent that starts activiy C and calls finish() on activity B.
When the user then press back on activity C he gets to activty A - and then when he presses the exit button (this button only preforms finish()), it pops up activity B again. How can I prevent it from happen?
Thanks!
Idea: set a isFinished field in your Application to true and call finish(). All activities check if isFinished in their onResume() and if true they finish().
I'm not sure I understand how you end up at A when going back from C. Shouldn't it go back to B (logically, I mean. I know you want it to go to A)? In fact, that seems to kind of be what's happening. B is getting relaunched, but A appears on top of it, so that when you finish A, B (which was under it) is now shown.
It sounds like you don't want B to be part of the history stack, so maybe when you launch B, you should launch it with the no history flag.
You activity b is not finished thats what i can figure out it is still in running state so when all other actitivties are finished it shows up please chekc if it is finished or not

How to keep a single activity instance but be able to update the view?

In my situation, there is one case in which I need to make sure the activity only runs one at a time.
I found if I set the LauchMode of the activity, I can reach the single instance aim, but it won't update the view of the activity.
This activity is launched by startActivityForResult, and we send the URI with the intent to the activity.
Let's discuss with this certain case:
gallery - lauch this activity with imageA.
camera - lauch this activity with imageB.
My request is not to destroy the old activity, but the activity that just received the new intent infomation should refresh the view.
I found a new method, onNewIntent.
This method can refresh the intent before resume. I will try it.
You can have an Activity with a manifest attribute of singleInstance.
As soon as the activity is relaunched , onResume gets called. You can update the view with the new image and invalidate the older View.
<activity ..
android:launchMode= "singleInstance" />
In your manifest, use android:launchMode="singleTask" instead of android:launchMode="singleInstance". Using singleInstance only returns to the existing instance if it is at the top of the stack. singleTask, on the other hand, return to the existing instance of the activity, as it is always at the root of the task.
Then, when your instance is launched, override onNewIntent to update your UI according to the new intent.
Refer to the Andorid documentation for details.
Be careful when using android:launchMode="singleInstance" in multiple activities application.
Here is my test on Pixel 4XL (Android 10)
Example, we have 3 activities (without declare taskAffinity)
A (entry activity)
B (start from A)
C (singleInstance, start from B)
If we start A->B->C. Now A,B in a task and C in a different task.
From C, press back -> will see B, press back -> will see A, press back -> app close. Everything working efine.
However, if we start A->B->C then press Home -> app go to to background.
Now there is 2 situations
User open app again from Recent app.
User will see C screen. Press back -> app will close (don't go to B)
User open app again by click on app icon
User will see B screen. Press back -> will see A, press back -> app will close (don't go to C)
The behaviour after open application is different between both case. But in both case, the application is always available in Recent app and you never able to remove application from Recent app (after remove it will appear again). Only able to remove it by Force stop in Setting.
If you run adb shell dumpsys activity activities, you will see that activities still exist in Stack, but you can not go back to it.
Another case
If we start A->B->C->A. Now A,B,A in a task and C in a different task (A is current visible to user).
From A, press back -> will see B (not C), press back-> will see A, press back -> will see C, press back -> app will close. (at least here we can go back to C)
Now if, we start A->B->C->A then press Home. In both case, user open app again by Recent or click on app icon, user will see A screen. Press back -> will see B, press back -> will see A, press back -> app will close (never see C screen)
Another note
The above example, although application run on 2 tasks but in Recent apps, it only show 1 task.
If you set the taskAffinity, in the Recent apps, you will see 2 tasks. In that case, you can choose the task which contain activity that you want to display but when you press back, it just go back to the activity in same task or close app (not able to go back to activity in another task).
Also, if you click on app icon to open app again, we have the same behavior like above demo.
I think singleTask and singleTop is less complex than singleInstance, so if it is enough for solve your problem, consider to use them instead of singleInstance

'Back stack's basic

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).

Categories

Resources