Activity lifecycle for non-foreground activity - android

My app has a main activity and occasionally on some user action it opens up another activity (and remains in the activity stack).
My understanding is, Android, if needed, can decide to kill the main activity when it's in background though the currently visible one will be unharmed.
I am pretty sure I have seen this phenomenon in past (2-3 years back).
Here are the questions -
Under what conditions Android might decide to kill the background activity though the app is in foreground?
Does some specific version of Android/vendors have more chances of doing this than the other?
If I remember correctly, in such cases activity's onStop may or may not be called. Is this assumption right?

My understanding is, Android, if needed, can decide to kill the main activity
There's no main activity concept in Android. Your app can be killed as whole or some unused elements can be garbage collected.
I am pretty sure I have seen this phenomenon
This is not a phenomenon but normal Android system behavior.
Under what conditions Android might decide to kill the background activity though the app is in foreground?
Does not matter really. All you need to bother is that you can be killed/restarted and knowing that all you need to do is to ensure your data can survive.
Does some specific version of Android/vendors have more chances of doing this than the other?
Again the same - it does not matter. Ensure your app handles such case correctly and that's it.
If I remember correctly, in such cases activity's onStop may or may not be called. Is this assumption right?
No, unless your process is really killed, not garbage collected.

If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere.
To answer your question your MainActivity will be stopped as soon as your new activity is launched,
you should read up on the activity lifecycle:
https://developer.android.com/reference/android/app/Activity.html

Related

Android destroying activities, killing processes

