Aidl introduction----- common reasons and solutions for stepping on pits

table of Contents

0. Preface

1. Introduction to Directory Structure

2. Introduction to the interface and each button function

3. Introduction to the execution logic of each button code

4. Code Analysis

5. Stepping on pits and solutions

6. Project Demonstration


0. Preface

Recently, AIDL has been used in development. I have read many articles in this area on the Internet. They are all very good, but when I reproduce it, I will encounter various problems, so I decided to write an article in this area and provide some easy-to-follow articles. The reasons and solutions for the pits are limited. If there are analysis errors, I hope everyone can actively put forward them. (Note: the red font is a more important knowledge point)

1. Introduction to Directory Structure

First introduce the directory structure of this article (if you want to know more about the role of each common directory in Android Studio, please see ( placeholder, expected to be completed by 2020.08) ). The directory structure has already included all the important files involved in this article. They are listed, and the role of these files in the article will be explained clearly later. The AidlDemo project contains two sub-modules: client and aidlservice. The main part of the client is MainActivity and GeneralService. The function of this module is to show how MainActivity starts and ends GeneralService, and how to bind and unbind GeneralService. In addition to calling the service of its own module, the MainAcivity can also bind and unbind the AidlService in the aidlservice through the AIDL interface. It should be noted that the MainActivity in the aidlservice module in this article is not the core and can be deleted.

AidlDemo
   |--client
   |     |--build
   |     |     |--generated
   |     |     |      |--aidl_source_output_dir
   |     |     |                  |--debug
   |     |     |                       |--compileDebugAidl
   |     |     |                                  |--out
   |     |     |--outputs                             |--aidl
   |     |          |--apk                                 |--IAidlService.java-------(1)
   |     |              |--debug               
   |     |                   |--client-debug.apk--------------------------------------(2)                                      
   |     |--src
   |     |   |--main
   |     |        |--aidl
   |     |        |   |--IAidlService.aidl--------------------------------------------(3)
   |     |        |--java
   |     |        |    |--com.zhouxi.client
   |     |        |            |--GeneralService.java---------------------------------(4)
   |     |        |            |--MainActivity.java-----------------------------------(5)
   |     |        |--res
   |     |        |   |--layout
   |     |        |         |--activity_main.xml--------------------------------------(6)
   |     |        |--AndroidManifest.xml----------------------------------------------(7)
   |     |--build.gradle--------------------------------------------------------------(8)
   |     
   |--aidlservice
   |     |--build
   |     |     |--generated
   |     |     |     |--aidl_source_output_dir
   |     |     |                  |--debug
   |     |     |                       |--compileDebugAidl
   |     |     |                                |--out
   |     |     |--outputs                           |--aidl
   |     |           |--apk                              |--IAidlService.java---------(9)
   |     |               |--debug
   |     |                    |--aidlservice-debug.apk-------------------------------(10)
   |     |--src
   |     |   |--main
   |     |        |--aidl
   |     |        |   |--IAidlService.aidl-------------------------------------------(11)
   |     |        |--java
   |     |        |   |--com.zhouxi.service
   |     |        |             |--AidlService.java----------------------------------(12)
   |     |        |             |--MainActivity.java---------------------------------(13)
   |     |        |--res
   |     |        |   |--layout
   |     |        |         |--activity_main.xml-------------------------------------(14)
   |     |        |--AndroidManifest.xml---------------------------------------------(15)
   |     |--build.gradle-------------------------------------------------------------(16)
   |
   |--build.gradle-------------------------------------------------------------------(17)
   |--setting.gradle-----------------------------------------------------------------(18)
                                        
                                        AidlDemo目录结构

2. Introduction to the interface and each button function

The first picture simulates the client client, which contains six buttons: START SERVICE, STOP SERVICE, BIND SERVICE, UNBIND SERVICE, BIND AIDL SERVICE and UNBIND AIDL SERVICE.

  • The first two buttons provide the startup and shutdown of GeneralService in the same module, and there is no binding relationship between the two.
  • The two buttons in the middle provide the function of binding and unbinding GeneralService in the same module.
  • The next two buttons provide the function of MainActivity in client to bind and unbind AidlService in aidlservice using AIDL interface.

