I'm aware that a Service's onDestroy() method may never be called but can someone tell me when such a scenario might occur? I'm especially interested in whether it's possible for a Service to be killed, yet its VM would continue to run.
I ask because I have a service that registers ContentObservers in the service's onStartCommand() method and unregisters them onDestroy(). If the service's onDestroy() method was never called because the whole VM was killed (along with the observers it created,) that would be fine. But I'm wondering if it's possible for a service to "go away" without onDestroy() being called, while the observers it created would live on and continue to receive changes.
I'm aware that a Service's onDestroy() method may never be called but can someone tell me when such a scenario might occur?
Here are three off the top of my head:
If the user Force Stops you from the Settings app
If Android needs RAM in a hurry (e.g., to process an incoming phone call) and elects to terminate your process to free up that RAM
You terminate the process from DDMS
Also, if your service crashes with an unhandled exception somewhere, Android may consider the service to be defunct and skip onDestroy(). I'm not sure about this one, as I haven't specifically tried it.
But I'm wondering if it's possible for a service to "go away" without onDestroy() being called, while the observers it created would live on and continue to receive changes.
Other than the unhandled-exception possibility I mention above, I am reasonably certain that if the process will be terminated in the conditions where onDestroy() is not called.
Also if the app is reinstalled/updated , ondestroy() is never called.
Related
I asked this question Is onDestroy called only if you explicitly call finish() ?? or are there any exceptions?
now in answer I got that
where are the cases where ondestroy() not get called up.
If you crash with an unhandled exception
If your process is terminated in an urgent fashion (e.g., the system needs RAM to process an incoming phone call)
If the user clicks "Force Stop" on your app's screen in Settings
On a few devices, if the user terminates your process using a manufacturer-supplied task manager
Now as for these cases as onDestroy() will not get called so I thought to try onStop()
But as for all above cases even if i will write code in onStop() to unregister the receiver then still it will not get called because of which my receiver will left registered.
So now my question is where can i write my code to unregister the receiver when any of the above four cases will happen.
Also if it is not possible then i guess as for both onStop() and
onDestroy() for these four cases we cannot rely on them to
unregister our receiver then why in Android docs it is written to
not use onDestroy() even both are equally unreliable ??
Shouldn't they say that both functions should not be used for releasing resources(unregistering receivers).
Solution - According to commonsware answer
In all three of these cases, your process is gone, and therefore your BroadcastReceiver is also gone. There is nothing to unregister.
So as the broadcastreceiver is also gone, so there won't be any need to unregister the receiver, So i think there won't be any problem in all these three cases if i will use onDestroy() to unregister the receivers.
Only for the 1 Case i will try to implement my own top-level uncaught exception handler, as onDestroy() won't be called for that.
But as for all above cases even if i will write code in onStop() to unregister the receiver then still it will not get called
For three of the above cases, in the vast majority of cases, onStop() will be called:
If your process is terminated in an urgent fashion (e.g., the system needs RAM to process an incoming phone call)
If the user clicks "Force Stop" on your app's screen in Settings
On a few devices, if the user terminates your process using a manufacturer-supplied task manager
Android will not terminate a process that is in the foreground from a UI standpoint. In all of these cases, the vast majority of the time, your app will not be in the foreground, and therefore onStop() will have been called.
Moreover, in all three of these cases, your process is gone, and therefore your BroadcastReceiver is also gone. There is nothing to unregister. This is one of the reasons why tend not to worry too much about these scenarios. onDestroy() is for cleaning up things that might prevent your activity from being garbage-collected, and if your process is terminated, your activity and all other objects are all gone.
The one scenario from the four that remains is if your app crashes with an unhandled exception. In that case, your app is seriously messed up. If you have your own top-level uncaught exception handler, you might consider terminating your own process as part of cleanup.
I would like to issue broadcast when service goes down. What callback is guaranteed to run when this happens? I want other apps to know its down, I cannot take a chance that it goes down and no one knows about it. So at point in the service lifecycle (which method) should I issue the sendBroadcast(ImGoingDown)? For example, how soon would onDestroy() be called?
While most answers here are aiding in the onDestroy approach, there are many events on your service being destroyed that you cannot intervene. For instance, if the user has force closed your application, your service is destroyed, but onDestroy will NOT be executed.
On a common scenario, your service would be destroyed when it has ran out of operations (mostly know as finished), when no other process that are bound to the service, or when its stopSelf()is executed, and most common, when the device is running low on RAM.
onDestroy would be the scenario where you can restart it.
As a suggestion, if the device has killed your process due to low RAM, dont restart it right away. set a Handler or AlarmManager to start it a bit later (so the lack of memmomry dont execute in back again.)
You can fire the broadcast in onDestroy(). This is the last call the service receives before getting destroyed. Service lifecycle ends with this call.
If you are running a background service that means you must be doing something in background, sending broadcast from onDestroy() might not be a best practice.
Think, your service gets destroyed because the task you wanted to run is completed, then you might don't want to send a broadcast in that case. You want to send a broadcast only when the service is killed right? So the better approach is to setting a boolean, say isTaskFinised, and if it returns false only then your onDestroy() should send a broadcast.
#Override
public void onDestroy(){
if(!isTaskFinished){
//send a broadcast
}
}
Android documentation says (in http://developer.android.com/training/basics/activity-lifecycle/stopping.html):
In extreme cases, the system might simply kill your app process without calling the activity's final onDestroy() callback, so it's important you use onStop() to release resources that might leak memory.
Sounds like it is wrong. How could killed process leak memory?
Suppose you started a service in your onStart() method, and you intend to stop that service when the user gets out of the Activity.
If you put the code to stop the service in onDestroy(), that code may never get called, which can leave that service running until Android decides to kill it (which may not happen for a while, if ever). That running service is and example of leaking memory/resources outside your application.
You should put cleanup code like that in a method that is guaranteed to be called.
Note that a process is killable after onPause() has been called, so onPause() is really the place you want to do cleanup that absolutely must happen.
(See table 1 in https://developer.android.com/guide/components/activities.html for details on the Activity lifecycle)
Another thing that might be really bad to leak: Bluetooth discovery or location reporting (GPS or network-based) turned on but not off as soon as possible - very bad for battery life.
I'm confused why anyone would ever override Activity.onDestroy() instead of onPause() if 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,
I see much code that overrides onDestroy() despite this warning. Why?
Why override Activity.onDestroy() if it isn't reliably called?
It's not that it isn't reliably called... it's just that it isn't the only way the Activity can be killed. The Android system might trash your entire process without giving the ActivityManager the chance to call onDestroy() if your device begins to lack memory resources.
For this reason, you shouldn't ever rely on onDestroy() being called, and you should always save persistent state in onPause.
Objects held by the activity will get destroyed if the process is killed directly. If the process is not killed (and onDestroy() is called) then you will have to manually release the objects if needed. E.g, when the process is killed, a Cursor will be destroyed, but if the process is not destroyed and you repeatedly enter the activity there will be resource leakage.
The life cycle diagram of an Activity on an android does not guarantee that onDestroy() would be called, but that the process may be killed and the Activity is removed abruptly. The life cycle diagram of a Service on an android does guarantee that onDestroy() would be called. So I have two questions relating to this difference.
Firstly, if the Service is part of the same process as the Activity, is the Service onDestroy() called, though the Activity onDestroy() is not called? I would think not, as "killing a process" suggest that the operating system is stopping its threads and releasing its resources.
And if that is the case, can a Service-only-process be abruptly killed by the OS?
I'm not sure where you're seeing that a Service is guaranteed to have onDestroy() called. As far as I know, this isn't the case. If you read this page of the docs, it describes the conditions in which a service could be killed. So if you're asking if a process which hosts both an activity and service is being killed, will onDestroy() be called on the service (but not on the activity) then the answer is no; a service's onDestroy() will not necessarily be called. As to whether a service-only process can be abruptly killed by the OS: yes, it can. This is especially true when you have a lot of work to do, and your onStartCommand call only queues up the work to do asynchronously. Then the service will be spending the majority of its time not in the protected onCreate, onStartCommand or onDestroy methods.
There are two things to consider:
Android might decide to shut down a process at some point, when memory
is low and required by other processes that are more immediately
serving the user. Application components running in the process that's
killed are consequently destroyed. A process is started again for
those components when there's again work for them to do. Source
In this case onDestroy() is not called as the Android OS will reclaim resources anyway (this is a basic task of the OS in general).
A service can be both started and have connections bound to it. In
such a case, the system will keep the service running as long as
either it is started or there are one or more connections to it with
the Context.BIND_AUTO_CREATE flag. Once neither of these situations
hold, the service's onDestroy() method is called and the service is
effectively terminated. All cleanup (stopping threads, unregistering
receivers) should be complete upon returning from
onDestroy(). Source
So when the Android OS notices that the Service has finished its job and is not needed anymore it will be destroyed. The OS gives the app a chance to release the Service's resources to prevent memory leaks. In this case onDestroy() is called as this is the place where the app can release its resources. Of course in this case the application's process stays untouched (as there may be other Services/Activities running in it).