Hi I'm wondering how Android is managing memory and I can't find precise answer anywhere.
Let's assume I have an application with 5 activities on current activity stack (4 are stopped and 1 is resumed), there is no service connected. I press HOME button so that all of my activities are stopped.
I start some other memory consuming application and overall device memory is starting to be low. And the question is
... What will happen to my application?
Can system destroy only one or some of my activities to recover memory?
Will system kill the whole process of my application? Will all activities be nicely destroyed?
What will happen when I get back to my application when it was totally killed? Will it start from beggining (like the first start) or will it try to recover activities to previeous state / if yes - is it only the one on the top of the stack or all of them?
UPDATE:
Before asking this question I've seen Activity lifecycle a few times but it doesn't have answers to my questions.
I made some tests and I have some answers. "Stop process" in DDMS was a clue for testing.
I haven't tested answer for question 1, but as guide says:
If an activity is paused or stopped, the system can drop the activity
from memory by either asking it to finish, or simply killing its
process.
It seems that one or more of the activities can be destroyed gently(with onDestroy method) without killing the process. You will simply get (onCreate + bundle) when getting back to them.
Question 2 answer:
YES. Generally system kills the whole process this means all data including activities and static fields are destroyed. This is NOT done nicely - you won't get onDestroy or finialize() for any of your paused/stopped activities. This is why saveInstanceState() is called just before onPause method. onPause is basically the last method where you should save something because after this method you could never see onStop or onDestroy. System can just kill the process destroying all of your objects whatever they hold and whatever they are doing.
Question 3 answer:
What will happen when you get back to a killed application?
Prior to Android 2.2 - application will start from the beggining, with launcher activity.
Starting from 2.2 - system will restore the previous application state. What does it mean? It means that last visible activity will be recreated (onCreate + bundle). What will happen with activity stack? Stack is fine but all activities on it are dead. Each of them will be recreated (onCreate + bundle) when you get back to it with back button.
There is one more thing about that:
Normally, the system clears a task (removes all activities from the
stack above the root activity) in certain situations when the user
re-selects that task from the home screen. Typically, this is done if
the user hasn't visited the task for a certain amount of time, such as
30 minutes.
Conclusion?
Don't think that handling activity rotation problems can be solved
by android:configChanges="orientation". When you do that you will
get many other problems that you are not even aware of.
Test your application with DDMS - Stop process button. See This
Be careful when using static variables. Don't think that when you initialized them in activity 1 - you will have them initialized in activity 2. The only safe place to initialize global statics would be Application class.
Remember that you may never see onStop or onDestroy. Close files/databases, stop downloaders in onPause. When you want app to do something in BG - use foreground Service.
That would be it ... Hope I helped with my essey :)
First please have a look at this:
onPause() Called when the system is about to start resuming a
previous activity. This is typically used to commit unsaved changes to
persistent data, stop animations and other things that may be
consuming CPU, etc. Implementations of this method must be very quick
because the next activity will not be resumed until this method
returns. Followed by either onResume() if the activity returns back to
the front, or onStop() if it becomes invisible to the user.
onStop() Called when the activity is no longer visible to the user, because another activity has been resumed and is covering this
one. This may happen either because a new activity is being started,
an existing one is being brought in front of this one, or this one is
being destroyed. Followed by either onRestart() if this activity is
coming back to interact with the user, or onDestroy() if this activity
is going away.
So, when you press "HOME" button on your device, your current foreground activity is put onto onPause() then onStop(), the other 4 should remain onStop()
According to Google's Documents:
If an activity in the foreground of the screen (at the top of the stack), it is active or running.
If an activity has lost focus but is still visible (that is, a new non-full-sized or transparent activity has focus on top of your
activity), it is paused. A paused activity is completely alive (it
maintains all state and member information and remains attached to the
window manager), but can be killed by the system in extreme low memory
situations.
If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however,
it is no longer visible to the user so its window is hidden and it
will often be killed by the system when memory is needed elsewhere.
If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing
its process. When it is displayed again to the user, it must be
completely restarted and restored to its previous state.
And, for the process lifecycle:
Process Lifecycle 3. A background activity (an activity that is not visible to the user and has been paused) is no longer critical, so
the system may safely kill its process to reclaim memory for other
foreground or visible processes. If its process needs to be killed,
when the user navigates back to the activity (making it visible on the
screen again), its onCreate(Bundle) method will be called with the
savedInstanceState it had previously supplied in
onSaveInstanceState(Bundle) so that it can restart itself in the same
state as the user last left it.
All the quotes above are come from: Android Developers Reference: Activity
It is confirmed that the system can destroy non-acitve activities and recycle memories when you launched some memory consuming applications. And you can implement like: isFinishing() in your activity and then using "kill" button in DDMS to detect which of your activities is being dropped by system. But I guess the system will destroy the oldest one first. However it is no point to keep other activities when the "Launch Activity" has been recycled.
UPDATE
Here's some opinions I found from here:
Stopped state
When an activity is not visible, but still in memory, we say it’s in a
stopped state. Stopped activity could be brought back to the front to
become a Running activity again. Or, it could be destroyed and removed
from memory.
The system keeps activities around in a stopped state because it is
likely that the user will still want to get back to those activities
some time soon, and restarting a stopped activity is far cheaper than
starting an activity from scratch. That is because we already have all
the objects loaded in memory and simply have to bring it all up to the
foreground.
Stopped activities can be removed from memory at any point.
Can system destroy only one or some of my activities to recover
memory?
Yes. Android kills activities which are running in the background when there is a need for memory. Killing one or all might depend on some conditions. For an instance paused or stopped can make android kill an activity or a process itself. Here under Activity Lifecycle you can get the below points. I recommend you to go through that page completely. It will definitely clear your doubts.
If an activity has lost focus but is still visible (that is, a new
non-full-sized or transparent activity has focus on top of your
activity), it is paused. A paused activity is completely alive (it
maintains all state and member information and remains attached to the
window manager), but can be killed by the system in extreme low memory
situations.
If an activity is completely obscured by another activity,
it is stopped. It still retains all state and member information,
however, it is no longer visible to the user so its window is hidden
and it will often be killed by the system when memory is needed
elsewhere.
If an activity is paused or stopped, the system can drop
the activity from memory by either asking it to finish, or simply
killing its process. When it is displayed again to the user, it must
be completely restarted and restored to its previous state.
Will system kill the whole process of my application? Will all
activities be nicely destroyed?
Activity pertains to an individual whereas process pertains to group of activities. Look at the third point above again it kills the process as mentioned.
What will happen when I get back to my application when it was totally
killed?
Its similar to restart . Again the third point will give you some answers like When it is displayed again to the user, it must be completely restarted and restored to its previous state
Get some more information about memory related stuffs here.
Edit:
All activities in an application runs in a single process. So when a process is killed all the activities no matter 5 or 10 will be killed i.e., restarted. Restart will cause your application to start from a beginning no saved states.

details of Android application components destruction and recreation