(Note: The MainActivity of aidlservice is not necessary. AidlService can be used as a background service alone. Therefore, the aidlservice shown on the right does not require an interface. The two buttons are specially designed mainly for debugging)

serviceclient

3. Introduction to the execution logic of each button code

3.1 START SERVICE和STOP SERVICE 

This service startup method is only to start the GeneralService, but there is no binding relationship between the two. That is to say, when the MainActivity is no longer running, the GeneralService will not be closed . Of course, the MainActivity can provide the function of manually closing the GeneralService.

  • START SERVICE only needs to put the current class name and the class name to be jumped into the intent, and directly execute startService(intent) to start the GeneralService.
Intent intent = new Intent(this, GeneralService.class);
startService(intent);
  • STOP SERVICE is similar to starting the service, just change startService to stopService.
Intent intent = new Intent(this, GeneralService.class);
stopService(intent);

3.2 BIND SERVICE和UNBIND SERVICE

Unlike the simple opening and closing of the service above, this method of starting the service binds the service cycle of the GeneralService to the MainActivity. Once the MainActivity is closed, the GeneralService will also be closed (note: on the contrary, when the GeneralService is closed, the MainAcitivy does not Will be closed) . Specifically:

  • BIND SERVICE Binding service requires bindService, which requires three parameters: Intent, ServiceConnection, and flag. Among them, Intent mainly records the information passed between MainActivity and GeneralService. Since both belong to the same module, that is, in the same apk, you only need to pass in the class name of both (note this and use the AIDL interface to cross The difference between apk calls).
Intent intent = new Intent(this, GeneralService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
  • The role of ServiceConnection is to supervise the binding status of the two, and to receive the IBinder object passed from GeneralService. ServiceConnection implements onServiceConnected and onServiceDisconnected. After onServiceConnected is successfully bound, it will return an IBinder object.
public ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, "onServiceConnected: bind GeneralService success.");
            GeneralService.GeneralBinder generalBind = (GeneralService.GeneralBinder) service;
            generalBind.readWriteInfo();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "onServiceDisconnected: bind GeneralService fail.");
        }
    };
  • And this object is an internal class of GeneralService.
class GeneralBinder extends Binder {
    public void readWriteInfo() {
        String info = readServiceInfo();
        Log.e(TAG, "getInfo: readServiceInfo success, the information: " + info);
        writeServiceInfo("This is writeServiceInfo in GeneralBinder.");
        Log.e(TAG, "getInfo: writeServiceInfo success.");
    }
}
  • Why do we need to define an inner class? Because in general MainActivity cannot directly access the methods in GeneralService, an internal class is defined through GeneralService. The internal class can define some methods. These methods call the methods accessed by GeneralService, and MainActivity indirectly implements the methods for accessing GeneralService.
  • UNBIND SERVICE needs to use unbindService to unbind. The input parameter is only ServiceConnection. It should be noted that only the onUnbind and onDestroy methods in GeneralService will be executed when unbinding, while the onServiceDisconnected in ServiceConnection is only returned when an error occurs during binding. This method is not executed when binding .
unbindService(aidlServiceConnection);

3.3 BIND AIDL SERVICE和UNBIND AIDL SERVICE 

