AIDL 进程间通信
AIDL 是英文 Android Interface Definition Language 的缩写。用于定义服务端和客户端通信接口的一种语言,可以用来生成IPC的代码。
Android 实现进程间通信(IPC)有很多种方式
- 广播:占用的系统资源比较多,如果是频繁的跨进程通信的话显然是不可取的
- Messenger: 进行跨进程通信时请求队列是同步进行的,无法并发执行,在有些要求多进程的情况下不适用
- AIDL: 只有允许不同应用的客户端用 IPC 方式访问服务,并且想要在服务中处理多线程时,才有必要使用 AIDL。
1. AIDL 语法
- AIDL文件以 .aidl 为后缀名
- AIDL支持的数据类型分为如下几种:
- 八种基本数据类型:byte、char、short、int、long、float、double、boolean 只支持in定向流(客户端到服务端)
- String,CharSequence 只支持in定向流(客户端到服务端)
- 实现了Parcelable接口的数据类型
- List 类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
- Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
-
AIDL文件可以分为两类。
- 一类是用来定义接口方法,声明要暴露哪些接口给客户端调用
- 一类用来声明实现了Parcelable接口的数据类型,以供其他AIDL文件使用那些非默认支持的数据类型。
-
定向Tag。定向Tag表示在跨进程通信中数据的流向,用于标注方法的参数值,分为 in、out、inout 三种。
- in 表示数据只能由客户端流向服务端
- out 表示数据只能由服务端流向客户端
- inout 数据可在服务端与客户端之间双向流通
明确导包。在AIDL文件中需要明确标明引用到的数据类型所在的包名,即使两个文件处在同个包名下
2. AIDL 实现进程间通信实现步骤
服务端
- 创建AIDL接口文件中需要传输的数据类型的接口文件。创建对应的实体类实现Parcelable接口
// Book.aidl
package com.littlezan.interviewpractice.module.aidl;
// Declare any non-default types here with import statements
parcelable Book ;
public class Book implements Parcelable {
private String name;
public Book(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
}
public void readFromParcel(Parcel dest) {
name = dest.readString();
}
public Book() {
}
protected Book(Parcel in) {
this.name = in.readString();
}
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
@Override
public Book createFromParcel(Parcel source) {
return new Book(source);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
- 创建AIDL接口文件。
// IMyAidlBookInterface.aidl
package com.littlezan.interviewpractice.module.aidl;
// Declare any non-default types here with import statements
import com.littlezan.interviewpractice.module.aidl.Book;
interface IMyAidlBookInterface {
List<Book> getBookList();
void addBookInOut(inout Book book);
}
- 创建一个Service,用来和客户端通信
public class AIDLService extends Service {
private static final String TAG = "AIDLService";
private List<Book> bookList;
public AIDLService() {
}
@Override
public void onCreate() {
super.onCreate();
bookList = new ArrayList<>();
initData();
}
private void initData() {
Book book1 = new Book("活着");
Book book2 = new Book("或者");
Book book3 = new Book("叶应是叶");
Book book4 = new Book("https://github.com/leavesC");
Book book5 = new Book("http://www.jianshu.com/u/9df45b87cfdf");
Book book6 = new Book("http://blog.csdn.net/new_one_object");
bookList.add(book1);
bookList.add(book2);
bookList.add(book3);
bookList.add(book4);
bookList.add(book5);
bookList.add(book6);
}
private final IMyAidlBookInterface.Stub stub = new IMyAidlBookInterface.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
return bookList;
}
@Override
public void addBookInOut(Book book) throws RemoteException {
if (book != null) {
book.setName("服务器改了新书的名字 InOut");
bookList.add(book);
} else {
Log.e(TAG, "接收到了一个空对象 InOut");
}
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return stub;
}
客户端
- 复制服务端aidl接口文件及实体类到项目中。将 aidl 文件夹整个复制到和Java文件夹同个层级下,不需要改动任何代码
- 绑定Service进程通信
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyAidlBookInterface bookController = IMyAidlBookInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};