AIDL 介绍
IPC 即 Inter-Process Communication (进程间通信),AIDL(Android Interface definition language) 是其中的一种方式,其功能强大,支持一对多并发通信,支持实时通信。
AIDL的作用是让你可以在自己的APP里绑定一个其他APP(或者进程)的service,这样你的APP可以和其他APP交互。
AIDL 使用
① 数据类准备
AIDL 用于处理进程间的数据通信,那么必然要先有数据。
创建 Book.java ,并实现 Parcelable 接口。
package com.zhxumao.android.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
int bookId;
String bookName;
protected Book(Parcel in) {
bookId = in.readInt();
bookName = in.readString();
}
public Book(int bookId, String bookName) {
this.bookId = bookId;
this.bookName = bookName;
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(bookId);
dest.writeString(bookName);
}
}
复制代码
② AIDL 接口创建
1、创建 AIDL 接口类 :IBookManager.aidl,并添加自定义方法。
2、因为 IBookManager.aidl 中用到了自定义的 Parcelable 对象 Book(非6种基础类型外),所以也需要创建下同名文件 Book.aidl
3、重新 Build 下工程,可在 build > gen 目录下找到 IBookManager 的实现类,这是由编辑器自动生成。
// IBookManager.aidl
package com.zhxumao.android.aidl;
import com.zhxumao.android.aidl.Book;
interface IBookManager {
void addBook(in Book book);
List<Book> getBookList();
}
复制代码
// Book.aidl
package com.zhxumao.android.aidl;
// Declare any non-default types here with import statements
//声明 parcelable 对象
parcelable Book;
复制代码
编辑器生成的 IBookManager 实现类
主要关注抽象静态内部类 Stub,需要我们在 service 中继承实现。
package com.zhxumao.android.aidl;
public interface IBookManager extends android.os.IInterface
{
/** Default implementation for IBookManager. */
public static class Default implements com.zhxumao.android.aidl.IBookManager {
//代码省略
...
}
public static abstract class Stub extends android.os.Binder implements com.zhxumao.android.aidl.IBookManager {
//代码省略
...
}
public void addBook(com.zhxumao.android.aidl.Book book) throws android.os.RemoteException;
public java.util.List<com.zhxumao.android.aidl.Book> getBookList() throws android.os.RemoteException;
}
复制代码
③ 远程服务端Service实现
1、创建 BookManagerService.java ,继承 Service
2、获取 AIDL 接口类中的 IBookManager#Stub 的实例,返回的是一个 Binder 对象:Binder mBinder = new IBookManager.Stub();
3、在 service 的 onBind() 中,返回以上 Binder 对象。
4、在 IBookManager 定义的方法体中,写自己服务端逻辑即可,服务端的功能就可以了。
public class BookManagerService extends Service {
private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<>();
private Binder mBinder = new IBookManager.Stub() {
@Override
public void addBook(Book book) throws RemoteException {
mBookList.add(book);
}
@Override
public List<Book> getBookList() throws RemoteException {
return mBookList;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
复制代码
//别忘记在 manifest.xml 中声明服务
<service
android:name=".BookManagerService"
android:process=":aidl" />
复制代码
④ 客户端实现
假设我们在某个 Activity 中:
1、实现 ServiceConnection 接口类,在 onServiceConnected() 中获取 IBookManager 对象。
private IBookManager manager;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
manager = IBookManager.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
复制代码
2、启动服务 BookManagerService,使用 bindService() 绑定启动服务,设置好 ServiceConnection 。
bindService(new Intent(MainActivity.this, BookManagerService.class), connection, Context.BIND_AUTO_CREATE);
复制代码
3、服务启动完成后,我们将在 ServiceConnection 中获取到 IBookManager 的实例,到此我们才能进行客户端的逻辑编写,比如想往 service 中插入/获取数据:
//插入一条数据
manager.addBook(new Book(1, "android"));
//获取service所有已保存数据
List<Book> bookList = manager.getBookList();
复制代码
现在整个 AIDL 的使用方式都已经实现了,注意最后退出的时候,如果不需要服务继续运行了,不要忘了解绑服务。
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
复制代码
最后总结一下,使用 AIDL 进行进程间通信,大概需要进行以下几个步骤:
- 创建 .aidl 接口文件。
- 在 service 中实现 aidl 接口的 Stub,并补充 service 业务逻辑(注意处理好线程并发问题)。
- 客户端实现 ServiceConnection ,并获取到 aidl 接口的实现类实例,并补充客户端业务逻辑。