An overview of the

Service is one of the four components of Android. Its main function is to perform operations in the background. Activities interact with users with a UI interface, while Service has no UI interface, and all operations are completed based on background running. A Service, like an Activity, can be called by another application and still run even if the user switches the application. A component that is bind to a Service can interact with data from the Service and can also interact with different processes (IPC). Services are commonly used for network requests, music manipulation, file I/O, etc.

Start the

A Service is usually started in one of two ways

startService

When a component (such as an activity) starts a Service by calling startService(). Once started, a Service runs independently in the background and can continue to run in the background even after the invoked component has been destroyed. Typically, a Service is started in this way when a single operation is required and the result of the operation does not need to be returned to the caller. For example, when an upload or download operation is complete, the Service should call stopService() or stopSelf() to terminate the operation.

bindService

When a component (such as an activity) starts a Service by calling bindService(). This method provides the interface of client-service, which enables the calling component to send requests and return results to the Service and set up inter-process communication (IPC). The Service is not destroyed as long as a component is bound to it. In addition, multiple components can bind to a Service at the same time, and the Service will be destroyed only when all bound components are unbound.

Although the two approaches are discussed separately, they are not mutually exclusive and can be bound once a Service is started using startService.

Note: Although the Service runs in the background, all operations are actually performed in the main thread. A Service is not started in a separate thread or process unless it is defined separately, but in the main thread. So this means that any operation that blocks the main thread (such as music playback or network requests) should be run on a separate thread, otherwise ANR can easily occur.

methods

When creating a Service, you must inherit the Service and override some of the main methods of the parent class to implement the function. The following is an introduction to the main methods

onStartCommand()

This function is called when a component (such as an activity or fragment) starts a Service by calling startService(). After this method is called, the Service is started and runs independently in the background. If this method is overridden, the developer needs to terminate the Service by calling stopSelf() or stopService() after the Service completes its operation. You do not need to override this method if the Service is only started by binding.

onBind()

This function is called when a component (such as an activity or fragment) starts a Service by calling the bindService() binding. When you implement this function, you must return a derived IBinder class that communicates with the Service. This function must be overridden by default, but if you don’t want to start the Service by binding, you can return NULL

onCreate()

This method is called to initialize one-off variables when the Service is first started. If the Service is already started, this method is not called again.

onDestroy()

The system calls this method when a Service no longer needs to be prepared for destruction. Note how threads, Listeners, and receivers are cleaned up when needed in a Service.

These are some of the ways to implement a Service.

If a component starts a Service by calling startService(), The Service runs in the background until stopSelf() is called inside the Service or a component calls stopService() to terminate the Service.

If a component starts a Service by calling bindService(), the Service runs in the background until the component is unbound. A Service is destroyed when there is no component binding

The following sections will show you how to create a Service using the two methods described above

Declare a Service in the Manifest

Like an Activity, all services must be declared in the Manifest as follows:

<manifest . >.<application . >
      <service android:name=".ExampleService" />.</application>
</manifest>Copy the code

Check the label’s official documentation for more information

Android: Exported is set to false in the

tag. This prevents other programs from starting your Service.

Start the Service by starting it

A component (such as an activity or fragment) calls the startService() method, and the system then calls the onStartCommand() method to start the Service in started mode.

When a Service is started in this form, its entire life cycle is completely independent and it can run indefinitely in the background, even if the component that started it has been destroyed. However, the developer should terminate the Service by calling stopSelf() or by calling stopService() from another component after the operation is completed.

An application component (such as an activity) can pass data between the component and the Service by passing an Intent to startService(). A Service is an Intent that is delivered via the onStartCommand() method of the system call to complete the data delivery process.

Note: The Service itself runs in the main thread by default, so if you want to do something in the Service that will block the thread, make sure you place it in a new thread.

The Android framework provides IntentServices for running asynchronous threads in the background.

IntentService

IntentService is a subclass of Service, and all requests are made in an asynchronous thread. If you don’t need a Service to handle multiple requests at the same time, IntentService will be the best choice. Simply inherit and rewrite the onHandleIntent() method in IntentService to perform background asynchronous thread operations with the incoming Intent.

IntentService provides the following functions:

  • An asynchronous thread is created to handle all messages sent from the program’s main thread toonStartCommand()The intents.
  • A queue pool was created to ensure that only one Intent was delivered at a timeonHandleIntent()Method to avoid multithreading problems.
  • Provide defaultonBind()Method that returns NULL
  • Provide defaultonStartCommand()The implementation of the Intent method places the incoming intent in a queue pool and then delivers it to the queueonHandleIntent()Do the processing

All developers need to do is implement onHandleIntent() and focus on what the Service does. Check out this article for more practical tips on IntentService.

