My Android application is being restarted when using the launcher to launch it after I have used the app store to launch it (and visa versa). Is there any way to prevent this?
By restarted I mean that the activity stack is lost. This is important as our users are setting up and returning to an activity in the app intermittently over the course of an hour or so. After first install, they will likely have installed and opened the app from the app store, set themselves up and then backgrounded the app. Later they are likely to open the app from the launcher and lose all their state!
The problem is further compounded as we start a foreground service along with the set-up activity. Clicking the services notification should bring the user back to the set-up activity but, as with the launcher, if the user originally opened the app from the Play store, they again lose all their state!
Reproducing the problem
I've made a sample application here:
https://github.com/samskiter/LaunchTest
Note: it uses the BBC weather application package Id in order to allow you to quickly open from the app store (the "Open" button will be shown on the BBC weather application if this app is installed).
Steps are as follows:
Uninstall the BBC weather app if you have it
Install the LaunchTest app
Close the LaunchTest app from recents
Open the LaunchTest app from the BBC weather app page on the Play Store
Click the button to navigate to the Second activity
Background the application (press home)
Open the LaunchTest application from the app launcher
The state is lost! you are back at the First (root) activity
What I've tried
Using singleTask launch mode hasn't helped - it causes the app to be relaunched even if you use the launcher every time.
I've tried alwaysRetainTaskState - I don't really expect this to work as this only really affects things over about a 30 minute wait.
What I think is going on
There is no mechanism in the activity manager / intent system to open a running app in it's current state. Instead, I think the UID of the launching application is taken into account. If it is different then the Intent.FLAG_ACTIVITY_NEW_TASK flag is forced and so created a new task and dropping all my users' lovely state.
Inspecting Google Maps
Google maps has a very similar interaction model to our application: a setup UI, followed by an ongoing process the user is going through for a long period of time (navigation) with a paired, foreground service (the navigation service you can see in your notification bar). BUT GMaps doesn't suffer from this problem. I think this is because it uses only a single activity for all of it's interface and uses singleTask. So now, when you tap on the launcher after originally launching from the play store, the task can be reused.
In my opinion this exposes a hole in the android intent/activity management system. The whole point of the savedInstanceState/activity lifecycle is to prevent dropping state, but here we have a way to dump everything. My current best solution is to detect app restarts by the fact the service is running and try to get the user back to where they were, which is more than a little tricky.
If someone knows a way I can prevent my state being dropped on the floor when reopening from the app launcher after opening from the store, I would really appreciate it.
This is more like a workaround to your problem, but it seems that there may be no real solution.
My first thought was - since the whole setup will take a while anyway - why don't you just save some kind of bookmark ('firstLaunch') to Preferences, post a (delayed?) notification and finish the app, so that the user has to open it again by tapping on the launcher icon. Only then you start the real setup, so you will not lose information due to the installer vs launcher problem.
But the problem seems to have been around for some time and the following SO-posts may help:
Re-launch of Activity on Home button, but…only the first time
After tap on app icon,launcher create a new instance of root activity again & again
Hope this helps!
Related
Simple put: I want the app to relaunch (yes, from the launch activity, like if the user just tapped the icon button) every time Android kills my task because of lacking resources reasons.
The reason is that instead of managing everything that could possible go wrong after the app came back "from the dead", like NPEs, I want to start all over from the beginning.
I've searched for a "good practice" solution, but nothing came across.
Any ideas?
EDIT: I don't want to force the app back to foreground. However, if the user do it, I mean he brings it back to fore by his own free will, if Android killed my app because of resources purposes, I want the app to relaunch.
Sorry for not being clear previously.
Bringing your app to the foreground when it hasn't been explicitly opened by the user is considered a bad practice and discouraged. In fact, it won't be allowed in Android Q, except in a few cases:
Android Q places restrictions on when apps can start activities. This
behavior change helps minimize interruptions for the user and keeps
the user more in control of what's shown on their screen. In
particular, apps running on Android Q can start activities only when
one or more of the following conditions are met:
The app has a visible window, such as an activity in the foreground.
A different app that's in the foreground sends a PendingIntent belonging to the app. Examples include a Custom Tabs provider sending
a menu item pending intent.
The system sends a PendingIntent that belongs to the app, such as tapping on a notification. Only pending intents where the app is
expected to launch a UI are exempt.
The system sends a broadcast, such as SECRET_CODE_ACTION, to the app. Only specific broadcasts where the app is expected the launch a
UI are exempt.
Therefore, I would definitely recommend you to discard the idea.
I have multiple activities in my app and a specific problem in which after my app is killed by the system, upon reopening the app (icon or from the overview) it starts loading my launcher activity with the splash screen instead of loading the last activity that the app was using.
My launcher activity is essentially a form of a login screen which should be used only the first time the app is opened, but instead it is reopened every time the app is killed by the system and app reopened by the user.
I am inexperienced and do not know if this is the default behavior of Android or a bug, I have searched through stack overflow but could not find a conclusive answer.
Coincidentally this well known long standing Android bug has appeared. (https://issuetracker.google.com/issues/36941942)
I do not know if the two problems might coincide, and I cannot be sure when the longstanding bug has first appeared because previously I was testing through Instant Run which does not result in the bug, but am now forced to test through play because it does result in the bug.
Thanks.
I am inexperienced and do not know if this is the default behavior of Android or a bug
This is the default behavior of Android, if there is no current task associated with your app. That includes:
User swiping the task off of the overview screen
You terminating the process and task from inside Android Studio
All the time if the user has been out of the app for 30+ minutes
User using Force Stop on your app in Settings
And probably some other scenarios that I'm not thinking of right now
My launcher activity is essentially a form of a login screen which should be used only the first time the app is opened
I recommend that your launcher <intent-filter> be on your primary activity in the app. If that activity determines that the user has not logged in, it can do something to authenticate the user (display a fragment, start an activity, etc.).
I'm working on large project, so there is some logic for saving application state, and then opening correct activity(fragment) when it comes from background.
But anyway, I've found that if user navigates through my app and then minimize it - android opens it from background in different ways in following cases:
User taps on app icon (behavior: user see home activity, doesn't matter where he was, when application was minimized)
User select app from android "recent apps" (behavior: user see exactly what he saw, when the application was minimized)
So, what is the difference between launching application from background by this two ways? I always thought, that it is the same mechanism, but, obviously, I was wrong.
Thanks for any answers
You should pay atention on the folowing docs Activity and Tasks. In short words: if user start app from recents you will receive onRestart before onStart (without onCreate it means that your app was just "suspended"). You able to save screen state using onSaveInstanceState(). But in general starting from icon and from recents - different application behaviors and you should provide proper code for this ways.
UPD
As described below root cause of unexpected behaviour was additional lunchmode attribute.
From what I experience as an Android user, both are same.
The difference we usually see is how we close the app
Press back button until app close / finish()
On this state no matter how we open the apps it will go to the main screen
Press Home button
On this state depend on the app. If the app does not handle any Activity the app will same with the first state. But if the app handle something like when onPause() the Activity then finish() the apps, then whatever you open with app icon or recent apps will provide the same result.
Correct me if I am wrong
In iphone when we exit app and start app again by clicking launcher icon the app start from screen which was open last time before exiting app.
We can achieve same in android when we exit app using center or home button on android phone. In android app if app is exited by pressing home button and started again by clicking on launcher icon the app start from activity which was open last time before exiting app.
Is that functionality similar to iphone in terms of keeping app in memory longer? Will that work in android all time because I think android system will remove app from memory after sometime or will it remain in memory longer? Can I depend on this functionality in android and expect it to work all time.
I have a project in android which client has asked me to have iphone like functionality if we exit app and start app again it should open from screen which was opened last time before exiting. Now this is possible in android only if we use centre button. And also if user has exited using centre button and started it again, app should check for user current location and do some other operations. If app is launched and user navigate to any activity is there any way to check if app was exited using back button or centre button so that I can run code if app is exited using center button.
Thanks
We can achieve same in android when we exit app using center or home button on android phone.
The HOME button does not "exit app".
The HOME button brings the home screen to the foreground, just as the CAMERA button (where available) brings the camera application to the foreground, the CALL button (where available) brings the dialer to the foreground, tapping on a Notification may bring something else to the foreground (e.g., SMS client) based on the Notification, etc.
In android app if app is exited by pressing home button and started again by clicking on launcher icon the app start from activity which was open last time before exiting app.
No. If you tap on a launcher icon, and the app's process is still in memory, the existing app instance will be brought to the foreground, returning you to whatever activity you had been on. If you tap on a launcher icon, and the app's process had been terminated to free up RAM for other apps, you launch a fresh copy of the app and bring up whatever the ACTION_MAIN/CATEGORY_LAUNCHER activity was that the user tapped upon.
Will that work in android all time because I think android system will remove app from memory after sometime or will it remain in memory longer?
The length of time that a non-foreground app's process will be in memory is indeterminate and will be based on what is going on with the device, plus the device capabilities (e.g., how much RAM). I suggest you read more about the process lifecycle.
Now this is possible in android only if we use centre button.
It is not possible "if we use centre button" (what Android developers refer to as the HOME button). It may happen automatically, but if the app's process has been terminated, it will not happen automatically.
If app is launched and user navigate to any activity is there any way to check if app was exited using back button or centre button so that I can run code if app is exited using center button.
You should not care whether the "app was exited using back button or centre button".
You should care whether you have your data and how old that data is, refreshing it if it is stale.
Whether the user left your app via HOME, BACK, CAMERA, CALL, a Notification, the recent tasks list, an incoming phone call, by smashing their phone to bits with a rock and replacing it with an exact duplicate, or by any other means, should not matter to you.
To draw an analogy, think of a Web app. In a Web app, you care about whether you have a session cookie and whether that session is stale (e.g., to force a fresh login). Whether the page request came because the user clicked a link within the app, or clicked on a link from a third party site pointing to your app, or refreshed their page, or used a bookmark to get at another page in your app, or double-clicked on a desktop icon that brings up your app, or right-clicked on a link and opened a fresh tab, or anything else, should not matter to you.
Review the Android Activity Lifecycle at http://developer.android.com/reference/android/app/Activity.html. If you do nothing, you have no guarantee of your app starting at the same point it left off, however you have control here. You can, for example, overload the onPause() method to save your state to a file, and onResume() to restore it.
I am building an Android application in Flex 4.5 and I am testing on a Samsung Galaxy S phone.
My application uses GPS and also Google maps.
When I run the application, and I try to close it, the application keeps on running in the background. I would like the application to stop when the user presses the device's home button or when the user clicks the back button until they leave the application.
How can I make the application shut down in both the cases?
This is how Android applications are supposed to work. See here: http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
Your application's process is in either the "background" state (if the user pressed how) or "empty" state (if the user pressed back).
For starters, you can try using the Activity noHistory flag in the manifest. This will make sure an Activity is finished if navigated away from.
http://developer.android.com/guide/topics/manifest/activity-element.html#nohist