This binding method is similar to the above binding method, the difference is that the above MainActivity and GeneralService are in the same module, that is, the same apk, MainActivity can easily find the GeneralService by directly entering the class name when starting the GeneralService position. When MainActivity and AidlService are in different apk, that is to say, if an apk wants to access the service functions in another apk, it needs to use the AIDL interface to provide an intermediate bridge to realize the function call between the apk. (Note: The apk does not necessarily have an interface. A single AidlService can also be packaged into an apk as a background service. This is related to the directory where the apk is installed, such as the system directory. The apk in this directory cannot be seen on the mobile desktop. Visible system services, but root permissions are required during the installation process. Normal directories usually have an interface, and the corresponding software can be seen on the phone)

  • BIND AIDL SERVICE is similar to BIND SERVICE, both call bindService(Intent, ServiceConnection, flag), the difference lies in Intent and ServiceConnection. For Intent, since the service bound by BIND SERVICE belongs to the same APK as itself, it is easy to find the corresponding service through the class name. The service bound by BIND AIDL SERVICE belongs to a different APK from itself. During the binding process, it is necessary to find the bound service through the package name and the corresponding ACTION.
Intent intent = new Intent();
intent.setAction("com.zhouxi.service.AidlService");
intent.setPackage("com.zhouxi.service");
bindService(intent, aidlServiceConnection, Context.BIND_AUTO_CREATE);
  • For ServiceConnection, the two use the same class, but the returned IBinder objects are different (note: different types of variables are needed to receive) ,
public ServiceConnection aidlServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.e(TAG, "onServiceConnected: bind AidlService success.");
        IAidlService aidlService = IAidlService.Stub.asInterface(service);
        try {
            Log.e(TAG, "onServiceConnected: the info of AidlService: " + aidlService.getServiceInfo());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.e(TAG, "onServiceConnected: bind AidlService fail.");
    }
};
  • GeneralService internally defines an internal class inherited from IBinder, and returns this type of object to onServiceConnected through onBinder. AidlService also provides the caller service function by customizing the inner class, but the inner class inherits from IAIdlService.Stub, nothing more, they essentially define the inner class and pass the object of the inner class to the client , So as to achieve the purpose of the client to call the service.
//两个内部类对比
class GeneralBinder extends Binder {
    public void readWriteInfo() {
        String info = readServiceInfo();
        Log.e(TAG, "getInfo: readServiceInfo success, the information: " + info);
        writeServiceInfo("This is writeServiceInfo in GeneralBinder.");
        Log.e(TAG, "getInfo: writeServiceInfo success.");
    }
}
================================================================================
class AidlBinder extends IAidlService.Stub {
    @Override
    public String getServiceInfo() {
        Log.e(TAG, "getServiceInfo: This is getServiceInfo in AidlBinder.");
        return info;
    }
}
  • Looking at the input parameters of onServiceConnected, you can find that regardless of whether the AIDL method is used, the second parameter is of the IBinder type. Although we do not know the relationship between the parent class Binder and IAIdlService.Stub inherited by the two inner classes, one thing is certain is that both are IBinder types . Through this comparison, the difference between the two is very clear. So what is IAdlService? What is IAidlService.Stub and what is the difference between the two? For specific analysis, please refer to this article (placeholder: expected to be completed on 2020.7.21). Back to the comparison of the two internal classes, the internal class of GeneralService directly defines one Method, through this method to obtain the function provided by GeneralService, the internal class of AidlService obtains the function provided by the service by implementing the method of the IAIdlService interface.
  • UNBIND AIDL SERVICE unbundling is the same as that of GeneralService, so I won’t introduce it again.
unbindService(aidlServiceConnection);

4. Code Analysis

This is the MainActivity of the client module, which is the interface of the six buttons in the figure above. This class defines six buttons to enable opening and closing GeneralService, binding and unbinding GeneralService, and binding and unbinding AidlService in another apk.

Two ServiceConnected are defined: serviceConnected and aidlServiceConnected are used to detect whether the binding is successful, and if the binding is successful, they will receive the IBinder object returned by the service respectively.

package com.zhouxi.client;

