AIDL是Android Interface Definition Language 的缩写,即Android 接口定义语言。那么AIDL到底是干什么用的呢?简单的说AIDL就是用来进行进程间通信的 ,可是Android已经有了Messenger、ContentProvider、Socket等进程间通信方式,那么我们为什么还需要AIDL呢?以及我们什么时候应该使用AIDL呢? 其实这 两个问题的答案可以在Android官方文档中找到,在Android的官方文档中有下面的描述:
Note: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.
只有需要多个不同App通过IPC访问服务而且还需要在服务中处理多线程时才应该使用AIDL。从这里我们应该明白了为什么要使用AIDL,以及什么时候使用AIDL。
AIDL实战
简单的了解了AIDL之后,接下来我们将通过一个简单的示例演示一下AIDL的使用。
新建AIDL接口
1 | //Book.java |
什么三个文件中,Book.java 是一个Java类,它实现了Parcelable接口,Book.aidl是Book类在AIDL中的声明,IBookManager 是我们定义的一个接口,里面有两个方法:getBookList和addBook。
注意:
* 无论自定义的Parcelable对象和AIDL对象和当前的AIDL文件是否在同一个包中,都要显式import进来
* 如果AIDL使用到了自定义的Parcelable对象,那么必须新建一个和它同名的AIDL文件
* AIDL中除了基本数据类型,其他类型的参数都必须标上方向:in、out、inout。
远程服务端Service的实现
首先新建如下Service1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41package com.weiqianghu.aidl;
public class BookManagerService extends Service {
private static final String TAG = "BookManagerService";
private CopyOnWriteArrayList<Book> mBooks = new CopyOnWriteArrayList<>();
@Override
public void onCreate() {
super.onCreate();
mBooks.add(new Book(1, "Android 群英传"));
mBooks.add(new Book(2, "Android 开发艺术探索"));
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private Binder mBinder = new IBookManager.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
return mBooks;
}
@Override
public void addBook(Book book) throws RemoteException {
mBooks.add(book);
}
};
}
<service
android:name=".BookManagerService"
android:enabled="true"
android:exported="true"
android:process=".aidl.BookManagerService">
</service>
上面新建了一个服务端Service,在onBind中返回了Binder对象,使用 CopyOnWriteArrayList 进行线程同步。在Manifest文件中将Service置于单独进程中。
客户端实现
1 | package com.weiqianghu.aidl; |
以上就是客户端代码,运行程序Log如下:
08-01 15:52:38.166 21955-21955/com.weiqianghu.aidl I/MainActivity: onServiceConnected: [1,Android 群英传, 2,Android 开发艺术探索]
08-01 15:52:38.170 21955-21955/com.weiqianghu.aidl I/MainActivity: onServiceConnected: [1,Android 群英传, 2,Android 开发艺术探索,3,Android 源码设计模式分析与实战]
可以看到客户端成功调用了服务端的方法。
AIDL的工作原理
1 | /* |
在gen目录下可以看到系统根据IBookManager.aidl生成了IBookManager.java这个类。IBookManager 继承了 IInterface 这个接口,所有需要在Binder 中传输的接口都需要继承IInterface接口。通过查看 IBookManager.java 源码我们可以看到,首先它声明了两个方法getBookList和addBook ,这两个方法就是我们在IBookManager.aidl 定义的方法。接着它声明了内部类Stub,Stub 继承了Binder,并且实现了 IBookManager 接口。可以看到首先Stub中声明了两个int型id分别用来表示getBookList方法和addBook方法。其次Stub中还有两个方法分别是: asBinder 和 asInterface 方法,asInterface 用于将服务端的Binder对象转换为客户端所需的AIDL接口类型的对象,asBinder 方法用于返回当前的Binder对象。最重要的是 Stub 中又定义了内部代理类 Proxy ,Proxy也实现了 IBookManager 接口,这也就是设计模式中的代理模式的应用。 Proxy 类中主要实现了getBookList和 addBook 方法。这就是AIDL的实现原理。
总结
Binder是Android系统中一个非常重要的跨进程通信机制,Binder 也是非常不容易理解的一个话题,因此本文并没有深入 Binder 细节,而是从AIDL入手介绍了 Binder 机制,简答来说 Binder 是 Android 的一个类,它实现了 IBinder接口, Binder 是 ServiceManager 连接各种 Manager 和相应 ManagerService 的桥梁, Binder也主要用在 Service 中。
参考资料:
Android 开发艺术探索 第二章 IPC 机制相关章节