Chapter 28 Background Services
Let’s see what lifecycle callbacks a service has.
A service’s lifecycle
For a service started with startService(Intent), life is fairly simple. There are three lifecycle
callbacks.
- onCreate(...) – called when the service is created.
- onStartCommand(Intent, int, int) – called once each time a component starts the service with
startService(Intent). The two integer parameters are a set of flags and a start ID. The flags
are used to signify whether this intent delivery is an attempt to redeliver an intent or is an attempt
to retry a delivery that never made it to (or never returned from) onStartCommand(Intent, int,
int). The start ID will be different for every call to onStartCommand(Intent, int, int), so it
may be used to distinguish this command from others. - onDestroy() – called when the service no longer needs to be alive.
The onDestroy() callback is called when the service stops. This can happen in different ways,
depending on what type of service you have written. The type of service is determined by
the value returned from onStartCommand(...), which may be Service.START_NOT_STICKY,
START_REDELIVER_INTENT, or START_STICKY.
Non-sticky services
IntentService is a non-sticky service, so let’s start there. A non-sticky service stops when the
service itself says it is done. To make your service non-sticky, return either START_NOT_STICKY or
START_REDELIVER_INTENT.
You tell Android that you are done by calling either stopSelf() or stopSelf(int). The first
method, stopSelf(), is unconditional. It will always stop your service, no matter how many times
onStartCommand(...) has been called.
The second method, stopSelf(int), is conditional. This method takes in the start ID received in
onStartCommand(...). This method will only stop your service if this was the most recent start ID
received. (This is how IntentService works under the hood.)
So what is the difference between returning START_NOT_STICKY and START_REDELIVER_INTENT? The
difference is in how your service behaves if the system needs to shut it down before it is done. A
START_NOT_STICKY service will die and disappear into the void. START_REDELIVER_INTENT, on the
other hand, will attempt to start up the service again later, when resources are less constrained.
Choosing between START_NOT_STICKY and START_REDELIVER_INTENT is a matter of deciding how
important that operation is to your application. If the service is not critical, choose START_NOT_STICKY.
In PhotoGallery, your service is being run repeatedly on an alarm. If one invocation falls through the
cracks, it is not a big deal, so: START_NOT_STICKY. This is the default behavior for IntentService. To
switch to using START_REDELIVER_INTENT, call IntentService.setIntentRedelivery(true).
Sticky services
A sticky service stays started until something outside the service tells it to stop by calling
Context.stopService(Intent). To make your service sticky, return START_STICKY.