import aidl.IAidlService;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    public static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.startGeneralService).setOnClickListener(this);
        findViewById(R.id.stopGeneralService).setOnClickListener(this);
        findViewById(R.id.bindGeneralService).setOnClickListener(this);
        findViewById(R.id.unbindGeneralService).setOnClickListener(this);
        findViewById(R.id.bindAidlService).setOnClickListener(this);
        findViewById(R.id.unbindAidlService).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.startGeneralService) {
            Intent intent = new Intent(this, GeneralService.class);
            startService(intent);
        } else if (v.getId() == R.id.stopGeneralService) {
            Intent intent = new Intent(this, GeneralService.class);
            stopService(intent);
        } else if (v.getId() == R.id.bindGeneralService) {
            Intent intent = new Intent(this, GeneralService.class);
            bindService(intent, serviceConnection, BIND_AUTO_CREATE);
        } else if (v.getId() == R.id.unbindGeneralService) {
            unbindService(serviceConnection);
        } else if (v.getId() == R.id.bindAidlService) {
            Intent intent = new Intent();
            intent.setAction("com.zhouxi.service.AidlService");
            intent.setPackage("com.zhouxi.service");
            bindService(intent, aidlServiceConnection, Context.BIND_AUTO_CREATE);
        } else if (v.getId() == R.id.unbindAidlService) {
            Log.e(TAG, "onClick: unbindAidlService");
            unbindService(aidlServiceConnection);
        }
    }

    public ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, "onServiceConnected: bind GeneralService success.");
            GeneralService.GeneralBinder generalBind = (GeneralService.GeneralBinder) service;
            generalBind.readWriteInfo();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "onServiceDisconnected: bind GeneralService fail.");
        }
    };

    public ServiceConnection aidlServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, "onServiceConnected: bind AidlService success.");
            IAidlService aidlService = IAidlService.Stub.asInterface(service);
            try {
                Log.e(TAG, "onServiceConnected: the info of AidlService: " + aidlService.getServiceInfo());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "onServiceConnected: bind AidlService fail.");
        }
    };
}

 GeneralService inherits from Service and implements the onBind and onUnbind methods of Service. When MainActivity calls to start the service, it executes the onBind method and returns an instance of the internal class. This internal class defines some methods to call the internal methods of GeneralService, which indirectly lets MainActivity calls the method of GeneralService. When MainActivity is unbound, execute the onUnbind method.

package com.zhouxi.client;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;

public class GeneralService extends Service {
    private static final String TAG = GeneralService.class.getSimpleName();

    private String info = "This is GeneralService info.";

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate: GeneralService is onCreate.");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand: GeneralService is onStartCommand.");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy: GeneralService is onDestroy.");
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: GeneralService is onBind.");
        return new GeneralBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind: GeneralService is onUnbind.");
        return super.onUnbind(intent);
    }

    class GeneralBinder extends Binder {
        public void readWriteInfo() {
            String info = readServiceInfo();
            Log.e(TAG, "getInfo: readServiceInfo success, the information: " + info);
            writeServiceInfo("This is writeServiceInfo in GeneralBinder.");
            Log.e(TAG, "getInfo: writeServiceInfo success.");
        }
    }

    public String readServiceInfo() {
        Log.e(TAG, "readServiceInfo: this is readServiceInfo in GeneralService.");
        return info;
    }

    public void writeServiceInfo(String info) {
        Log.e(TAG, "writeServiceInfo: this is writeServiceInfo in GeneralService.");
        this.info = info;
    }
}

This is the AndroidManifest file of the client module. It mainly focuses on the package name package="com.zhouxi.client" and the registration information of the two components (you can review the four components in Android that you don’t know). What is the use of this registration information: Generally speaking, if the four major components need to be used, they must be registered (declared) in the AndroidManifest, otherwise when the component needs to be called during the execution of the apk, the system will go to the xml file to find the apk which is If there is no such component name, it will crash directly if it is not. This is also a common crash cause in Android apk debugging.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.zhouxi.client">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        //MainActivity注册信息
        <activity android:name="com.zhouxi.client.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        //GeneralService注册信息
        <service android:name="com.zhouxi.client.GeneralService"/>
    </application>

</manifest>