If the developer needs to override other methods, such as onCreate(), onStartCommand(), and onDestroy(), make sure that the parent class is called to ensure that IntentService handles the thread life cycle correctly. Such as:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this."service starting", Toast.LENGTH_SHORT).show();
    return super.onStartCommand(intent,flags,startId);
}Copy the code
The system reclaims resources

When the system runs out of memory, it forces activities and services to be reclaimed to get more resources to the program or page that the user is interacting with. This requires the Service to restart automatically when resources are available. This is done with the return value of onStartCommand()

START_NOT_STICKY

When the system destroys a Service to reclaim resources, it does not automatically start the Service when the resources are sufficient again. Unless there is an Intent to send for processing. When your program can easily restart unfinished operations, this is the safest option to avoid starting a Service unnecessarily.

START_STICKY

When the system destroys a Service to reclaim resources, the Service is automatically started when the resource is sufficient again, and the onStartCommand() method is called again, but the last Intent is not passed. Instead, onStartCommand() is called with an empty Intent. Unless there is an Intent to send for processing.

START_REDELIVER_INTENT

When the system destroys a Service to reclaim resources, it automatically starts the Service when the resource is sufficient again, and calls onStartCommand() again, passing the last Intent to onStartCommand(). The corresponding intEnts in the queue are also delivered one at a time. This mode applies to services such as downloads.

Start Service

This method allows multiple components to perform the startService operation on the same Service at the same time, but if one of them calls stopSelf() or stopService(), the Service will be destroyed.

Intent intent = new Intent(this, HelloService.class);
startService(intent);Copy the code
Stop Service

When multiple components perform startService operations, you should not directly call stopSelf() or stopService() to terminate the Service, because this will affect other operations that have already initiated the request. Therefore, the onStartCommand() method accepts a startId, and when terminating a Service, the stopService(int) method is called to terminate only one specific request, thus protecting other requests from being affected.

Start the Service by using Bind

When an activity or other component in your application needs to interact with a service, or when some of your application’s functionality needs to be exposed to other applications, you should create a Bind service and use interprocess communication (IPC) to do this.

A Service lives only as long as it works for the bound application component, so the system automatically destroys the Service as long as no component is bound to it

Get the IBinder instance
Extend the Binder class

If the service is private to your application and runs in the same process as the client (as it usually is), you should create your interface by extending the Binder class and returning an instance of it from onBind(). Clients receive this Binder object and use it to directly access public methods available in Binder or even Services.

If your service is just doing some background work for your own application, this is the preferred technical solution. There is only one reason not to create interfaces this way, if the service is to be used by other applications or across multiple processes.

Use the Messenger

If you need an interface to work across multiple processes, you can use Messenger to create an interface for your service. In this way, the service defines a Handler that responds to various Message objects called Messages. This Handler is the basis for Messenger and the client to share the same IBinder, and it enables the client to send instructions to the service using the Message object Message. In addition, the client can define its own Message so that the service can send messages back.

This is the easiest way to perform interprocess communication (IPC) because Messenger queues all requests in a separate process, so you don’t have to design the service in thread-safe mode.

Use AIDL

Most applications should not use AIDL to create a BIND service, as this may require multithreading capabilities and make the code more complex. Therefore, AIDL is not suitable for most applications, and this article does not discuss how to use its content in services. If you are sure you need to use AIDL directly, refer to the AIDL documentation.

Extend the Binder class

If your service is only for native applications and does not work across processes, you can implement your own Binder classes so that your clients can directly access the public methods in your service.

Note: This approach is only useful if the client and service are in the same application and process, which is the most common case. For example, a music app that needs to tie an activity to its own background music playing service would be great.

Here are the setup steps:

  1. In your service, create an instance of Binder that implements one of the following:
    • Contains public methods that can be invoked by clients
    • Returns the current Service instance, which contains public methods that can be invoked by clients
    • Alternatively, it returns an instance of another class that contains a Service class that contains public methods that can be called by clients
  2. Return this instance of Binder from the callback method onBind()
  3. On the client side, the Binder is received in the callback method onServiceConnected() and calls the bound service with the provided methods

    Note: The service and client must be in the same application so that the client can properly cast the returned object and invoke its API. The service and client must also be in the same process, because you cannot perform any marshalling across processes this way.

In specific practical cases please check ApiDemos LocalService. Java classes and LocalServiceActivities. Java.

Use the Messenger

Here’s an overview of how to use Messenger:

  • The service implements aHandlerFor the client to receive a callback each time it is invoked
  • thisHandlerUsed to create aMessengerObject (which is a pairHandlerA reference)
  • thisMessengerObject to create aIBinderThe service returns it to the client in onBind()
  • The client withIBinderMessengerReference serviceHandler), which clients use to send message objects to the serviceMessage
  • Service receivesHandlerEach message inMessage— specifically, received in the handleMessage() method

In MessengerService. Java (services) and MessengerServiceActivities. Java (client) routines, you can see how about the practical example of Messenger.

The Service life cycle

Service life cycle diagram