Could someone push me in the direction of some concrete, trustworthy (and preferably concise) information on the following:
The order in which components are destroyed and (where applicable)recreated by the system
(Fragment, Activity, Activity's Threads/AsyncTasks/Timers,
static data(when are classes unloaded?), Threads/AsyncTasks/Timers in other classes, host
TabActivity, ActivityGroup, bound local Services, Application, process)
both when the app is in the background, and in the foreground.
At which points the destruction can stop (what states can be encountered
upon return to the app - like "everything including the Application object
destroyed, process alive"?
Is it possible (without modifying Android) to programmatically cause the same kind of destruction
ourselves, so that it is indistinguishable from when the system does it, or is a separate mechanism needed for when we ourselves choose to free memory (triggered by onLowMemory)?
Reliable reproduction steps of all scenarios from 1) (would junit.framework do? I haven't investigated that) ?
"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": is this aside from the process/component lifecycle/destruction, or tied to it?
I have read various sources give pieces of information, often incomplete and misleading, sometimes incorrect.
I admit, I have skimmed over some parts of the documentation, so i may have missed or misunderstood something.
[EDIT] To avoid misunderstandings: What I am asking about is Android destroying components to free memory, bypassing Activity.onDestroy.
When I put the app in the background and return later, the one of these sequences will occur:
onPause, onStop, onRestart, onStart, onResume
onPause, onStop, Application.onCreate, onCreate(notNull), onStart, onResume
[EDIT2]
Bounty started. Need reliable info on: Activities, Fragments, Application, bound (potentially remote)Services, process.
Partial/full destruction scenarios. See 1st point.
This is what my experience, and that of devs I've asked, seems to suggest:
Fragments are not autodestroyed.
non-visible Activities on the app's stack can be autodestroyed in any order, and in any number.
destroyed Activity's (or any other class's) Threads and statics remain untouched until Application is destroyed.
TimerTasks: haven't tested.
bound local Services: destroyed somewhere between the destruction of the last binding Activity and of Application.
Application is the last thing to go within a process, and "goes" along with all Threads.
the process can exist for a long (20+ minutes) time after the destruction of the Application object, unless you have an automatic task killer.
Activities under TabActivity or in ActivityGroups are not autodestroyed, but go all at once if the container is destroyed.
Example: a TabActivity with ActivityGroups under tabs. All Activities live. Another Activity is started, fullscreen. The TabActivity with everything in it is now eligible for destruction by Android, all at once or not at all.
NO.
If you destroy an Activity manually, it goes through the entire lifecycle and doesn't pass a Bundle to onCreate when started again.
Also, onLowmemory is unreliable - even with small allocation steps, it might never be called before OutOfMemoryError is thrown.
NO.
Despite the autodestruction/restoration being such a major feature in Android, there isn't any way to test such scenarios.
This is probably related only to whether the process still exists or not. If it does, Android will attempt to restore the old Activities. If not, it's a clean restart.
The above include some assumptions.
I am still waiting for someone to confirm it and supply some docs (guarantees not dependent on the current implementation of classes).
Please, PLEASE correct me if any of this is wrong.
Edit: The above information may be out of date, it was tested on Android 2.1-2.3
Credit for this goes to hackbod for writing it here(read the whole answer), and to CommonsWare for linking in a comment.
In short: All the docs, rewritten many times, continue to lie to us. They're not misleading, they just give us untrue information. Unless you're using Fragments (dunno if support v4 counts, too), Android frees memory by killing the whole process, or does nothing.
Of course, this does not address everything:
Point 4 of the question
Why I frequently saw onCreate(notNull) on pressing Back on an Activity stack with Activities handling all config changes (Android 2.3.7)
How this relates to the widely accepted belief that onPause is the last call you are certain to get, and onStop may never get called (how, then, can the app go to the background, to be killed?)
We're getting somewhere, though.
Well, my friend,
I guess you'll have a lot of trouble in your research. Basically because you're talking about two black boxes: the Dalvik garbage collector and the android heap manager. I would say that you cannot trust that android will follow any order of object destruction. But, you can trust that this lifecycle is going to be followed [Programming Android, 2011]:
Activity Lifecycle:
onCreate() - Called after the instance of the activity has been created for the first time
onRestart() - Called after an activity has been interrupted, just before the onStart();
onStart() - Called when the object activity and their visions become visible to the user;
onResume()- Called when the object activity and their visions become interactive to the user;
onPause() - Called when a different instance of the activity is going to get visible and the present activity ceases to interact with the user
onStop() - Called when the activity is no longer visible or is not interacting
onDestroy() - Called when an activity instance must be destroyed and it's no longer needed.
Fragments have different lifecycles including methods onAttach, onCreateView and onActivityCreated .
But, why do you care about the objects order of destruction? I can't see no reason for you to monitor such events, but if you really need, learn more about the garbage collector.
The ActivityManagerService#trimApplications()method remove any unused application processes if the application's current receiver is null, does not have any activity and service.
When it comes to activities, they will be only destroyed on on Destroy() until and unless developer manually calls the finish() function,
Fragment life cycle is a completely matched to its parent activity, so when parent activity destroys on on Destroy(), the fragments on Destroy() as well will be called.
Timer Tasks will finish their work and become candidates for garbage collection, once the activity creates them the task runs in its own thread, no relation with activity, even if the activity is destroyed, the task finishes itself....
This is not a complete answer but what I would recommend is that you place toast messages in each of these methods. Add in your own onPause(), onStop(), onResume(), etc. and inside put a line like this:
Toast.makeText(this, "onPause()", Toast.LENGTH_SHORT).show();
You cannot directly call these methods, however moving another activity to the top of the stack will of cause these methods on the existing activity to be called. One more thing to keep in mind is that onCreate() need not be called every time you start an activity. It really depends on how you start the activity, for example if you send this intent
Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP);
it will appear call onNewIntent() instead if it has already been created. In summary the best thing is just to watch the Toast messages. Also you really need to focus on using the debugger. Place a breakpoint on each method and you can see it. One thing I am sure of is that you cannot directly invoke these methods like onPause(). Also keep in mind that in general you don't know when onDestroy() will be called.

