Because memory is shared between threads, they can communicate easily, for example by sharing variables. Communicating between processes is much more difficult. To achieve interprocess communication, we need to define a common interface description language (IDL) between different processes. The commonly used IDLS include JSON and Protocol Buffers. Android also has a special Language for communication between different processes, called AIDL (Android Interface Definition Language). Here’s a scenario to illustrate how we can use the AIDL.

Scenario: There is now a Teacher app and multiple Student apps. The Teacher app is installed on the phone first. When a Student app is installed, it will tell the Teacher app its package name and process number. The Teacher app will print out this information and calculate an alias based on this information to the Student. Student gets the alias and shows it.

Define the agreement

First, we created a module named rule in Teacher’s project to define communication rules. We create a iteacher. aidl file in the Rule Module (it is recommended to create aiDL directly using the New method in Android Studio). As follows:

// ITeacher.aidl package me.pengtao.rule; import me.pengtao.rule.StudentInfo; Interface ITeacher {// Register your Id with the teacher void registerId(in String Id); // Students get their own nickname String getAlias(); }Copy the code

This file needs to be in the same aiDL directory as Java, where the arguments to a method can be basic types (int, float, Boolean, double, String) or POJO classes, but not wrapper classes. The POJO classes are explained in detail later in the section.

Note: A new module is created here to define the AIDL because different processes can only communicate with the AIDL with the same name and package name. Once a Module is created here, it can be used as a dependency to be distributed to apps that need to communicate with the process.

In addition, careful readers may have noticed that AIDL method parameters are preceded by the in keyword. In AIDL syntax, there are three key definitions for the flow direction of the parameter. In: Indicates that the Client inputs information to the Server. Out: Indicates that the Client obtains data from the Server. Inout: can be obtained or entered. Client and Server are explained in detail below.

Note the following when using these keywords:

  • If the argument is a primitive type, only in can be used, and the in can be omitted.
  • If it is an array type or a POJO class, one of these three keywords must be added;

Registration Service

AIDL process communication is similar to a Server/Client model, with one side serving as the Server for receiving and distributing data, and the other side serving as the Client for connecting to and interacting with the Server. The Teacher here acts as the Server. Therefore, we need to provide a Service for Teacher to provide services to other clients. The implementation of this Service is as follows:

public class TeacherService extends Service {
    private String mId;
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    IBinder mBinder = new ITeacher.Stub() {

        @Override
        public void registerId(final String id) throws RemoteException {
            mId = id;
        }

        @Override
        public String getAlias() throws RemoteException {
            return mId + "Alias";
        }
    };
}
Copy the code
<permission android:name="me.pengtao.teacher.RULE"/>
<service
  android:name=".TeacherService"
  android:exported="true"
  android:permission="me.pengtao.teacher.RULE" />
Copy the code

After completing the above steps, we run Teacher. Then we will create a StudentA project that relies on rule. The key code is implemented as follows:

private ITeacher mTeacher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent serviceIntent = new Intent().setComponent(new ComponentName("me.pengtao.teacher",
                "me.pengtao.teacher.TeacherService"));
        bindService(serviceIntent, mConnection, BIND_AUTO_CREATE);
    }

    ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(final ComponentName name, final IBinder service) {
            mTeacher = ITeacher.Stub.asInterface(service);
            try {
                mTeacher.registerId(BuildConfig.APPLICATION_ID);
                ((TextView) findViewById(R.id.alias)).setText(getString(R.string.alias, mTeacher
                        .getAlias()));
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(final ComponentName name) {
            mTeacher = null;
        }
    };
Copy the code

After running StudentA, it first binds TeacherService, then sends its package name to Teacher, who returns an alias and displays it.

POJO class

Now that we’ve shown the basic types of communication, let’s look at how to transfer a POJO class between different processes. For example, instead of requiring students to provide an ID, teachers now require them to provide a set of information, such as their name, gender and so on. So how do you do that?

First we need to define such a POJO class in the Java directory of Rule’s Module and implements Parcelable. Then we create an AIDL file with the corresponding name and package name in the aiDL directory. As follows:

// IStudentInfo.aidl
package me.pengtao.rule;

parcelable StudentInfo;
Copy the code

And you’re done. When using the POJO class, note the following: 1. Aidl must be named the same as the POJO class.

Error:Execution failed for task ':rule:compileDebugAidl'. > java.io.IOException: com.android.ide.common.process.ProcessException: Error while executing the process/Users/Chris/Library/Android/SDK/build - the tools / 26.0.2 aidl with the arguments {-p/Users/chris/Library/Android/sdk/platforms/android-26/framework.aidl -o/Users/chris/kujiale/Teacher/rule/build/generated/source/aidl/debug -I/Users/chris/kujiale/Teacher/rule/src/debug/aidl  -I/Users/chris/kujiale/Teacher/rule/src/main/aidl -i/Users/Chris /. Gradle/files/caches/transforms - 1-1.1 / support - media - compat - 26.1.0. Aar/a2b4d6b89d0b463dae37ed4ed6eac440 / ai Dl - I/Users/Chris /. Gradle/files/caches/transforms - 1-1.1 / support - compat - 26.1.0. Aar / 80390967 c8d1c220862dcd091cfa81ca/aidl -d/var/folders/t9/x4yt536976l_sd9xcn2d6xwm0000gn/T/aidl5092216096502271751.d /Users/chris/kujiale/Teacher/rule/src/main/aidl/me/pengtao/rule/ITeacherWant.aidl}Copy the code

The POJO class must implement a default constructor, otherwise the following error will be reported:

Error:(49, 9) error: constructor StudentInfo in class StudentInfo cannot be applied to given types;
required: Parcel
found: no arguments
reason: actual and formal argument lists differ in length
Copy the code

POJO classes must use Parcelable and must implement a readFromParcel(Parcel) method, otherwise the following error will be reported;

Error:(88, 5) error: cannot find symbol method readFromParcel(Parcel)
Copy the code

4. When a POJO class is a parameter, it must be preceded by in, out, or inout. See above for the usage of these three keywords.

Demo code: github.com/CPPAlien/AI… Github.com/CPPAlien/AI…