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
Related
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.
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'm trying to get the main activity for my app to finish (not remain an active application in background) while keeping the process alive for a service.
If the user presses the home button and leaves my app or another activity is launched from outside of my app, I want the activity to be closed and NOT listed as an active application.
It is important, however, that the process stays alive. I don't want my background service to die as well.
What's the best way to go about doing this?
You should not forcibly close the application as the system does well in handling this itself. Instead you should call finish() to signal that the app is done and can be disposed of(your service will continue running).
By default Services don't have a UI. Once started they run until they crash or are killed . The user can close your app and launch a new one and the Service will persist.
Activities on the other hand are only running when they are visible. When the user navigates to another activity the previous activity is paused, stopped, or killed.
A simple way to do what you've briefly described above would be to create an Activity that starts a Service. That way when use navigates away form your Activity the Service will keep running in the background.
If you want your activity to die completely whenever a new Activity comes into view simply put a call to finish() in the onPause() or onStop() methods for your activity (which ever is more appropriate for your app).
could you suggest me how can I make my app does not go on pause?
Thanks
Unfortunately, you essentially have no control over the state of your main activity. onPause() will get called anytime you application loses the foreground. You can look here to get a general idea of how life cycles work. You can use a service to keep executing tasks even while your application is in the background. It would also be a good idea to save state anytime onPause() is called. That way the user can resume your application smoothly, even if it is eventually killed by the os.