Sometimes, we have to execute a task that must continue to run even if the user switches to another app or activity.
To be able to execute a task, even if the user switches away, we use a Service
instance:
Service
, and in most cases, we can use an IntentService
instance:[Service] public class XamarinService : IntentService { protected override void OnHandleIntent(Intent intent) { // some long-running task } }
StartService()
method on the Context
type:StartService(new Intent(this, typeof(XamarinService)));
var intent = new Intent(this, typeof(XamarinService)); intent.PutExtra("MyKey", "MyValue"); StartService(intent);
string value = null; if (intent.HasExtra("MyKey")) value = intent.GetStringExtra("MyKey");
Some tasks take fairly long to execute or may be a continuous execution. If normal threads are used, they are not terminated and will be leaked if the activity is killed or paused.
Services are used as they are independent of other app components and have their own lifecycle. They can be used to perform tasks and the various activities can interact with them. Services stop automatically when they complete the task, or they can be stopped by another component.
Some of the most common tasks performed by services are network or I/O operations. By delegating downloads or file processing to a background service, the user and the app are free to continue working. When the task has completed, the service can inform the user, who can then decide to continue the last task.
Another task can be to play music. The service can be started with a playlist and then left to go on ahead. When the user wants to control playback, messages can be sent to the service. This frees up the app for navigation and filtering, without having to worry about playing audio. The same goes for the service, which now no longer has to worry about any UI operations and can focus on its task.
Services inherit from the Service
type either directly or indirectly. For most simple cases of executing a task in the background, we can use the IntentService
instance. This type of service starts from an Intent
instance and runs the task in a new thread in the background. As soon as the task is complete, the service is terminated.
This type of service is the best option if we don't need the service to handle multiple requests simultaneously. If multiple requests come in, they are queued up and executed one at a time. If the service is required to be able to handle simultaneous requests, we should inherit from the base Service
type.
All services must include the [Service]
attribute as this declares the service with the AndroidManifest.xml
file. This is then registered by the Android OS so that we can start the services using the StartService()
method or the BindService()
method. If we want to prevent the service from being accessed by other apps, we can explicitly set the Exported
attribute property to false
.
We override the OnHandleIntent()
method to perform the task. This happens on a new thread so we don't have to start our own. As soon as the task has completed and we exit the method, the service is terminated. If there are other requests in the queue, the process is repeated.
To start a service, we need to invoke the StartService()
method on the Context
type, such as the Activity
or BroadcastReceiver
instances. We pass an Intent
instance that defines the service to start as well as any extra pieces of data we wish to pass to the service. Data is passed via the extras mechanism of the Intent
instance through the PutExtra()
method on the intent itself. In the service, we can extract the extra data from the intent using the various GetXxxExtra()
methods.
The IntentService
instance does not process start requests simultaneously, but rather queues them and executes them one at a time. To handle simultaneous execution, we need to use the base Service
type.