The Service series consists of two parts. It mainly introduces how to use Service and how to use Service to achieve IPC communication. The focus of this article is on the use of services. Implementing IPC communication through Services will be explained in the next article.

What is a Service

According to the official introduction:

  1. A Service is not a thread. A Service usually runs in the main thread that is the host process. Therefore, to perform time-consuming operations in a Service, you need to start a thread inside the Service.
  2. Nor is it a separate process. The process in which the Service resides is the process in which the application resides unless the process name is specified when declared in the manifest file.

A Service exists for two purposes:

  1. Tells the system that the current program needs to do some processing in the background. This means that a Service can run in the background without a UI, regardless of whether the page that started it is destroyed, as long as the process is still running. It can be called by startService(). Note that the Service is always running unless it manually calls stopService() or automatically calls stopSelf() from within the Service.
  2. Programs open certain operations to the outside world through services. BindService () is related to Service calls, long-running connections and interactions, Service life cycles, and the components to which it is bound.

Service Lifecycle

public class MyService extends Service {

    @Override
    public void onCreate(a) {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return startCommandReturnId;
    }

    @Override
    public void onDestroy(a) {
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null; }}Copy the code

To explain this, we need to start with the implementation of the Service. We need to implement the abstract method onBind and override onStartCommand, which are described below.

As you can see from the above, there are three ways to start a Service:

  1. startService()
  2. bindService()
  3. At the same time call

The Service life cycle starts slightly differently in these ways.

StartService way

StartService () requires only an Intent parameter that specifies the Service to start

Intent intent = new Intent(MainActivity.this, MyService.class);
Copy the code
  1. When the startService() of the Service is called,

    • OnCreate () is called before onStartCommand().
    • If the Service is already started, call onStartCommand() directly
  2. When stopSelf() or stopService() is called, onDestroy() is executed, indicating the end of the Service lifecycle.

  3. StartService does not call onBind(). StartService can be called multiple times, and onStartCommand() is executed on each call. No matter how many times startService is called, stopService is called once. If startService is not called after stopSelf or stopService, the Service is always alive and running in the background.

  4. OnStartCommand returns three values

    • START_STICKY = 1: After the process running the service is killed, the system keeps the service status as the start state. The system tries to restart the service. When the service is restarted, the intent may be null.
    • START_NOT_STICKY = 2: The system does not restart the service after the process running the service is killed
    • START_REDELIVER_INTENT = 3: The system automatically restarts the service and delivers the previous intent

    START_STICKY is returned by default.

BindService way

Binding Service with bindService is a bit more complicated than startService. Since bindService is executed asynchronously, you need to build an additional ServiceConnection object to receive the state of bindService and specify the type of bindService.

//1. Define the object to communicate with, the object returned in onBind() of the Service.
public class MyBind extends Binder {
        public int mProcessId;
 }

//2. Define the ServiceConnection used to receive the recipient
mServiceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                // The service will call back the method after the binding is successful
                // If the service is restarted after an abnormal interruption, the change method will be called again
                MyService.MyBind myBinder = (MyService.MyBind) service;
            }

            @Override
            public void onNullBinding(ComponentName name) {
                //Service onBind() calls this method when it returns null. OnServiceConnected () is not called.
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                // Called when the service terminates abnormally.
                // Note that unbindService is not called}};//3. Bind to Service where necessary
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
Copy the code

BindService () can also be called multiple times. Unlike startService(), the callback method in ServiceConnection is not returned multiple times after the originating object has been successfully bound to the Service.

After bindService is bound to a Service, the Service life cycle ends when no object is bound to the Service. This process includes the destruction of the bound object or the unbindService() call.

StartService and bindService are both enabled

After startService and bindService are called, stopService and unbindService are called respectively to destroy onDestroy().

A Service must be destroyed only when it is not associated with any Activity and handles the stopped state.

IntentService

From the above introduction, we know that if stopService is not actively called when StartService is started, the Service will always run in the background. Also, if ANR exceptions are caused by time-consuming operations in a Service, IntentService is introduced to solve both problems. IntentService works well when we need to perform one-off, asynchronous operations.

IntentService Does not need to implement onStartCommand(), but onHandleIntent(). The real logic we need to deal with is in the implementation of onHandleIntent(), where IntentService internally automatically calls stopSelf() to shut itself down.

To prevent ANR exceptions, the implementation is actually quite simple, is to create a child thread, and in the child thread internal Looper to distribute the event, the specific code is not attached.

The next articleAndroid ServiceIPC communication through services will be introduced