I've read many answer that sound similar to my problem but simply adding android:alwaysRetainTaskState="true" or using launchMode="singleTop" to the Activity are not the answer.
Edit:
After the most recent launch of this app, we find that this behaviour has begun to occur on all devices after the first restart. Which seems crazy to me but looking through the restart process, I can't actually find what's going wrong.
asked Oct 23, 2013 at 15:24 25.8k 27 27 gold badges 125 125 silver badges 188 188 bronze badgesThis may seem like a trivial question to ask, but did you set "Don't keep activities" to true in your develop options for the Xoom?
Commented Oct 23, 2013 at 15:43Nope (I wish! :)) - I've logged the lifecycle of each Activity and the Activities in the background as still available (They're stopped - not destroyed). The OS seems to call finish() on them in instances where it begins the first Activity again instead of resuming them.
Commented Oct 23, 2013 at 15:45If you have pressed the home button and then click the launcher icon the resume behaviour is the default for android as you are probably aware. However if you press the back button to return to the home screen most phones will finish() the app. Is it possible whatever method you are using to exit the app is different on the different devices? Could you log out the onKeyUpEvent to check that some aren't handling the hard/sof tkeys strangely?
Commented Jan 27, 2014 at 21:02Nope - I'm sure of the problem as stated above. Using home to put the app in the background (not back, which you're right would finish() the Activity). It's possible on the Xoom to resume the app from the Task List (just not from the Launcher) so the backstack has definitely not been killed.
Commented Jan 28, 2014 at 15:31Answer with the bounty is the way to fix the problem described in the question. Marked my own answer as "correct" because although sometimes the problem is caused by an app bug in the launcher (as noted in his answer) my particular problem was caused by Task switching. The solution to both problem is fixed by his solution.
Commented Nov 6, 2014 at 15:28The behavior you are experiencing is caused by an issue that exists in some Android launchers since API 1. You can find details about the bug as well as possible solutions here: https://code.google.com/p/android/issues/detail?id=2373.
It's a relatively common issue on Samsung devices as well as other manufacturers that use a custom launcher/skin. I haven't seen the issue occur on a stock Android launcher.
Basically, the app is not actually restarting completely, but your launch Activity is being started and added to the top of the Activity stack when the app is being resumed by the launcher. You can confirm this is the case by clicking the back button when you resume the app and are shown the launch Activity. You should then be brought to the Activity that you expected to be shown when you resumed the app.
The workaround I chose to implement to resolve this issue is to check for the Intent.CATEGORY_LAUNCHER category and Intent.ACTION_MAIN action in the intent that starts the initial Activity. If those two flags are present and the Activity is not at the root of the task (meaning the app was already running), then I call finish() on the initial Activity. That exact solution may not work for you, but something similar should.
Here is what I do in onCreate() of the initial/launch Activity:
if (!isTaskRoot() && getIntent().hasCategory(Intent.CATEGORY_LAUNCHER) && getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN))answered Apr 22, 2014 at 12:51 11.5k 6 6 gold badges 36 36 silver badges 41 41 bronze badges Can you explain isTaskRoot() ? Commented Apr 23, 2014 at 8:56
Implemented this solution and it definitely helps. Also used this in conjunction with 'Intent resumeIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); resumeIntent.setAction(Intent.ACTION_MAIN); resumeIntent.addCategory(Intent.CATEGORY_LAUNCHER); context.startActivity(resumeIntent);' code to resume the current task and then build upon it from static context. Very very useful.
Commented May 1, 2014 at 11:40So far this works for me with no adverse side effects so far. Based on the logical assumptions, I see no reason why it isn't valid.
Commented Aug 13, 2014 at 5:56I was confronted with the same issue on a Nexus 4.Tried this and it definitely works. Thank you very much for the answer.
Commented Oct 14, 2014 at 17:04It can be null only in 2 cases that are almost impossible here, just added a suggestion to prevent event them. stackoverflow.com/questions/37856407/…
Commented Mar 7, 2017 at 9:06This question is still relevant in 2016. Today a QA tester reported an app of mine restarting rather than resuming from the stock launcher in Android M.
In reality, the system was adding the launched activity to the current task-stack, but it appeared to the user as if a restart had occurred and they'd lost their work. The sequence was:
Note: this problem does not manifest for debug APK's deployed via ADB, only in APKs downloaded from the Play Store or side-loaded. In the latter cases, the launch intent from step 5 contained the flag Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT , but not in the debug cases. The problem goes away once the the app has been cold-started from the launcher. My suspicion is the Task is seeded with a malformed (more accurately, non-standard) Intent that prevents the correct launch behavior until the task is cleared entirely.
I tried various activity launch modes, but those settings deviate too much from standard behavior the user would expect: resuming the task at activity B. See the following definition of expected behavior in the guide to Tasks and Back Stack, at the bottom of the page under 'Starting a Task':
An intent filter of this kind causes an icon and label for the activity to be displayed in the application launcher, giving users a way to launch the activity and to return to the task that it creates any time after it has been launched.
I found this answer to be relevant and inserted the following into the 'onCreate' method of my root activity (A) so that it resumes appropriately when the user opens the application.
/** * Ensure the application resumes whatever task the user was performing the last time * they opened the app from the launcher. It would be preferable to configure this * behavior in AndroidMananifest.xml activity settings, but those settings cause drastic * undesirable changes to the way the app opens: singleTask closes ALL other activities * in the task every time and alwaysRetainTaskState doesn't cover this case, incredibly. * * The problem happens when the user first installs and opens the app from * the play store or sideloaded apk (not via ADB). On this first run, if the user opens * activity B from activity A, presses 'home' and then navigates back to the app via the * launcher, they'd expect to see activity B. Instead they're shown activity A. * * The best solution is to close this activity if it isn't the task root. * */ if (!isTaskRoot())
UPDATE: moved this solution away from parsing intent flags to querying if the activity is at the root of the task directly. Intent flags are difficult to predict and test with all the different ways there are to open a MAIN activity (Launch from home, launch from 'up' button, launch from Play Store, etc.)
1 1 1 silver badge answered Jul 12, 2016 at 20:01 Rich Ehmer Rich Ehmer 2,774 24 24 silver badges 18 18 bronze badges"The problem goes away once the the app has been cold-started from the launcher." This is the weirdest part and I observed it too--killing the app after the first launch, it starts behaving normally again. Such an odd bug. Thanks for analyzing it so throughly and for the solution.
Commented Dec 13, 2016 at 19:04Note: you can get the issue to reproduce again after initially clearing it (by "cold-starting" as you described it) by using "Open" from the app's Google Play page, even if you installed the APK it via Android Studio. I found this very useful for verifying the fix worked.
Commented Dec 13, 2016 at 19:11 Nice explanation ! Commented Feb 7, 2017 at 9:37 Thanks for this explanation :) Commented Apr 25, 2017 at 15:30 This happens with a lot of the apps. Google Photos being a major one that I tested. Commented Sep 22, 2017 at 8:16Aha! (tldr; See the statements in bold at the bottom)
I've found the problem. I think.
So, I'll start off with a supposition. When you press the launcher, it either starts the default Activity or, if a Task started by a previous launch is open, it brings it to the front. Put another way - If at any stage in your navigation you create a new Task and finish the old one, the launcher will now no longer resume your app.
If that supposition is true, I'm pretty sure that should be a bug, given that each Task is in the same process and is just as valid a resume candidate as the first one created?
My problem then, was fixed by removing these flags from a couple of Intents :
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
While it's quite obvious the FLAG_ACTIVITY_NEW_TASK creates a new Task , I didn't appreciate that the above supposition was in effect. I did consider this a culprit and removed it to test and I was still having a problem so I dismissed it. However, I still had the below conditions:
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
My splash screen was starting the "main" Activity in my app using the above flag. Afterall, If I had "restart" my app and the Activity was still running, I would much rather preserve it's state information.
You'll notice in the documentation it makes no mention of starting a new Task :
If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.
For example, consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.
The currently running instance of activity B in the above example will either receive the new intent you are starting here in its onNewIntent() method, or be itself finished and restarted with the new intent. If it has declared its launch mode to be "multiple" (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance's onNewIntent().
This launch mode can also be used to good effect in conjunction with FLAG_ACTIVITY_NEW_TASK: if used to start the root activity of a task, it will bring any currently running instance of that task to the foreground, and then clear it to its root state. This is especially useful, for example, when launching an activity from the notification manager.
So, I had the situation as described below:
At this stage the second FLAG_ACTIVITY_CLEAR_TOP flag is restarting B which is in the task stack. I'm assuming this must destroy the Task and start a new one, causing my problem, which is a very difficult situation to spot if you ask me!
So, if all of my supposition are correct: