AIDL 使用详情及原理 - tenji/ks GitHub Wiki

AIDL 使用详情及原理

AIDL(Android Interface Define Language)是一种 IPC 通信方式,我们可以利用它来定义两个进程相互通信的接口。他是基于 Service 实现的一种线程间通信机制。它的本质是 C/S 架构的,需要一个服务器端,一个客户端。

一、Android 中的 IPC(Inter-Process Communication) 方式

  • 使用 Bundle,四大组件都是支持 Bundle 的,由于 Bundle 实现了 Parcelable 接口,可以在进程中传递数据,我们在一个进程中启动另一个进程的 Bundle,可以进程间通信
  • 使用文件共享
  • 使用 Messager
  • 使用 Aidl
  • 使用 ContentProvider
  • 使用 socket

二、AIDL 的使用

2.1 创建 AIDL

首先我们在 AndroidStudio 中创建一个 Andorid 工程,随后添加一个 module,作为 aidl 的服务端,在 aidlserver 中创建 aild 目录, 同时创建一个 aidl 文件

// IMyAidlInterface.aidl
package com.yunzhou.aidlserver;

// Declare any non-default types here with import statements

interface IMyAidlInterface {

    /**
    * 自己添加的方法
    */
    int add(int value1, int value2);
}

​这边可以看到 aidl 的语法跟 JAVA 是一样的,声明了一个接口,里面定义了 aidl 服务器端暴露给客户端调用的方法。完成这部分操作之后还没有结束,我们需要手动编译程序,生成 aidl 对应的 Java 代码。

2.2 实现接口,并向客户端放开接口

public class MyAidlService extends Service {
    public MyAidlService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

    private IBinder iBinder = new IMyAidlInterface.Stub(){
        @Override
        public int add(int value1, int value2) throws RemoteException {
            return value1 + value2;
        }
    };
}

我们创建了一个 Service,并在 Service 内部声明了一个 IBinder 对象,它是一个匿名实现的 IMyAidlInterface.Stub 的实例,同时我们在发现 IMyAidlInterface.Stub 实例实现了 add 方法,这个方法正是我们在 aidl 中声明的供客户端调用的方法。

2.3 客户端调用 aidl

首先在客户端跟服务器一样,新建 aidl 目录,将服务器端的 aidl 拷贝到客户端,这边特别要注意,拷贝后的客户端的 aidl 文件包目录必须与服务器端保持一致,拷贝完后同样时编译工程,让客户端也生成对应的 java 文件。

其次就是在 Activity 的 onCreate 中绑定服务:

private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // 绑定服务成功回调
        aidl = IMyAidlInterface.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        // 服务断开时回调
        aidl = null;
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // do something
    bindService();
}

private void bindService() {
    Intent intent = new Intent();
    // Android 5.0 开始,启动服务必须使用显示的,不能用隐式的
    intent.setComponent(new ComponentName("com.yunzhou.aidlserver", "com.yunzhou.aidlserver.MyAidlService"));
    bindService(intent, connection, Context.BIND_AUTO_CREATE);
}

绑定完服务,就是进行调用了。

三、AIDL 可使用的参数类型

3.1 基本数据类型

基本数据类型支持:byte, char, int, long, float, double, boolean,不支持:short

3.2 引用数据类型

引用数据类型根据官方介绍,可以使用 String, CharSequence, List, Map,当然,我们也可以使用自定义数据类型。

3.3 自定义数据类型

自定义数据类型,用于进程间通信的话,必须实现 Parcelable 接口,Parcelable 是类似于 Java 中的 Serializable,Android 中定义了 Parcelable,用于进程间数据传递,对传输数据进行分解,编组的工作,相对于 Serializable,他对于进程间通信更加高效。

...

四、AIDL 原理

...

参考链接