I'm unable to find good documentation on an Application's long term lifecycle.
If I have the app running, hit the home button, and then click on the app's launcher icon the Application's onCreate is not called and the front Activity's onResume is called. But presumably if I wait long enough at some point clicking the launcher icon will call Application onCreate and the MAIN LAUNCHER activity is started. When does this happen?
When I go through the apps in the Recents list if I click on a really old app that I haven't used in a month the app does not return to its previous state, instead the app goes through its startup. So it seems at some point apps move from a saved state to no saved state. When does this happen?
If the app gets killed due to memory pressure presumably the savedInstanceState bundle is saved and Activity onResume is called, but does Application's onCreate get called at that point? How long is the bundle saved for?
But presumably if I wait a long enough at some point clicking the launcher icon will call Application onCreate and the MAIN LAUNCHER activity is started. When does this happen?
These are separate issues.
The Application singleton is created shortly after the process is forked, as part of spinning up a new process for you. This will be triggered when something needs your app to exist (e.g., user taps on the launcher icon) and your process does not already exist. Processes do not live forever. How long any given process remains in memory depends on a variety of environmental factors.
Whether the launcher activity resumes an existing task, or whether your task is reset, depends upon whether the task exists (i.e., did the user swipe the task off the recent-tasks list) and how long it has been since the user left the task. A task is considered "alive" for about 30 minutes, though there are manifest entries that you can use to try to adjust this a bit.
So it seems at some point apps move from a saved state to no saved state. When does this happen?
About 30 minutes (see previous paragraph).
If the app get's killed due to memory pressure
I presume that by "app get's killed" you mean "the app's process is terminated".
presumably the savedInstanceState bundle is saved and Activity onResume is called, but does Application's onCreate get called at that point?
Yes, because a new process needs to be created for you.
How long is the bundle saved for?
About 30 minutes (see above).
Each application installed on the device runs within its process.
If you enter the application for the first time, the following sequence is called:
Application.onCreate()
YourFirstActivity.onCreate() (provided that the YourFirstActivity is declared in AndroidManifest.xml)
YourFirstAcitvity.onStart()
YourFirstActivity.onResume()
If you click the Home button, the application goes to background and the following callback methods are called:
YourCurrentActivity.onPause()
YourCurrentActivity.onSaveInstanceState() - this invocation is not specified exactly but you can assume that by the onStop() method is called in most of the cases the onSaveInstanceState() should be called.
YourCurrentActivity.onStop();
While the application is in background it is not specified how long it will be there.
It is up to the System to maintain it in background.
Many applications, while your is in background, perform periodic syncs, run scheduled services or simply run in foreground when launched and for that purpose the Android OS must somehow find memory to execute all this logic. Thus, if there is a shortage in the required memory then the OS kills processes (e. g. your application).
So if you hide your application to the background and click on either the application launcher icon or return to it from Recent apps list immediately, the following sequence of callback methods are executed (assuming that you hid the app while being in YourCurrentActivity):
YourCurrentActivity.onRestart();
YourCurrentActivity.onStart();
YourCurrentActivity.onRestoreInstanceState();
YourCurrentActivity.onResume();
However, if you do not reenter the hidden application for a longer period then it is high probability that the OS has already killed your application in favour of meeting other applications requirements.
If this happens the following sequence of callback methods are called:
Application.onCreate()
YourCurrentActivity.onCreate();
YourCurrentActivity.onStart();
YourCurrentActivity.onResume();
Notice please that it is still YourCurrentActivity that you left when hiding the application to the background.
The following sequence is executed because System creates new process for your application as #CommonsWare points.
How to prevent the app from being killed by the System?
(Android - implementing startForeground for a service?)
Hope this helps somehow.
Related
I'm wondering if Android system is able to kill the activity without the entire application process while the app is minimized. From Android documentation we know that onDestroy is only called when the activity is about to be destroyed and the systems guarantees to call this method whenever it is about to kill the activity, it will not be called only in case the entire application process is killed.
So, imagine such a situation - you send the app to the background(minimize) and after some time the os starts to run low on memory and decides to kill the activity, but since the app is currently suspended and cannot execute code it is not able to call its onDestroy method althought it is guaranteed that it will be called before every activity destruction.
So, this kind of reasoning gives me a thought that while the app is in the background os is only able to kill the entire process but not some specific activities. Is my reasoning correct, or did I miss something?
That's true: while the app is in the background os is only able to kill the entire process but not some specific activities.
Your reasoning is correct.
If the user navigates away from the activity/application (e.g. by pressing the home button) then the activity is said to be in the "Stopped" state. (States being "None-existent", "Stopped", "Paused" and "Resumed"). If android get low in memory and needs to kill some processes it will target those processes whose activities are in the "Stopped" state and it kill the whole process (not the activity). Furthermore, it will not be polite when doing so and therefore, will not call the activity's onDestroy() method.
Edit following comments about the confusion of saved state on process death:
If the activiy's process is killed, the system temporarily saves a set of settings outside the activity and using these settings, it recreates the activity the next time it is launched.
For example, just before moving to the "Stopped" state the system calls onSaveInstanceState(Bundle) on an activity that is not "finished" and saves this Bundle outside the activity. The system also does remember that it killed activity's process while it was not finished. Using these two along with other settings (saved outside the activity), the system recreates the activity.
If, However, the activity is finished (e.g. user presses the back button, swipes away the activity's card from the overview window, Activity.finish() is called explicitly, etc), onSaveInstanceState() is not called and the system doesn't save any settings to recreate the activity next time it's launched. It simply creates a fresh one.
This is good news, why? Becuase if it wasn't the case, the developer would have had to stash key state properties manually outside activities and reinstate them when activities are relaunched (that would've been a nightmare)
Since there's been much confusion on this issue, in large part due to the confusing state of the official docs in the past, here's what the docs say
at present:
The system never kills an activity directly to free up memory.
Instead, it kills the process in which the activity runs, destroying
not only the activity but everything else running in the process, as
well.
This as well as real world observation yields that the answer is no.
https://developer.android.com/guide/components/activities/activity-lifecycle#asem
I've noticed an issue when I pause my app, say by pressing home, and then bring up the list of recent apps (via the square button) to resume it.
If I resume it shortly after pausing it, it works fine. But if I leave it paused for too long, i.e. a few hours or overnight, then when I touch its window to resume it, it just posts a "failed to start..." toast and removes the app from the list.
I've searched around, but haven't found any info about what would cause this or how to start debugging it.
My theory would be that is has to do with the activity lifecycle. You can find it here:
https://developer.android.com/training/basics/activity-lifecycle/starting.html
When an app is paused, the onPause() function is called, and if the app is paused, and the system needs memory for another app that is running in the foreground, it will stop, or destroy the activity. When you go back into the app, it calls the onCreate() and onStart() functions
I don't know how your app is structured, but my guess is that when the activity is stopped, it is leaving behind some kind of code that needs to reference something that is no longer there, or destroying the referenced thing itself. Then, when onStart() is called, it checks for that thing that is no longer there and crashes.
The best way to fix this is to make sure that each step of the life cycle isn't referencing anything that could possibly be non existent at the time it is called.
When the user leaves a task by pressing the Home button, the current activity is stopped and its task goes into the background. The system retains the state of every activity in the task. If the user later resumes the task by selecting the launcher icon that began the task, the task comes to the foreground and resumes the activity at the top of the stack.
If the user leaves a task for a long time, the system clears the task of all activities except the root activity. When the user returns to the task again, only the root activity is restored. The system behaves this way, because, after an extended amount of time, users likely have abandoned what they were doing before and are returning to the task to begin something new.
You might look up into the Android documentation regarding Tasks and Back Stack and upon some information about Pausing and Resuming an activity. :)
You issue probably related to memory management on android. It looks like android kills you app to release memory so that it can be used by another app. I have an app with very complex layout (The app loads too many images). After some times, when I run the app from recent app list, it always run the app from start. Not from the last state where I left the app. Anywa, nothing to worry about. This is normal behaviour.
As of my concern this is your problem-
you are starting an activity.
then you press home button. and the activity goes to background.
when you start the app after 5 minutes the app starts from the paused activity. but when you start app after 5 hours the app starts from the beginning.
Solution-
This is happening because the activity is being killed in background by the android system.
the application can be killed by calling the ondestroy() method of the activity.
and when the app goes to background it is added to the application stack of the android system. when ever android needs more memory for any operation it takes memory from the last application in the application stack. it kills the last application and takes its memory.
this is the reason your app is being killed after long time. your app is at the last of the stack and android has killed your app to get memory.
you can find more explanation of the process here.
How to solve this problem
this can be solved by bringing your app to front of the stack periodically.
you can run a service from your activity in background so that is stays on top side of stack.
or save the last opened activity in a shared preference and go to this activity when the app starts.
I am working on a project, where while being on a specific Activity we show a local sticky notification. That should also be the case when the app is minimized. What I have to accomplish is to remove the local notification whenever the app is killed (by Android, because of memory lack or by the user, with a swipe from the recent apps list).
Usually onDestroy would be called whenever Android takes the Activity to open some space. That is fine in one of the cases, however swiping an app from the recent app lists doesn't call the onDestroy and the sticky notification stays.
What I did is, I implemented an empty Service which would force the onDestroy when the app is killed (both swipe and system kill) so I can get my notification removed.
However, what I would like to do is to differentiate between the swipes and system kill.
Is this even possible?
In general, if Android wants to kill your application because it has been in the background for too long (or because it wants to reclaim resources), Android will just simply kill the OS process hosting your app. It will not call finish() or onDestroy() on any Activity or Service components. The behaviour of "swipe from recent tasks list" has changed over time and is different in different Android versions. Someone should write a book about that :-(
You can check for when the user swipe-closes the app by adding a service to your app, and implementing the onTaskRemoved method: https://stackoverflow.com/a/26882533/2441655
This is a comment I found in reddit that seems to me really interesting:
Swiping an app away will effectively "kill" most apps. You can test
this out using ADB if you have the SDK installed. Swipe everything out
of your recents list, then launch the browser.
Use ADB to run 'ps' on the device and verify that the com.google.android.browser process is
running. Go to the home screen, it's still running. Launch some other
apps, and the com.google.android.browser process is still there.
Swipe it out of the recents list, however, and the process is gone. You can
create a test app to further verify, and log the onDestroy() call in
your Activity. It's not called when you back or home out of the app,
or when you launch other apps. It does get called when you swipe the
app out of the recents list though. I do agree that the recent apps
list isn't really "multitasking".
The apps in the list aren't necessarily even running, the processes could have been killed by the
memory manager long before you try to re-open it. However, you can't
argue that the only purpose is to jump quickly to other apps when the
swiping makes the actual process go away.
This is another good answer about what happen when you swipe an app out of the recent apps list. But the part that I liked most was:
Actually, removing an entry in recent tasks will kill any background
processes that exist for the process. It won't directly causes
services to stop, however there is an API for them to find out the
task was removed to decide if they want this to mean they should stop.
This is so that removing say the recent task of an e-mail app won't
cause it to stop checking for e-mail.
If you really want to completely stop an app, you can long press on
recent tasks to go to app info, and hit force stop there. For stop is
a complete kill of the app -- all processes are killed, all services
stopped, all notifications removed, all alarms removed, etc. The app
is not allowed to launch again until explicitly requested.
By Swiping from recent task list removes only from recent tasks ..
It was also called onDestroy before android 5.0 .
Might be you are having issue above api level 20 devices.
System kill normally can not be executed in normal android activity lifecycle.
It just finishes the activity on back press event.
when swiping app to left if any Thread still run in your app Interrupted but service not stopped, when you kill handy app Thread and services are stopped.
the behavior is similar to but not exactly the same as closing an app -- in general (for apps that don't define explicit back button handling) it's the same thing as hitting back enough times from within an application that you exit out of it.check out this link discussion it has some good input on the subject
First, let's get one thing clear: Android MAY NOT CALL onDestroy(). Referring to the Activity Page, from Honeycomb onward, onPause() and onStop() are guaranteed to be called before an app is killed.
Be aware that these semantics will change slightly between applications targeting platforms starting with HONEYCOMB vs. those targeting prior platforms. Starting with Honeycomb, an application is not in the killable state until its onStop() has returned. This impacts when onSaveInstanceState(Bundle) may be called (it may be safely called after onPause() and allows and application to safely wait until onStop() to save persistent state.
So after (hopefully) clearing the air on the Android lifecycle, I think you can achieve what you want by putting the notification removing code in onStop() instead. If you end up needing it back because the user actually DOES come back to the specific Actvitiy(IE not killed), you can bring it back in onRestart().
I got a main-activity, then it opened a new-activity. After putting it to background by clicking home button. If I killed the process using adb shell commands, then I reopen my app.
The new-activity is shown by default instead of starting from the first activity.
My question is that activity's life cycle is beyond its application process?
As the sample shows, even activity's application process is killed, the saved activity still is there. Is this correct? And will android system recycle the saved activities later?
If you reopen the app via the activities list, it will attempt to restart via the last open activity. It's a "feature" of Android that can be incredibly annoying (and frequently just wrong)- Android assumes every app can serialize its entire state when exited for later reopening. You either need to do that (via onSaveInstanceState and onRestoreInstanceState) or you need to catch when you're relaunched and explicity launch your main activity.
This shouldn't happen if you're relaunched via the app launcher, as that should always launch your specified activity.
Android remembers the state of recent tasks and activities. Android can kill your application's process at any time (if it is in the background). If your application was killed while in the background, Android remembers what activities were in the task and how they were started (Intents). If the user now returns to the task (either by selecting from the list of recent tasks, or by tapping the application's icon in the list of applications), Android will create a new process for the task and recreate the activity that was on the top of the stack (ie: the activity that was in front when the task was sent to the background). This allows users to open an applicaton, use it, leave it to do something else, and then return to the application where they left off.
In order for this to work properly, you must save and restore any necessary state (using onSaveInstanceState() and onRestoreInstanceState().
If a task goes to the background and is idle (unused) for some period of time (device manufacturers can change this, usually the value is something like 30 or 60 minutes), Android will reset the task. In this case, if the user returns to the task, the previous saved state will be ignored and the user will start from the beginning. However you can prevent this from happening by setting alwaysRetainTaskState="true" on the root (starting) activity.
I just did a little test: I started my app, went to a certain screen, pressed the home button and killed the process via Advanced Task Killer.
Now, if I go back to my app just a few moments later, I come back to that very screen. I also know that onRestoreInstanceState() is called in this case, as I have played around with this method quite a bit.
However, just out of curiosity, I did all the same, but let my phone lie around for some time (an hour or something). When I restarted my app, it went straight to the main activity.
So my question is: for how long does Android keep the saved state? or what determines if it throws it away or not? I already figured out it had nothing to do with lockscreen on/off.
Kind regards,
jellyfish
The activity is restored because such applications as Advanced Task Killer use "illegal" methods for killing applications. Android kills application is a similar way when it's low on memory and when killed application is launched again its state is restored.
Android keeps an application state for some time. Usually it's about 15-30 minutes but I think it depends on the device. But you can ask Android to keep an activity state "forever" (until the activity is finished) using android:alwaysRetainTaskState="true" attribute.
When you killed an application with Advanced Task Killer for example, the application restart with the main activity the next time. I suppose that the application save the state in file to restore the same activity even if it killed!
Android will dispose of the activity when it needs the resources that the activity is holding (usually memory) and the activity is not in the foreground. There's more criteria involved, but that's the general case. There's no predefined time limit or criteria other than "when it decides it needs to". The app could die almost immediately or it could stay up indefinitely. You should never assume your app will ever be killed and you should never assume your app will never be killed.