The IAidlService interface is the communication bridge between MainActivity and AidlService. The interface defines the getServiceInfo method. AidlService defines an internal class AidlBinder inherited from IAIdlService.Stub, which has been analyzed above. By looking at the input parameters of onServiceConnected of aidlServiceConnected, IaidlService can be judged. Stub is an object of IBinder type. Please continue to study the next section (placeholder: expected to be completed on July 20, 2020) . Here we can imagine this AidlBinder internal class as the GeneralBinder in another service, and their overall steps In fact, it is almost the same, except that the internal class of AidlBinder inherits the IAIdlService interface, so it needs to implement the method defined by the interface internally. Then MainActivity indirectly accesses the functions of AidlService through the methods defined by this internal class.

// IAidlService.aidl
package aidl;

interface IAidlService {
    String getServiceInfo();
}
package com.zhouxi.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import aidl.IAidlService;
import androidx.annotation.Nullable;

public class AidlService extends Service {
    private static final String TAG = AidlService.class.getSimpleName();

    private String info = "This is AidlService info.";

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate: AidlService is onCreate.");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand: AidlService is onStartCommand.");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy: AidlService is onDestroy.");
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: AidlService is onBind.");
        return new AidlBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind: AidlService is onUnbind.");
        return super.onUnbind(intent);
    }

    class AidlBinder extends IAidlService.Stub {
        @Override
        public String getServiceInfo() {
            Log.e(TAG, "getServiceInfo: This is getServiceInfo in AidlBinder.");
            return info;
        }
    }
}

This is the AndroidManifest file of the aidlservice module. It has been introduced above. Here we will only introduce the feature of intent-filter. Check the process of MainActivity starting AidlService: Action and Package are passed in the Intent. The function of the Intent is mainly to transmit information. Here is to tell the system when I bindService what the package name of the service I am going to bind now is, why can’t I write the class name directly like the previous one, because these are two apks, which must be operated by an intermediary The function of the action defined at the same time can be understood as the "secret sign" called between two apks. You define this feature in AndroidManifest. I also inject this "secret sign" when I look for the service. Then I will Can I find you?

Intent intent = new Intent();
intent.setAction("com.zhouxi.service.AidlService");
intent.setPackage("com.zhouxi.service");
bindService(intent, aidlServiceConnection, Context.BIND_AUTO_CREATE);
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.zhouxi.service">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".AidlService">
            <intent-filter>
                <action android:name="com.zhouxi.service.AidlService"/>
            </intent-filter>
        </service>
    </application>

</manifest>

 Not to mention the main_activity file, it defines six buttons to display on the home page and provide a click response function.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.zhouxi.client.MainActivity">

    <Button
        android:id="@+id/startGeneralService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start service"/>

    <Button
        android:id="@+id/stopGeneralService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Stop service"/>

    <Button
        android:id="@+id/bindGeneralService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Bind service"/>

    <Button
        android:id="@+id/unbindGeneralService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="unbind service"/>

    <Button
        android:id="@+id/bindAidlService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Bind aidl service"/>

    <Button
        android:id="@+id/unbindAidlService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Unbind aidl service"/>

</LinearLayout>

5. Stepping on pits and solutions

Before testing, let's sort out some of the easy pits in the Demo of this article. This is also the most important place in this article. It may solve many pits you encounter.

1. Why does my apk crash during operation?

Solution 1: Pay attention to the AndroidManifest file to see if the corresponding component has been registered in the file. If the corresponding component is not registered and the component happens to be called, then there will be a crash.

Solution 2: If there is an Exception in the code, there will be a crash, so in ordinary coding, you must develop a good log printing habit, try to use the log to locate the problem, how to use the log to locate the problem efficiently, please refer to this article Article (placeholder: expected to be completed by 2020.08) ?

2. Why does the internal class in the service show that the interface cannot be found when it implements the interface?

