Is an android service guaranteed to call onDestroy()?
Asked Answered
O

2

64

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?

Officinal answered 29/8, 2011 at 22:34 Comment(0)
H
40

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.

Heavyarmed answered 30/8, 2011 at 0:29 Comment(7)
That link was what I wanted to see. Thanks! I was just confused by looking at the life cycle diagrams, because one showed the case of the process being killed and the other did not. I thought that the latter was implied, however. Just didn't know where to verify my thoughts.Officinal
how then to get a notification when you need to clean a service up before shutdown? for instance, i want to cache some state and flush it to storage before being shut down; if i am never told i am shutting down, i will lose my state - not good!Serve
@Serve Consider flushing it to storage periodically/whenever your data changes. It's a reasonable question. In fact if my simple answer doesn't satisfy you, it'd be worth posting your own question about this to get some good in-depth answers.Heavyarmed
@kabuko: no it's good to know this for sure. my original reading of the documentation suggested onDestroy would be called so i decided it would save a lot of battery and flash erase cycles to not flush whenever state changes, but... so much for that idea. i have decided to split my state so the infrequent changes (<20 times/day) go to internal flash while the more frequent stuff (up to 1 Hz) go to external flash which can be swapped out if needed. still unhappy about the battery thing though.Serve
"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." How do you know that? Is this documented somewhere?Synecology
@MarianPaździoch I don't know if this is documented somewhere, but I assure you that's exactly what happens - onDestroy is not being called.Alphard
Then by what method should we call to terminate the service? StopService might not call onDestroy method, then how does the service is killed?Wow
O
15

There are two things to consider:

  1. 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).

  2. 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).

Outdistance answered 26/2, 2015 at 15:22 Comment(12)
Once neither of these situations hold != guaranteed != alwaysAlphard
So? What's this comment is all about? You quoted part of official docs, so?Synecology
I quoted same part of official docs which you did. It says that Once neither of these situations hold, the service's onDestroy() method is called. It still means that even when both of situations hold service won't be just killed without onDestroy being called. And in practice that happens to be true.Alphard
Sorry, I meant: "it still means that even when both of situations hold service might be just killed without onDestory being called"Alphard
What? It means: onDestroy is called when service is stopped AND there are no "more connections to it with the Context.BIND_AUTO_CREATE flag".Synecology
Yes, it's called when Service is stopped in a normal way (through stopSelf for instance). It's not always called when Service is killed (by the system)Alphard
"It's not always called when Service is killed (by the system)." You mean when Android OS kills Service process? Of course it's not called in that case. Anyway what would be the purpose of calling onDestroy right before everything is destoryed anyway.Synecology
Now funny (not really) thing is that it might happen not only when whole process is killed. In our app we have two services, one is running in foreground (see startForeground) and therefore kept alive by the system. Second service is background Service (although started with START_STICKY). System kills the second service without calling onDestroy although first service is still alive. Both run in the same process.Alphard
I think you're doing sth wrong as I've never experienced such behavior - Android either kills whole process (and you don't have to worry about a thing as all your resources are reclaimed anyway) or destroys a Service (an calls onDestroy() on it - you have release your resources by yourself as the process is still running). If it wouldn't work this way then it would be pointless as nobody would be able to release the resources and it would lead to memory leaks. Absurd!Synecology
This makes sense, maybe I was not right about 1 service being destroyed and another one kept alive. Please, add your last comment to the body of the answer so: 1. it will be more complete, 2. I can change my vote on itAlphard
Done, consider also down-voting on accepted answer as it's not an answer at all :)Synecology
Now it's a cool answer. Although accepted answer is also correct, as basically onDestroy is indeed not guaranteed to be called (just as described in your answer - if process is killed).Alphard

© 2022 - 2024 — McMap. All rights reserved.