Simple use of AIDL in Android (Hello world)

AIDL: Android Interface Definition Language (Android interface definition language)

Function: Cross-process communication. For example, application A calls the interface provided by application B.

A brief description of the code implementation process:

Application A creates the aidl interface and creates a Service to implement this interface (return an instance of our interface in the onBind method).

Move the aidl file created by application A to application B intact (note that the package and class names must be the same). B uses bindService to bind the service created by application A, thereby calling the interface provided by application A.

accomplish:

1. Application A (server) (providing interface callee):

1. Create AIDL file:

Android Studio right-clicks on the main directory of the project to create a new one and finds AIDL. It will help us create folders and files. The default name is IMyAidlInterface. Developers can modify the name according to their needs.

have inside:

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    //上面这个是新建的时候自己生成的,可以去掉,我们自己新建以下方法,一个get(从服务端取值),一个set(传值给服务端)
    String getHelloString();
    void setHelloString(String string);
}

After writing it, make project and the IMyAidlInterface class will be automatically generated.

2. Create service: (A application does not need to start Service manually, this service will start automatically when B application bindService)

public class AidlTestService extends Service {

    private String hello;

    @Override
    public void onCreate() {
        super.onCreate();
        hello = "hello";
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    public class MyBinder extends IMyAidlInterface.Stub{

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
            Log.i("xaeHu", "basicTypes: \nanInt = "+anInt
                    +"\naLong = "+aLong
                    +"\naBoolean = "+aBoolean
                    +"\naFloat = "+aFloat
                    +"\naDouble = "+aDouble
                    +"\naString = "+aString
            );
        }

        @Override
        public String getHelloString() throws RemoteException {
            return hello;
        }

        @Override
        public void setHelloString(String string) throws RemoteException {
            hello = string;
        }
    }
}

3. The manifest file declares this service: (It is said on the Internet that this name requires the full name, but I can actually bind it successfully without using the full name here)

<service android:name=".AidlTestService"
            android:enabled="true"
            android:exported="true" />

The work of application A is completed. Next is how application B uses this interface:

2. B application (client) (interface caller):

1. The manifest file declares the package name of application A: (New in Android 11, this step is required if the project targetSdk>=30, otherwise bindService cannot adjust the service of application A) (Many AIDL tutorial blogs on the Internet do not have this pitfall. explain)

   <!--  配置服务端的包名-->
    <queries>
        <package android:name="com.example.myapplication" />
    </queries>

2. Copy the AIDL file created by application A, including the package name of application A, to the main directory of application B:

The package name of my A application is "com.example.myapplication", and the package name of B application is "com.example.myapplication2"

 Note that the package name of aidl must be consistent with application A, otherwise an exception will be reported when calling the method: java.lang.SecurityException: Binder invocation to an incorrect interface

After putting it in, make project and the IMyAidlInterface class will be automatically generated.

3. Bind the service and call the method provided by the aidl interface:

For example, bind the service directly in onCreate of MainActivity:

public class MainActivity extends AppCompatActivity{
    private IMyAidlInterface myAidlInterface;
    private final ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            myAidlInterface = null;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //点击按钮一去绑定服务
        findViewById(R.id.btn1).setOnClickListener(v -> {
           Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.example.myapplication","com.example.myapplication.AidlTestService"));
            boolean re = bindService(intent, connection, Context.BIND_AUTO_CREATE);
            Log.i("xaeHu", "bindService: "+re);
        });

        //点击按钮2调用set方法
        findViewById(R.id.btn2).setOnClickListener(v -> {
            if(myAidlInterface != null){
                try {
                    myAidlInterface.setHelloString("hello world");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }else {
                Log.e("xaeHu", "btn2 onclick: myAidlInterface == null");
            }
        });

        //点击按钮3调用get方法
        findViewById(R.id.btn3).setOnClickListener(v -> {
            if(myAidlInterface != null){
                try {
                    Toast.makeText(this, myAidlInterface.getHelloString(), Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }else {
                Log.e("xaeHu", "btn3 onclick: myAidlInterface == null");
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(connection);
    }
}

A simple AIDL call is all it takes.

Advanced:

The above demonstration is to pass basic data types as parameters, and then pass the object through AIDL

First create the entity object file in the aidl folder, and then create the entity class in the java folder. Otherwise, if you create the entity class in java and then create the same name in aidl, an error will be prompted.

A in application:

For example, when we create a Student object, it is Student.aidl in the aidl folder. The code inside is very simple:

package com.example.myapplication;

parcelable Student;

Then create Student.java in java. Note that Parcelable needs to be implemented:

public class Student implements Parcelable {
    private int id;
    private String name;
    private int age;
    private int sex;

    public Student() {
    }

    public Student(int id, String name, int age, int sex) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    protected Student(Parcel in) {
        id = in.readInt();
        name = in.readString();
        age = in.readInt();
        sex = in.readInt();
    }

    public static final Creator<Student> CREATOR = new Creator<Student>() {
        @Override
        public Student createFromParcel(Parcel in) {
            return new Student(in);
        }

        @Override
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getSex() {
        return sex;
    }

    public int getId() {
        return id;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
        dest.writeInt(age);
        dest.writeInt(sex);
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

Add a method to the aidl interface: (note addStudent(in Student student); parameters need to be added in to indicate receiving parameters, and there are also out and inout)

// IMyAidlInterface.aidl
package com.example.myapplication;

import com.example.myapplication.Student;
// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    String getHelloString();
    void setHelloString(String string);

    void addStudent(in Student student);
    Student getStudent(int id);
}

Implement these two methods in the service:

private Map<Integer,Student> studentMap;

@Override
public void addStudent(Student student) throws RemoteException {
    Log.i("xaeHu", "addStudent: "+student);
    if(studentMap == null){
        studentMap = new HashMap<>();
    }
    studentMap.put(student.getId(), student);
}

@Override
public Student getStudent(int id) throws RemoteException {
    if(studentMap != null){
        Student student = studentMap.get(id);
        Log.i("xaeHu", id + " -> getStudent: "+student);
        return student;
    }
    Log.i("xaeHu", id + " -> getStudent: null");
    return null;
}

B application:

Similarly, move the aidl files and classes over. Note that the package name of the entity object needs to be consistent with the package name of the A application:

Then similarly, after binding the service, you can call:

myAidlInterface.addStudent(new Student(1,"student1",26,0));
myAidlInterface.addStudent(new Student(2,"student2",27,1));

Log.i("xaeHu", "getStudent1: "+myAidlInterface.getStudent(1));
Log.i("xaeHu", "getStudent2: "+myAidlInterface.getStudent(2));

 

over.

Guess you like

Origin blog.csdn.net/qq_35584878/article/details/130702204