Service
A Service
is an application component that can perform long-running operations in the background, and it doesn’t provide a user interface. Another application component can start a service, and it continues to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service can handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
By default, a service runs in the same process as the main thread of the application. If we have to implement complex logic, with longtime processing, we have to take care of creating a new thread, otherwise, the Android service runs on the main thread and it could cause ANR problem.
Services run with a higher priority than inactive or invisible activities and therefore it is less likely that the Android system terminates them. Services can also be configured to be restarted if they get terminated by the Android system once sufficient system resources are available again.
These are the three different types of services: Foreground, Background, Bound.
- Background: A background service performs an operation that isn’t directly noticed by the user. For example, if an app used a service to compact its storage, that would usually be a background service.
- Bound: A service is bound when an application component binds to it by calling bindService(). A bound service offers a client-server interface that allows components to interact with the service, send requests, receive results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.
- Foreground: A foreground service performs some operation that is noticeable to the user. For example, an audio app would use a foreground service to play an audio track. Foreground services must display a Notification. Foreground services continue running even when the user isn’t interacting with the app.
You must declare all services in your application’s manifest file, just as you do for activities and other components.
To declare your service, add a <service>
element as a child of the <application>
element. Here is an example:
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
The basics
To create a service, you must create a subclass of Service
or use one of its existing subclasses. In your implementation, you must override some callback methods that handle key aspects of the service lifecycle and provide a mechanism that allows the components to bind to the service, if appropriate. These are the most important callback methods that you should override:
onStartCommand()
- The system invokes this method by callingstartService()
when another component (such as an activity) requests that the service be started. When this method executes, the service is started and can run in the background indefinitely. If you implement this, it is your responsibility to stop the service when its work is complete by callingstopSelf()
orstopService()
. If you only want to provide binding, you don’t need to implement this method.onBind()
- The system invokes this method by callingbindService()
when another component wants to bind with the service (such as to perform RPC). In your implementation of this method, you must provide an interface that clients use to communicate with the service by returning anIBinder
. You must always implement this method; however, if you don’t want to allow binding, you should return null.onCreate()
- The system invokes this method to perform one-time setup procedures when the service is initially created (before it calls eitheronStartCommand()
oronBind()
). If the service is already running, this method is not called.onDestroy()
- The system invokes this method when the service is no longer used and is being destroyed. Your service should implement this to clean up any resources such as threads, registered listeners, or receivers. This is the last call that the service receives.
If a component starts the service by calling startService()
(which results in a call to onStartCommand()
), the service continues to run until it stops itself with stopSelf()
or another component stops it by calling stopService()
.
If a component calls bindService()
to create the service and onStartCommand()
is not called, the service runs only as long as the component is bound to it. After the service is unbound from all of its clients, the system destroys it.
The Android system stops a service only when memory is low and it must recover system resources for the activity that has user focus. If the service is bound to an activity that has user focus, it’s less likely to be killed; if the service is declared to run in the foreground, it’s rarely killed.
onStartCommand()
requires we return an Integer as result. This integer represents how the Service should be handled by the OS:
- START_NOT_STICKY - If the system kills the service after
onStartCommand()
returns, do not recreate the service unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs. - START_STICKY - If the system kills the service after
onStartCommand(
) returns, recreate the service and callonStartCommand()
, but do not redeliver the last intent. Instead, the system callsonStartCommand()
with a null intent unless there are pending intents to start the service. In that case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands but are running indefinitely and waiting for a job. - START_REDELIVER_INTENT - If the system kills the service after
onStartCommand()
returns, recreate the service and callonStartCommand()
with the last intent that was delivered to the service. Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.
Service lifecycle
The lifecycle of a service is much simpler than that of an activity. However, it’s even more important that you pay close attention to how your service is created and destroyed because a service can run in the background without the user being aware.
The service lifecycle—from when it’s created to when it’s destroyed—can follow either of these two paths:
-
A started service. The service is created when another component calls
startService()
. The service then runs indefinitely and must stop itself by callingstopSelf()
. Another component can also stop the service by callingstopService()
. When the service is stopped, the system destroys it. -
A bound service. The service is created when another component (a client) calls
bindService()
. The client then communicates with the service through anIBinder
interface. The client can close the connection by callingunbindService()
. Multiple clients can bind to the same service and when all of them unbind, the system destroys the service. The service does not need to stop itself.
These two paths aren’t entirely separate. You can bind to a service that is already started with startService()
. For example, you can start a background music service by calling startService()
with an Intent that identifies the music to play. Later, possibly when the user wants to exercise some control over the player or get information about the current song, an activity can bind to the service by calling bindService(
). In cases such as this, stopService()
or stopSelf()
doesn’t actually stop the service until all of the clients unbind.
Links
https://developer.android.com/guide/components/services
https://www.vogella.com/tutorials/AndroidServices/article.html
https://www.survivingwithandroid.com/android-service-tutorial-2/