AIDL 是什么:
首先简单介绍一下AIDL,AIDL:(Androidinterfacedefinition language的缩写)它是一种Android内部进程通信接口的描述语言,我们可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。
在Android 上,一个进程通常无法访问另一个进程的内存。 尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。
编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理。通过这种机制,我们只需要写好 aidl 接口文件,编译时系统会帮我们生成 Binder 接口。
AIDL 支持的数据类型:
共4 种:
- Java 的基本数据类型
- List 和 Map
- 元素必须是 AIDL 支持的数据类型
- Server 端具体的类里则必须是 ArrayList 或者 HashMap
AIDL 如何编写:
AIDL 的编写主要为以下三部分:
- 创建 AIDL
- 新建 aidl 文件夹,在其中创建接口 aidl 文件以及实体类的映射 aidl 文件
- Make project ,生成 Binder 的 Java 文件
- 创建 Service,在其中创建上面生成的 Binder 对象实例,实现接口定义的方法
- 在 onBind() 中返回
- 实现 ServiceConnection 接口,用asInterface的形式将IBinder还原成接口,从而拿到 AIDL 类
- bindService()
- 调用 AIDL 类中定义好的操作请求
AIDL 实例:
1. 创建AIDL
新建工程,无需多讲,新建成工程如下图:
在其中可以看到工程中已经存在aidl文件夹,这是我已经建好的,不必在意。
然后我们右键new-AIDL-AIDL File,就可以新建一个如上图可见的aidl文件,定义好我们自己需要的文件名,OK,以aidl结尾的文件出现在我们的工程列表中。打开,我们定义的aidl文件,可以看到如下图:
其中basicTypes方法本身没有多少用处,就是可以告诉我们aidl文件支持的数据类型有哪几种。
在这个文件中我们可以定义我们自己需要的接口,例如:我自己定义了int getRootValue();
点击 Build -> Make Project,然后等待构建完成。
然后就会在 build/generated/source/aidl/你的 flavor/ 下生成一个 Java 文件:
现在我们有了跨进程的通信媒介,接下来就可以编写我们的client和service代码了。
2. 编写服务器端服务
创建 Service,在其中创建上面生成的 Binder 对象实例,实现接口定义的方法;然后在 onBind() 中返回
创建将来要运行在另一个进程的Service,在其中实现了 AIDL 接口中定义的方法:
上述的代码中通过IDataAidlInterface.Stub创建了一个mBinder的对象,这个对象就是将来我们通过serviceConnection传递到client端的service。
不要忘记在Manifest.xml中声明我们的service,
至此,服务器端的代码就算是基本完成。
3. 客户端实现绑定和通信
1.首先在客户端我们先在main目录下边建立一个aidl目录,然后把我们在service端创建的aidl目录内容整体拷贝到client端中,AS中sync整体工程,可以看到在client中出现了和service端同样的aidl,在这里必须强调一点,aidl目录结构必须保持一致,否则无法使用。后续会说到。Sync完整体目录之后我们对client端 code进行一次编译
2.开始实现serviceConnection接口,在其中拿到aidl类。
3.绑定服务,我在主页面中设置了两个button,如下图:
一个用来bindservice,一个用来做IPC通信,看下bindservice的code:
看到我们通过隐式intent的方法设置了我们需要的service的action,这个action就是我们在service端声明的service的name,同时也设置了intent的package,这就是为什么需要service端和client端aidl需要设置相同包名的原因。Client端会根据包名和service name找到具体的service进行bind。注意:要执行 IPC,必须使用bindService()
将应用绑定到服务上。
5.0 以后要求显式调用 Service,所以我们无法通过 action 或者 filter 的形式调用 Service,具体内容另外讨论
4.拿到 AIDL 类后,就可以调用 AIDL 类中定义好的操作,进行跨进程请求
至此,Activity 与 另外一个进程的 Service 通信成功了。