In order for the AIDL interface on both sides of the client and the server to provide its own class calls, and to achieve communication between the two apks, the following conditions need to be met:

  1. Refer to (3) of the top AidlDemo directory structure, the aidl package must exist, and the aidl package must be at the same level as java. The IAIdlService.aidl file must be saved under aidl, it can be directly saved under aidl, or a new package can be created under aidl save.
  2. The package name must correspond to the top package name in the IAIdlService.aidl class.
  3. It needs to be compiled in advance, and the compiled result will be saved in (1). Without this file, the IAIdlService cannot be imported, and a compilation error will be reported.
  4. The package name of the IAIdlService on the client and server must be the same. It should be noted that if the first three conditions are not met, the compilation will fail. If the first three items are all satisfied and the fourth item is not satisfied, the program can run normally, but it will crash when called across apk.

If you want to know more about the storage location of the AIDL interface, please see this article (occupied, expected to be completed on 2020.07.20) .

6. Project Demonstration

Next, let’s verify the following effects. Click the six buttons in turn, and the printed log is as follows. Through the log, we can find the calling relationship of each function:

START SERVICE: After starting the service, directly call the onCreate->onStartCommand of the GeneralService service

STOP SERVICE: Close the service and directly call onDestroy of the GeneralService service

BIND SERVICE: After binding the service, the service first opens the onCreate of the AidlService service->calls the onBind method of the service and returns the IBinder object->onServiceConnected method receives the object returned by the service->the main function calls the method of the object to access the internal method of the GeneralService .

UNBIND SERVICE: After unbinding the service, GeneralService calls onBind->onDestroy.

BIND AIDL SERVICE and UNBIND AIDL SERVICE are similar to the above-mentioned binding process and will not be introduced in detail.

The following is the log of the six buttons clicked in turn. It is easier to understand the calling process of the function through the log and the above code.

//START SERVICE
2020-07-15 00:34:47.208 13981-13981/com.zhouxi.client E/GeneralService: onCreate: GeneralService is onCreate.
2020-07-15 00:34:47.209 13981-13981/com.zhouxi.client E/GeneralService: onStartCommand: GeneralService is onStartCommand.

//STOP SERVICE
2020-07-15 00:34:50.445 13981-13981/com.zhouxi.client E/GeneralService: onDestroy: GeneralService is onDestroy.

//BIND SERVICE
2020-07-15 00:34:51.578 13981-13981/com.zhouxi.client E/GeneralService: onCreate: GeneralService is onCreate.
2020-07-15 00:34:51.578 13981-13981/com.zhouxi.client E/GeneralService: onBind: GeneralService is onBind.
2020-07-15 00:34:51.580 13981-13981/com.zhouxi.client E/MainActivity: onServiceConnected: bind GeneralService success.
2020-07-15 00:34:51.580 13981-13981/com.zhouxi.client E/GeneralService: readServiceInfo: this is readServiceInfo in GeneralService.
2020-07-15 00:34:51.580 13981-13981/com.zhouxi.client E/GeneralService: getInfo: readServiceInfo success, the information: This is GeneralService info.
2020-07-15 00:34:51.580 13981-13981/com.zhouxi.client E/GeneralService: writeServiceInfo: this is writeServiceInfo in GeneralService.
2020-07-15 00:34:51.580 13981-13981/com.zhouxi.client E/GeneralService: getInfo: writeServiceInfo success.

//UNBIND SERVICE
2020-07-15 00:34:52.321 13981-13981/com.zhouxi.client E/GeneralService: onUnbind: GeneralService is onUnbind.
2020-07-15 00:34:52.321 13981-13981/com.zhouxi.client E/GeneralService: onDestroy: 
GeneralService is onDestroy.

//BIIND AIDL SERVICE
2020-07-15 00:34:53.044 13981-13981/com.zhouxi.client E/MainActivity: onServiceConnected: bind AidlService success.
2020-07-15 00:34:53.046 13981-13981/com.zhouxi.client E/MainActivity: onServiceConnected: the info of AidlService: This is AidlService info.

//UNBIND AIDL SERVICE
2020-07-15 00:34:53.683 13981-13981/com.zhouxi.client E/MainActivity: onClick: unbindAidlService

 

 

 

Guess you like

Origin blog.csdn.net/weixin_48968045/article/details/107216295