Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

App loses its ability to remember its stack when launched from another application

Now that I have researched this even more I am rewriting this to make it clearer. If you are looking for more info, there is some available in older edits.

What is happening:

(This refers to an application that has not set any launchMode settings and so is using the defaults)

  1. You launch an app from the Market or from the Installer. This launches the root/main activity of the application with the FLAG_ACTIVITY_NEW_TASK flag and no categories. Right now the applications stack is [ A ]

  2. Then you proceed to the next activity in the application. Now the stack in this task is [ A > B ]

  3. Then you press the home key and then relaunch the same application by pressing it's icon from either the home screen or the app tray.

  4. What is expected at this point is that activity B will show, since that is where you left off. However A is shown and the tasks stack is [ A > B > A ] This second instance of A is launched with the following flags: FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_RESET_IF_NEEDED, and FLAG_ACTIVITY_BROUGHT_TO_FRONT. It also has the android.intent.category.LAUNCHER category.

At this point, if you hit the back key, it will return you to B, as it was when you left it.

Looking at the documentation it seems as if FLAG_ACTIVITY_BROUGHT_TO_FRONT should only be set for activities that use the singleTask or singleTop launchModes. However, this application has not set any launchModes and is therefore using the default standard launchMode.

I assume this is not suppose to happen in this case?

I should also note, that once it gets into this weird state, then it happens everytime the app is launched from the home screen or app tray. If the task is finished (restarting the phone, force stopping the app, or hitting back all the way through the stack) will fix this issue and will no longer launch it incorrectly. It only happens if you launch the app from the installer or market and then try to launch it from the launcher.

So in summary, why is this happening? Is there a way to prevent it?

like image 860
cottonBallPaws Avatar asked Mar 15 '11 22:03

cottonBallPaws


People also ask

What is activity back stack?

These activities are arranged in a stack—the back stack—in the order in which each activity is opened. For example, an email app might have one activity to show a list of new messages. When the user selects a message, a new activity opens to view that message. This new activity is added to the back stack.

Which flags is cleared with the help of stack?

udayatom/Clear all activities in android API 11 or greater, FLAG_ACTIVITY_CLEAR_TASK and FLAG_ACTIVITY_NEW_TASK flags on Intent to clear all the activity stack.

What is Android noHistory true?

From the docs about noHistory : A value of "true" means that the activity will not leave a historical trace. It will not remain in the activity stack for the task, so the user will not be able to return to it.


1 Answers

Here is a workaround I have come up with so far. Some other workarounds I have seen involved looking at the currently running tasks. However, I really did not want to have to ask for another permission (GET_TASKS) from the user just to make a work around.

Please let me know if you see any holes in this.

In the main/root activity's onCreate method, check if the intent has the FLAG_ACTIVITY_BROUGHT_TO_FRONT set and if so, call finish(). This then pops the extra instance of A off the stack [ A > B > A ] becomes [ A > B ] and from the users perspective, it launches into the activity they were expecting.

It seems to work in all of my tests so far. My only worry is that if there is some weird case where someones launcher would always flag a launch with FLAG_ACTIVITY_BROUGHT_TO_FRONT even if the app wasn't already in a task, and therefore would completely lock them out because it would call finish() and not have anything in the stack to return to.

--

As requested in the comments here is how you can check if an intent a specific flag:

int flags = intent.getFlags();
boolean hasFlag = flags & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT == Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT;

--

Also I should note that I am still seeing this problem occur sometimes with this fix in place. It doesn't seem to be a perfect solution.

like image 112
cottonBallPaws Avatar answered Sep 18 '22 05:09

cottonBallPaws