Android multitaksing

I am seeking short characteristic of Android Multitasking. I have found, that when you minimize Android application, it is ended and it's process remains on the background. When user wants to reuse his app, this process alive it's application. User will be at the same state, when he left (if there was enough memory while working with it), or it will be loaded from scratch, because there was no free RAM for other work and Android exited this process. Am I right? Everywhere there are articles with 20 pages and more about Android multitaksing. I need to know key points because I am lost in a such long artices.
Thanks
Short Answer: Yes. If your app can live in memory despite being 'closed' then it will stay in RAM and processing will continue when you click on it again. Otherwise it will be restarted and you will get an onResume().
Long Answer: Please just read the Activity Lifecycle:
When Android activity is covered by other windows it will enter into paused state and method onPause will be called. It may also me destroyed by OS and then onDestroy will be called. You have very little control over it and can't expect your application to come back up with the same state. However, when activity is brought up again to foreground in will go through steps of onCreate and onPause. Those methods can be used to restore its state.
Here you can find nice diagrams describing Activity lifecycle. Similar but slightly different lifecycle is applicable to service.
http://developer.android.com/reference/android/app/Activity.html
Android activities are the main visible screens that user see while the application is running. If you close the screen or switch to another application, the current activity is put to hibernate and you can save the state with
Activity.onSaveInstanceState(Bundle bundle)
After your activity gets the control back, you can restore the state with
Activity.onRestoreInstanceState(Bundle bundle)
Note that you need to be careful not to store any context references within the activities and related classes as the activity and thus context has changed between pause and resume. Instead, you should always pass the current activity as the active context to avoid having exceptions from invalid context.

How does Android's Activity lifecycles work in relation to the entire Application?

