1.为什么试用aidl,而不是直接通信?
- 一个进程空间分为:用户态(用户空间)和内核态(内核空间),即把进程内用户和内核隔离开来
- 进程之间,由于Android系统为每个进程分配了一个独立的虚拟机,用户空间和内核空间的数据不可交互
- Binder作为进程间的介质,充当了中介,使得进程间的内核态可以通过Binder进行数据交互
2.通信过程
- 首先编写以“aidl”结尾的aidl文件,编译生成同名的java文件,在app/build/generated/source/aidl 目录下
- 打开aidl生成的java文件查看主要类,当前类实现了IInterface接口,同时生成的Stub抽象类(运行在Service端),以及Stub抽象类的内部类 Proxy代理类(运行在Client端)
- 开始通信,通过自定义一个方法,例如 call(String msg)
private android.os.IBinder mRemote;
@Override
public java.lang.String call(java.lang.String req) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(req);
// 调用了IBinder 的transact
// 第一个参数表示这一次请求执行的意图,IBinder定义了像
// INTERFACE_TRANSACTION、PING_TRANSACTION这样的几个通用命令。
// 自己使用的命令的标识值需要在FIRST_CALL_TRANSACTION和LAST_CALL_TRANSACTION之间。
// 这个参数是客户端和服务端约定好的。
// 第二个参数表示向服务端发送的数据,不能为null。
// 第三个参数表示服务端返回的数据,可以为null。
// 第四个参数flags只有0和FLAG_ONEWAY (=1)两种,默认的跨进程操作是同步的,所以transact()方法的执行会阻塞flasg=0;
//指定FLAG_ONEWAY时,表示Client的transact()是单向调用,执行后立即返回,无需等待服务端返回。
mRemote.transact(Stub.TRANSACTION_call, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
**注意:**执行 transact 后当前线程就会被阻塞,直到服务端返回结果,如果耗时太长,需要我们在子线程开启通信
再进入查看 IBinder 的 transact是空方法,查找子类Binder
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
可以看到最终调用了Binder的onTransact 方法,再查看我们的Stub抽象类,继承了Binder类,重写了onTransact方法
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_call: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
java.lang.String _result = this.call(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
根据code不同执行不同的方法,然后将数据写入reply,最后Proxy代理类收到数据,线程继续向下执行。
binder kernel 那一块还在研究… 会更新的
最后附Binder路径: platform_frameworks_base/core/java/android/os/