Android中使用多进程可以分配更多的内存,内存空间隔离,Android系统是用户空间+内核空间,用户程序崩溃了系统内核程序也不受影响,其中Server、Client、ServiceManager 运行于用户空间,Binder驱动运行于内核空间。Android的多进程通信就是采用Binder实现的。
Binder驱动建立了内核缓存区和内核数据接收缓存区的映射关系,以及内核数据接收缓存区和接收进程用户空间地址的映射关系,内核缓存区和接收进程的用户空间地址存在内存映射,发送方进程将数据复制到内核缓存区,相当于把数据发送到了接收进程的用户空间。
为了更了解Android进程间的通信机制,理解AIDL的原理,利用binder实现进程间的通信,记录一次手写AIDL的过程
定义一个bean类Book,实现序列化
1 | public class Book implements Parcelable { |
定义操作接口类IBookManager继承IInterface,定义数据操作的方法
1 | public interface IBookManager extends IInterface { |
定义抽象类Stub继承Binder类和IBookManager接口
- 实现onTransact方法,获取传入的参数,调用IBookManager接口的方法,这里暂不实现IBookManager的方法
- 返回IBookManager对象,需传入binder对象,如果与这个传入的binder对象在同一进程调用queryLocalInterface返回,否则把Binder传入Proxy对象返回一个远程的代理对象
- 返回Binder对象(自身)定义一个代理类实现IBookManager接口,调用Stub类传入的Binder对象通过Stub类的onTransact方法进行数据操作
1
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58public abstract class Stub extends Binder implements IBookManager {
private static final String DESCRIPTOR = "com.enjoy.binder.common.IBookManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static IBookManager asInterface(IBinder binder) {
if ((binder == null)) {
return null;
}
// 先查找本地接口对象,如果同一个进程直接返回
IInterface iin = binder.queryLocalInterface(DESCRIPTOR);
if ((iin != null) && (iin instanceof IBookManager)) {
return (IBookManager) iin;
}
// 传入binder对象,返回一个远程的代理对象
return new Proxy(binder);
}
// 返回自身对象
public IBinder asBinder() {
return this;
}
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION:
reply.writeString(DESCRIPTOR);
return true;
// 添加书,调用addBook接口
case TRANSACTION_addBook:
data.enforceInterface(DESCRIPTOR);
// 获取传入的book对象
Book arg0 = null;
if ((0 != data.readInt())) {
arg0 = Book.CREATOR.createFromParcel(data);
}
this.addBook(arg0);
reply.writeNoException();
return true;
// 获取书的列表,调用getBookList接口
case TRANSACTION_getBookList:
data.enforceInterface(DESCRIPTOR);
List<Book> result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(result);
return true;
}
return super.onTransact(code, data, reply, flags);
}
static final int TRANSACTION_addBook = IBinder.FIRST_CALL_TRANSACTION;
static final int TRANSACTION_getBookList = IBinder.FIRST_CALL_TRANSACTION + 1;
}定义一个工作在独立进程的远程服务类,定义数据源,创建Binder对象,实现数据操作接口IBookManager内addBook方法和getBookList方法的具体业务逻辑,并返回创建的Binder对象1
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57public class Proxy implements IBookManager {
private static final String DESCRIPTOR = "com.enjoy.binder.common.IBookManager";
private IBinder mRemote;
// 保存Stub类传入的Binder对象
public Proxy(IBinder remote) {
mRemote = remote;
}
// 实现跨进程数据传输,调Binder对象的onTransact方法
public void addBook(Book book) throws RemoteException {
Parcel data = Parcel.obtain(); // 跨进程传输数据对象
Parcel reply = Parcel.obtain(); // 跨进程传输返回结果
try {
data.writeInterfaceToken(DESCRIPTOR);
if ((book != null)) {
data.writeInt(1);
book.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
// 调Stub的onTransact方法进行Stub.TRANSACTION_addBook处理,远端返回
mRemote.transact(Stub.TRANSACTION_addBook, data, reply, 0);
reply.readException();
} finally {
reply.recycle();
data.recycle();
}
}
// 实现跨进程数据传输,调Binder对象的onTransact方法
public List<Book> getBookList() throws RemoteException {
Parcel data = Parcel.obtain(); // 跨进程传输数据对象
Parcel reply = Parcel.obtain(); // 跨进程传输返回结果
List<Book> result;
try {
data.writeInterfaceToken(DESCRIPTOR);
// 调Stub的onTransact方法进行Stub.TRANSACTION_getBookList处理,远端返回
mRemote.transact(Stub.TRANSACTION_getBookList, data, reply, 0);
reply.readException();
result = reply.createTypedArrayList(Book.CREATOR);
} finally {
reply.recycle();
data.recycle();
}
return result;
}
// 返回Stub类传入的Binder对象
public IBinder asBinder() {
return mRemote;
}
}在AndroidManifest中声明该服务在对立进程1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class RemoteService extends Service {
private ArrayList<Book> books; // 定义数据源
// 服务绑定后返回Binder对象
public IBinder onBind(Intent intent) {
books = new ArrayList<>();
Log.e("RemoteService", "success onBind");
return iBinder;
}
// 创建一个Binder对象,实现IBookManager的数据操作方法,Stub类的对象在远端进程(独立进程)初始化
private IBinder iBinder = new Stub() {
public void addBook(Book book) throws RemoteException {
books.add(book);
}
public List<Book> getBookList() throws RemoteException {
return books;
}
};
}在主进程Activity中绑定远端服务进程,并通过binder对象调用数据操作方法1
2
3
4
5
6
7
8
9<service
android:name=".server.RemoteService"
android:exported="true"
android:process=":remote">
<intent-filter>
<action android:name="com.enjoy.binder" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>最后总结一下:1
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
41public class ClientActivity extends AppCompatActivity {
private IBookManager iBookManager;
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 绑定远端服务进程
Intent intent = new Intent(this, RemoteService.class);
intent.setAction("com.enjoy.binder");
bindService(intent, connection, Context.BIND_AUTO_CREATE);
// 点击,通过binder对象(远程代理对象)调用数据操作方法
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
iBookManager.addBook(new Book("数据结构与算法", 3));
List<Book> books = iBookManager.getBookList();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private ServiceConnection connection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("ClientActivity", "onServiceConnected: success");
iBookManager = Stub.asInterface(service);// Binder对象(远程代理对象)
}
public void onServiceDisconnected(ComponentName name) {
Log.e("ClientActivity", "onServiceDisconnected: success");
iBookManager = null;
}
};
} - Stub继承binder实现服务接口,onTransact根据code调服务接口
- Activity绑定远程服务,连接回调中获取Stub.asInterface,区分是否同一进程返回代理对象,如果是返回本地接口,否则返回远程服务onBinder返回的IBinder代理对象
- 代理类实现服务接口,数据打包,检查token,跨进程调transact序列化发送data和获取返回reply,客户端线程挂起
- 服务端实例化Stub并实现服务接口接收客户端请求并响应