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.
Related
If I, for example, need to keep some very important data which the user can edit within my app, should I need to save them every time user changes such data or is it ok if I would save it within onPause(), onStop() or onDestroy() methods?
Can somehow application end without any of those methods calling? (For instance when battery runs out)
This certainly can't be done in onDestroy().
According to the documentation:
There are situations where the system will simply kill the activity's
hosting process without calling this method (or any others) in it, so
it should not be used to do things that are intended to remain around
after the process goes away.
So yes, the application can end without calling any of the lifecycle methods.
In that scenario when the phone is shutting down, you can use the ACTION_SHUTDOWN Intent.
More info here. For all other cases onPause should do the work. Even in the link provided, there is a statement that onPause will be called if the app is in FG.
Apps will not normally need to handle this, since the foreground
activity will be paused as well.
However, if it is not so expensive operation, I would go with saving data after edit.
As per the documentation of Android activity life cycle, onPause is called when an activity is going into the background, but has not (yet) been killed.
Hence, in most Android documentation, and sample codes you will find onPause is used for saving any persistent state the activity is editing, to present a "edit in place" model to the user and making sure nothing is lost if there are not enough resources.
So in your use case, all you need to do is implement onPause for your Activity and write a code to Save the activity state (EditText content or any other ongoing user interactions). Android system will save the activity state which you can always get back in onCreate of your Activity when android launch your activity next time.
in this case please verify your phone activity via debug interface , some of phones are terminate your application this is force quit.
To make things as simple and easy to follow I created a new empty project in Android Studio with only one MainActivity and Hello World text. This could not by any means be a consuming app. I also did override all the important life-cycle methods like onCreate ,onStart, onResume, onPause, onSaveInstanceState, onStop, onDestroy and logged them to see what is happening.
So here is what I am experiencing (in each step the list of life-cycle callbacks is printed)
After app/activity launches (expected behavior)
onCreate onStart onResume
After I press home button / app goes in background (expected behavior)
onPause onSaveInstanceState onStop
After I immediately return / app goes in foreground (expected behavior)
onStart onResume
After I press home button (app goes in background) and I open another app like Facebook and immediately return back to my app I expect it to resume, but instead onCreate gets called.
onCreate onStart onRestoreInstanceState onResume
I find this really strange because I am not low on memory on my device and I have basically empty activity. Is there some flag I can set in the manifest or any solution that will not recreate my activity when I return to it ?
Please don't suggest I save and restore state using onSaveInstanceState and onRestoreInstanceState, I am specifically interested why onCreate is called when I move my app back in foreground. I've done many apps in the past and I don't remember having this issue before with activities being destroyed so early.
I open another app like Facebook and immediately return back to my app I expect it to resume, but instead onCreate gets called
Apparently, Android terminated your process, either of its own volition to free up system RAM or at the behest of some other app (e.g., task manager). This may also be device-specific, as device manufacturers can tweak how this stuff works, from what I can tell.
I find this really strange because I am not low on memory on my device
Perhaps Android or the task manager disagreed with you. Perhaps your means of determining free memory isn't the same as what the out-of-memory killer uses. Also, bear in mind that Facebook uses some techniques that cause them to use an outsize amount of RAM for their process, so they will cause more of this sort of thing than will a leaner app.
Is there some flag I can set in the manifest or any solution that will not recreate my activity when I return to it ?
No.
That being said, there are a variety of factors that the out-of-memory killer will use to determine what process(es) to terminate to free up memory, including:
process importance (are you in the foreground? do you have a service running?)
process age
process working set size (i.e., memory usage)
Please don't suggest I save and restore state using onSaveInstanceState and onRestoreInstanceState
I would suggest to all Android developers that they save and restore instance state using onSaveInstanceState() and onRestoreInstanceState(). That helps with configuration changes as well as these sorts of process termination scenarios.
I've done many apps in the past and I don't remember having this issue before with activities being destroyed so early.
Perhaps you did not test them on this device, or on this device and OS version (if you got an upgrade). Perhaps you did not test them in this scenario (e.g., launching Facebook). Perhaps you did not test them with the other apps you have running that might be affecting matters. Since you wrote those other apps, presumably you can re-run your tests using those apps, for more of an apples-to-apples comparison.
You can (and should) make this happen for testing by turning on the "don't keep activities" developer option. You cannot prevent it from happening. This can always happen, and you must handle it gracefully.
Please don't suggest I save and restore state using onSaveInstanceState and onRestoreInstanceState
That's what you have to do if you want your app to work reliably.
The android lifecycle guarantees some things and provides no guarantees about others. It's guaranteed that if your activity was destroyed, onCreate() will be called before onStart() and onStart() before onResume().
However, in most cases there is no guarantee that your activity will NOT be destroyed once it goes into the background. The reasons are not fully spelled out because this gives google (and individual android distributions) the freedom to modify such things in the future. Part of the downside of having no such guarantee means that just because your activity did not get destroyed in the past, does not mean that in a different version of android, different device, or different circumstance, that it will not get destroyed in the present.
If you must know the exact reason why, I would suggest monitoring the log output very closely, it may contain some clue. But keep in mind that android does not intend for the developer to try to avoid this, only to resume from where you left off when the activity is re-created.
I wrote a small game on android. It has one activity + one fragment. I save the state of the game in Fragment.onSaveInstanceState and restore the state in Fragment.onCreateView.
If I rotate the screen, the game state is preserved properly. However, if I turn off the screen and come back to the game at a later time, sometimes I lose the game state and get a new game instead. Therefore, I wonder if Fragment.onSaveInstanceState is called at all when the system decides to kill a process to recover memory. Also, what is the life time of the stuff that gets saved into the Bundle in Fragment.onSaveInstanceState?
By the way, is there anyway to easily test such a case during development? It'd be terribly inefficient to wait for a day or two for the system to kill it.
Thanks for helping me out!
I wonder if Fragment.onSaveInstanceState is called at all when the system decides to kill a process
Yes.It is called.
I think your issue lies somewhere here.From the documents :
The most significant difference in lifecycle between an activity and a
fragment is how one is stored in its respective back stack. An
activity is placed into a back stack of activities that's managed by
the system when it's stopped, by default (so that the user can
navigate back to it with the Back button, as discussed in Tasks and
Back Stack). However, a fragment is placed into a back stack managed
by the host activity only when you explicitly request that the
instance be saved by calling addToBackStack() during a transaction
that removes the fragment.
Not sure if this can solve your problem but i think you should keep it in mind while writing your game code.
I have an app, a single activity app with fragments in it.
The usual use case for this app is, that you start it and put the phone away and every now and then, you get back to the phone and insert some data... It's a logging app, you are doing something and insert your results into the app...
I have the problem, that every now and then, my activity get's destroyed and is recreated with an empty bundle... (Most of the time this is not the case, but every now and then this happens...). My app sometimes starts a service, even this service is killed in this case...
This means, that the system has killed my app, does it? How can I avoid this?
I need to keep the user data and the current top fragments... And they are saved to the bundle and everything works as long as their states and the data get saved...
Btw., my activity is always the TOP ACTIVITY, only that the screen turns off often... I just want to keep my activity alive as long as possible until the user leaves it with the back button... Or to save the state reliably
IMPORTANT NOTE
onSaveInstance does not always work (it's not part of the lifecycle and therefore not guaranteed to be called)... it only works most of the time... I need a way to that works always... If android kills my app...
don't keep your app in memory
You don't want to block Android from killing your app. What you want is to restore your app's state properly. Then the user will never notice the app has been destroyed and the user still gets the benefit of an app that was destroyed when not in use.
If you really want this use a wakelock. This will drain your users battery so I think twice before implementing this... Info at How do I prevent an Android device from going to sleep programmatically?
onSaveInstanceState explained
To do so check what information is needed in the bundle and persist that information with the onSaveInstanceState(bundle:Bundle) method so you can reuse it in onCreate(sameBundle:Bundle).
More information available from Google documentation at Save your Activity state and Restore your Activity State.
About Android Activity lifecycle
As stated by #prom85 in the comments below it's not guaranteed that the onSaveInstanceState method will be called because it's not part of the lifecycle. Workaround for this is using the onPause lifecycle hook to ensure your data is stored.
More information at Android: onSaveInstanceState not being called from activity
I had a similar problem, I arrived at this post while searching for a solution, you have to play with the manifest to achieve this and also understand what exactly activity is, in Android eco system,
In Android activity is a task which has a pre defined work.
I dig a lot in the documentation, I found that, we can configure activity in two ways,
Persistent
non persistent
if you mention for the activity in the manifest as
android:persistent="true"
and run the below use case
Start the APP
Press back or home button
you select the activity in the back stack again to bring it to front
Activity enters start -> pause -> stop - > resume , it does not get into onDestroy method.
if do not mention
android:persistent="true"
for the same use case
Activity enters start -> pause -> stop -> destroy, and if you select the activity from the back stack
Activity enters resume->create->start
If you want to run a service/task on activity start which keeps running when the app is in back stack, then you have to start that in the onCreate method, and kill them onDestroy by specifying your activity as persistent in manifest.
I hope my above solution might help others who arrive here for the same problem
I want to discuss the Android life cycle. I know the basics of how the Android life cycle works but there are some questions I want to ask.
Why don't Android apps move from running to stop directly why it first goes through the pause phase ?
Why don't Android apps move from Running to Destroy directly like IPhone apps? Why does it move from Pause->Stopped->Destroy why not Running->Destroy ?
Apps are not immediately destroyed mainly for performance reasons. From the Android Developer Activity Reference:
The Android system attempts to keep application process around for as
long as possible, but eventually will need to remove old processes
when memory runs low.
If the screen is still powered on and there's no pressing need for your device to free up memory, for example, it's obviously faster for the user if the activity is simply paused instead of completely destroyed. Multiple end lifecycle stages make this possible.
The various callbacks indicate different things. This allows you to separate your cleanup functions into the quick, critical items (disconnecting from system resources like a database or network connection) vs. the longer term tasks (persisting user data across launches of your application, for instance). Because your activity is kept around as long as possible, you can avoid the expensive operations when the user is just pausing the activity momentarily.
onPause() is the first callback, indicating your activity is no longer in the foreground. An app will be paused if a dialog appears or if the user pushes the Home button, for instance. If the app is paused for a dialog, for example, you wouldn't want it to be destroyed because it's still visible.
If you also receive onStop(), it indicates your activity is no longer visible. At this point the user no longer sees what you are displaying. This could mean the user opened another application, for example. Even at this point, however, the system may still keep your activity around to make it quicker for the user to return to it later. (If you/the user ended the activity, however, then it will not be kept and will proceed with the end lifecycle callbacks.)
onDestroy() is the final callback before the activity is destroyed. Note that in extreme cases, the system may destroy your activity without calling this method.