If an activity is being shown on the screen and has a button with a click listener attached to it, that gets attached to the button during the onCreate method, and then the device goes into sleep mode (or the user taps on the power button to turn off the screen), when the screen comes back on the activity is still visible as it was prior to going into sleep mode.
The onResume gets called, which is documented as part of the lifecycle for an activity. What I don't understand is why the onCreate doesn't get called again. How is it possible for the button's click listener to even function after coming out of sleep mode? You would think that Android has destroyed all running processes attached to the activity which includes the button's click listener.
What do you mean by, why doesn't the onCreate() get called again?
Simple answer: your activity is not being destroyed when the screen goes off, so there is no reason for onCreate() to be called again.
When the phone's screen is turned off, the activity's onPause() callback is called, followed by onStop(). However, just because it reaches onStop() does not mean that it will always reach onDestroy(). At least to my understanding, Android's OS attempts to keep as much of its memory used as possible so that apps will load back up faster, etc (this is a real over simplification, but I believe that is the general idea). That means that your activity still exists in memory when the screen goes off (at least at the beginning). Only when the system really needs the resources that your activity holds will it call your activity's onDestroy(). That is why your button click listener still works when you turn the screen off. Your activity still exists in memory, which means that your button listener is also still registered.
I think it's important to point out that sleep mode and turning off the screen are not the same thing. When you turn the screen off, it may or may not go into sleep mode right away. When the screen goes off but it doesn't go into sleep mode yet, the cpu is still working and the service is still running. When the phone goes into sleep mode it powers down the CPU, essentially "freezing" all processes, and as a result all services also. Using wakelocks prevents the phone from going into sleep mode, which is why services will still run while the phone's screen is off for an extended period of time. If you haven't read it yet, the Service reference has some pretty good info. It also discusses its lifecycle and how Android prioritizes its memory usage.
Android's activity lifecycle is extremly complicated and even Romain Guy states he doesn't understand it fully after many years of core development on android. You can assume that Android OS can interfere with your Activities lifecycle how it may seem fit when it's in background. The activity lifecycle represents the actual behaviour only very roughly, mostly I got my understanding through experience and trail and error.
In your case if you send your activity in background, if android has RAM available it trys to keep your activity in RAM, so it's going through onPause and onStop. Now this state can persist until you return to your app, then it will go through onStart and onResume, since all your references/fields you created onCreate still exists and can be "reused". On the other hand if the OS decides to it needs more memory it can destroy your activty and will be open for garbage collection and also will go through the onDestroy() lifecycle. The next time you reopen your app a new activity will be created with the state saved onSaveInstanceState() and the whole lifecycle from onCreate() will be run through
With services it's the same thing. Usally service SHOULD not run over long time, they also should stop themselfs immediatelyafter they are done. So if the OS finds a service that runs over long time in the background it trys to get rid of it to save battery / ram after an abitrary amound of time (and perhaps other parameters are included in this decision). On the other hand IF you need a long running service you need to manually keep a wakelock to sginal the OS "I need this done no matter what".
When you press power button or home button ,android OS put your current activity onto back stack,
Reason why onCreate doesnt get called again is,it is specifically made to create views and to do one time memory operation like loading your xml layout into activity.The system works such as you dont have to allocate memories each time you come on that page instead only when you created the page.onResume gets called because you are resuming back to the same activity.
Memroy Managment is very crucial in Android as it is a mobile operating system.
short answer:
onCreate() gets called when a Activity gets created.
the behavior for a device going into sleep and comming back is defined as onPause() and onResume() call. device sleeping will not kill the app or the activity - state keeps (nearly) the same.
#AndroidDev you will get clarity of this question, if you know which methods are calling at what time. below is the method called list at the different scenario
1)when we start activity nothing but calling startActivity(intent) this time
onCreate()
onStart()
onResume()
2)how many ways activity goes in sleep mode?
a)when we pressed lock button it will goes in sleep mode and below methods called
b)when we pressed overview button it will goes in sleep mode and below methods called
c)when we start another activity from present activity it will goes in sleep mode and below methods called
onPause()
onStop()
3)how many ways activity destroy
a)if we called finish() method it will called below methods
b)if we click back button it will called below methods
onPause()
onStop()
onDestroy()
so when ever activity going in sleep mode it's not calling onDestory() method, that why when your coming back from sleep mode your activity not calling onCreate method.
onCreate() will called only first time when you called startActivity() or if you destroy activity calling finish() or back button pressed in this both condition destroy() method will called.
Related
I have an Activity that I consider a critical operation (Specific communication with another computer over Bluetooth) and I want to make it so that when the user leaves the activity, it cannot be resumed to that state. With other words, if the user resumes the activity it should be recreated.
Since this activity uses Bluetooth it might start one or two activities for result (Enable-Bluetooth activity and Request-Permissions activity) and therefore, I cannot simply finish() the activity in onPause().
By leaving the Activity, I mean presses the home button, takes a phone call or presses the multitask button
I have experimented with some Activity Launch modes (like singleTask) without success.
I already call super.onCreate(null) in the Activity's onCreate() method, preventing it from recreating to a specific state after it has been destroyed, but I want to reset the activity whether onDestroy() has been called or not.
Does anyone have any suggestions on how this should be done correctly?
Edit:
The question in the Possible duplicate explains how to quit an application and it's subtasks completely (whereas just finish() would suit my needs perfectly - if I knew where to call it). This question is about finding a clean way to not resume the previous state of the Activity.
If you never want a state persist once you've left via the home button, or perhaps even when the screen turns off, the simplest thing is to work with the lifecycle events available. It's a whole lot simpler than trying to work around Androids design by doing things like forcing the close of your app.
Since everything needs to be setup each time someone returns to the app, you can move all of your setup logic out of onCreate and into onResume. Then, perform all the required cleanup (kill your BT connection, etc) in onPause. The only possible gotchas are related to things like changing screen rotation/ opening the keyboard which might trigger lifecycle events that you didn't intend. That might make your program less responsive if you have a lot of long running tasks on the UI thread in onResume.
I create a new thread in an activity and I rely on onPause() to interrupt the thread. If my app crashes, or the Activity somehow ceases to exist, I want the thread to be killed.
Is Activity/Fragment.onPause() guaranteed to be called when an Activity is no longer running? If not, how can I guarantee the thread in question is killed?
If my app crashes
onPause() is not called here, but this shouldn't bother you as your entire app process ceases to exist, inclusive of all threads you have created (UI or otherwise).
Activity somehow ceases to exist
onPause() will be called whenever your Activity is moved to the background from the foreground, which is done in every conceivable way in which your Activity can be shut down, except for your app crashing. However, as I mentioned above, the app crashing will also by default kill your thread.
onPause() is essentially called whenever your Activity is no longer in the foreground. Your Activity may still be alive and in memory after onPause() has been called, but there is no scenario which I can think of in which your Activity is alive and in the background without onPause() being called.
Yes , onPause() will be called when an activity is no longer running. Suppose an activity is closed then the sequence of events will be onPause() -> onStop() -> onDestroy(). Even if your activity slips into the background when another activity starts or when the screen switches off, onPause() is always called even if the other two methods aren't called. So even if activity ceases, onPause() will be called and your thread will be killed.
But when your app crashes, along with your entire activity, even the thread that you have started will be taken care of by Android by finishing it all.
Suppose you have two activities A and B. You navigate from A to B. Activity A goes to background ie activity A is paused. Activity B takes focus ie foreground. When you click back button activity B is popped from back stack and activity A takes focus ie activity A resumes.
When you display a dialog in activity the activity in paused and dialog is displayed on click of back button dialog is dismissed and activity resumes (foreground).
When activity is no longer running it is in background so it is paused. I agree with Raghav Sood to what happens when app crashes.
You should usually use the onPause() callback to:
Stop animations or other ongoing actions that could consume CPU.
Commit unsaved changes, but only if users expect such changes to be permanently saved when they leave (such as a draft email).
Release system resources, such as broadcast receivers, handles to sensors (like GPS), or any resources that may affect battery life while your activity is paused and the user does not need them.
Note :
Multiple tasks can be held in the background at once. However, if the user is running many background tasks at the same time, the system might begin destroying background activities in order to recover memory, causing the activity states to be lost.
In addition to the accepted answer, which helped me here, I would like to add that there exists a way to basically, catch any error or crash that happens. This allows you to do things before the app exits. For example, you can save the whole logs, in order to send it later to a remote server for debug.
This means you can also probably do other some kind of light computational things if you really needs to (properly closing active connexions, etc etc).
More concretely: Is it safe to place the canceling of a task in onDestroy? Also, is it safe to use onDestroy for unregistering receivers and freeing up resources?
My aim is to make sure that my task is canceled/destroyed when the Activity is destroyed, but not before.
onDestroy():
is called when the activity is destroyed and resources must be
released.
is NOT called when the activity is destroyed in a hurry (when the
system is low on resources etc).
The first case is clear: I do all cleaning in onDestroy and no problems arise. The second case is a bit of a problem though. When the Activity is destroyed and onDestroy is skipped (so I don't cancel my task), could it happen that the task continues execution, then completes and tries to update the dead Activity, so the app crashes?
We come to the real question:
When an Activity is killed and onDestroy is skipped, is everything attached to that Activity automatically destroyed? (Is onDestroy skipped only in case that everything will be wiped out altogether? Tasks, registered receivers etc)
If onDestroy is skipped does this mean that the whole app is being killed?
Let's focus on onDestroy(), because the solution is not in onPause() or onStop(). Arguments:
onStop() could be skipped when the Activity is being destroyed, just like onDestroy
onPause is called too early and too often, so it is not appropriate for the use case. Examples:
Screen lock: onPause can be called when the device screen is locked. Very often this happens like a screensaver and the user unlocks immediately because he is standing there looking at the screen. Canceling tasks and stopping everything my app is doing in such a case will only degrade user experience. I don't want my app to choke and misbehave just because of an incidental "screensaver".
In an example app I have two screens that are Activities. The user can quickly switch between them. In this app users tend to switch screens often and quickly.
Navigation: One of the screens has a map which receives location updates from the system. It records a precise graphical log of the changes in location (route), so it needs to run constantly until the Activity is closed. Normally I would register and unregister any receivers in onResume and onPause. However, this would make the app very unusable, as the updates on the map will stop every time the user navigates away. Therefore, I would like to unregister the receivers in onDestroy.
Loading list: The second screen has a list that shows data from a webservice. It takes 4 seconds to download the data. I use an AsyncTask and I know I should cancel when necessary. It should not be canceled in onPause, because it should continue loading while the user switches between screens. Therefore, I would like to cancel it in onDestroy.
There can be many more examples. Some of them might not be totally appropriate in everyone's opinion (you might even suggest using a service instead of AsyncTask). But the idea is important, and all of them have the same idea: keep on doing work that's specific to the Activity, while the Activity is paused, but ENSURE to stop doing it when the Activity is destroyed. (It does not matter whether I am using an AsyncTask or a Service. In either case, the work should be stopped when the Activity is destroyed.)
P.S. If the answer is that it is not safe to do the clean up in onDestroy, this would mean that the Android framework requires us to stop everything we are doing in onPause. And then I would not see any reason for using onDestroy...
I would like to refer you to this baby: http://developer.android.com/reference/android/content/ComponentCallbacks2.html#onTrimMemory(int)
Essentially it gives you all the places where the system finds it useful to cancel tasks and clean its memory:
Please take a closer looks at the following 2 cases:
TRIM_MEMORY_UI_HIDDEN - the process had been showing a user interface, and is no longer doing so.
TRIM_MEMORY_COMPLETE - the process is nearing the end of the background LRU list.
Which are the cases for most of what you asked.
In the same method you can also catch TRIM_MEMORY_RUNNING_CRITICAL which will alert you to a case where the system has no memory and special actions must be taken immediately.
This method has made my development life much better in similar cases.
If you just need to do some cleanup, no matter how the activity is closed, you should be able to use a combination of onSaveInstanceState() and onDestroy(). One of those should be called no matter what. Maybe have a boolean cleanupDone in your activity, which is set whenever one of the two finishes.
Concerning saving of user data, have a look at Saving Persistent State:
Google suggest a
"edit in place" user model
That is: save as soon as the user creates new data, at the latest in onPause(). This does not mean that you need to recreate the data in onResume(), just that it should have been saved.
By the way: onStop() can be skipped only on pre-Honeycomb devices, that is, as of June 2015, less than 6 % of all devices. Still, onSaveInstanceState() should be called if either onDestroy() or onStop() are omitted.
As far as I gone with android,
1 When your apps crashes every resource relevant to it are destroyed.
2 When the device changes configuration resulting the Activity to be destroyed and recreated.
3 When apps running in background and Android kill it due to running on Low Memory
apart from these the other callback method are called i e
1 when another Activity come in front , or your device locks ..etc
In all case according to your requirement you can release all your resources in onDestroy and cancel the Thread and Asyntask and stop all the services etc .if you want your task remain paused and alive while on destroy called then you can save the configuration and retain it while onCreate is called again by check is null or not.
I run my android app, and when I press home button and come back to the app. Everything is maintained (the score, the state ..etc). assume it goes to OnPause the OnResume.
However, when I get a phone call while running my app, then my app state is reset (score is gone ..etc).
Why is that? Shouldn't it go through the onPause/OnResume as well?
When you get a phone call, it does go through onPause and onStop and when it is brought to the front again it goes through onStart and onResume. It may also be going through onDestroy which will cause it to go through onCreate when you bring it back. Suggest putting Log statements in each of the lifecycle methods to see which are getting called (or breakpoints in the debugger). Then you'll know what approach to take to resume your game.
In reality, you should implement the app such that it can go through onDestroy and recover when starting up again in the way you want.
When your app goes into the background, the Android OS decides if it should kill the app based upon current factors (e.g. available memory). If there are insuffuicient resources to maintain an app in the onPaused() state then they are destroyed (onStop() followed by onDestroy()).
Shouldn't it go through the onPause/OnResume as well?
Based upon the above and documentation, then yes it does go into onPause but then it goes into the other phases afterward.
Here is a handy image to help from the documentation that i know you read.
I'm running a countdowntimer in a fragment and everytime I press the back button onDestroy() is called and kills my countdowns. When I launch my app again a new activity has started and the countdowns are gone.
onDestroy() isFinished() returns true.
This wont happend if I press the home button.
How can I keep this from happening? Use services? Set flags? override the back button? I'm lost here.
The destruction of your activity is out of your control. It fully depends on the garbage collector. If it needs to clean up memory, and your activity is in the background, it will destroy it most likely.
You should use a service with startForeground(...) to make sure it will only be destroyed when it is absoslutely necessary. Also don't forget to acquire a WakeLock in your service, if you want to keep it alive while the screen is locked.
You are breaking the normal Android lifecycle with this approach, if the user presses back is because he wants to leave your app no matter what.
But anyway, you can avoid the behavior overriding onBackPressed and make the Back key acts like the Home key. Just have a look here Override back button to act like home button
When the Back Button is pressed the activity/process is destroyed. So yes to get around this use a Service, if its vital that this timer keep running running then use a Foreground Service (requires a constant Notification). A Foreground Service can not be destroyed, where normal Service can be if system memory is low and needs to be reclaimed. In my experiences this does not happen very often (especially on new devices).
Your timer is running in the context of the Activity, so when the activity is destroyed so is the timer. When home is pressed the activity is put into a paused state, hence the different actions.
Move to a background service which can then be started when required and will continue running in the background when the activity is destroyed. Be aware that even though you have a background service it may still get killed by the device if the memory is needed so you will need to handle that as well.
Sync the countdown timer with the device time. That way if the service is destroyed you can then re-sync the countdown time using the devices current time.
Also take a look at the AlarmManager, which will be useful in this situation - http://developer.android.com/reference/android/app/AlarmManager.html