This doesn't appear to be well documented or I missed it, so before I run a bunch of my own tests I was wondering if anyone already knows the answers to some of these questions.
First off, when I say "Application" I am referring to extending the Application class. http://developer.android.com/reference/android/app/Application.html
The questions I have are as follows, some are related.
When an a user leaves an Activity from within the Application, and goes to the Activity of another application, does the Application somehow get paused as well, even though it doesn't have an onPause()? Or does it continue to live unpaused until all of it's activities are destroyed?
when does the Application stop? When all of it's Activities are destroyed?
Is there ever a chance that one of the Applications Activities could be running without an instance of the Application, or will the Application class always exist if one of the Activities does?
If there is some process running on the Application, and it's Activities are all paused, will that process continue to run?
Is the Application effected by rotation in any way or does rotation only change Activities?
Thanks
As you say the application does not have onPause so nothing happens to the application. When onPause gets called in your Activity nothing special happens, your Activity continues to run and can do whatever it wants including run new threads, timers can go off, whatever.
I believe what you are asking is: when is an Application destroyed and when the onTerminate method in an Application called? The answer is hard to pinpoint and is up to the system, it does not necessarily happen when all activities get onDestroyed called. In fact even when onDestroy is called, your Activities aren't necessarily garbage collected. When the system gets low on memory the process that your Application lives in can be killed, meaning your Application will disappear; onTerminate may or may not be called. At that time all the Activities, Services, etc, are killed too.
The Application is always instantiated first, an Activity must have an associated Application, just like how you define it in the AndroidManifest.xml.
Processes never pause in Android, the onPause method does not actually really do anything other than tell you to pause things in your app. Other than that the process keeps chugging away, your threads keep running, even the main thread receive Intents with a BroadcastReceiver.
The Application gets rotation callbacks in the Application's onConfigurationChanged(). I'm not sure if you can disable that since there is no configChanges attributes supported by application tags in the AndroidManifest.xml.
A good comparison to Application is static field in any of your classes. The static fields will live as long the process is not destroyed, just like the Application. Static fields can be accessed by all Activities, Services, etc (assume the static fields are public), just like your Application.
Good Luck!
Jacob
The easiest way to understand this is to just forget that Application exists. Application has nothing to do with the application lifecycle. It is just a global on a process, that can be useful for some things, but is not needed for anything. Everything about how an application runs revolves around the Activity, BroadcastReceiver, Service, and ContentProvider components declared in its .apk.
An instance of Application can continue to exist after your last Activity is destroyed. Even if ALL activities are gone (ie. have all had their onDestroy methods called), the Application instance could still exist.
This application instance could be "re-used" for what you might otherwise think are two separate runs of your application.
This is all explained in detail here: http://developer.android.com/reference/android/app/Activity.html. If you read through it, you should understand everything.
Real quick:
Every activity has an onPause. You can choose not to override it, but it'll get called nonetheless. As soon as you switch away, onPause will be called.
Define "stop". Define "Application". The process may linger around forever, but it'll simply sleep and wait until one of its activities is started.
It's impossible for an activity to exist without being instantiated.
Every code executed runs in a process, so there's always one process for your app. The process will continue to exist after you switch to a different app, but it'll be in sleeping state. Android could at any time kill the process if system resources run low.
Every time you rotate the screen, your activity will be destroyed and recreated, unless you specifically disable that.

How much time can be taken inside onDestroy() before the activity is killed?

I know my question caption must have sounded really vague. But let me clear it out here.
Say I have an android application over a middleware stack. In onCreate() of my activity, I initialise my middleware modules.
In its onDestroy(), I must de-initialise the middleware. Now my middleware calls may take quite some time to process. So I want to know how much time the onDestroy() function has, and see whether my deinitialisation can take place within that time.
Is it reasonable to keep my de-init in the onDestroy()?
Also, suppose I initialise the middleware in onCreate() of activity A1. On a button click, activity A1 switches to activity A2. In low memory situations, the LMK will kill the activity that has not been in use for some time. In such a case, won't activity A1 be killed? When activity A1 is killed, will all instances I create in A1 also get destoryed?
Regards,
kiki
I believe you are rather confused to ask this question.
In order to get a good comprehension of what is happening, you should take a look at the lifecycle graphs that can be found on developer.android.com:
Activity lifecycle
Background service lifecycle
You will see that Activity.onDestroy() only gets called in the case of a controlled shutdown of the activity - something that happens extremely rarely, as the Android OS can kill your process in a variety of states without ever calling your onDestroy() method.
What and why do you need to de-initialize?
If you're worried about releasing resources, then most of them will get released anyway when/if your process is killed.
If you are worried about saving the user's data (your application's state) then you should override onSaveInstanceState() and onRestoreInstanceState()
If you really want an answer to your question, then here it is:
While it is running onDestroy(), your app has (probably) as much time as it would like to - the fact that it is even running onDestroy() means that the OS did not select it to be killed. But it will most likely not matter: for one, onDestroy will never be run in most apps, and if the OS changes its mind and decides that your app must die, it will kill it even if it is running onDestroy.
http://developer.android.com/guide/practices/design/responsiveness.html:
In Android, the system guards against
applications that are insufficiently
responsive for a period of time by
displaying a dialog to the user,
called the Application Not Responding
(ANR) dialog
The ANR dialog will normally pop up if your application is un-responsive for 5 seconds. As pointed out by jhominal, the onDestroy() method is probably not where you want to do your clean-up/save preferences/etc.
Regardless of where you choose to do this, be it onDestroy(), onSaveInstanceState() or in onPause(), I believe the general 5 second rule will apply. If what you're doing takes more than 5 seconds, the ANR dialog will show and the user can choose to force-close your app.
Edit:
If your application is in the background, it might be (probably?) that it is killed directly without the ANR dialog being displayed if you violate the 5 second rule. But I do not know this for sure, only assuming.

Categories

Resources