IBinder sm = (IBinder) Reflect.on(\).call(\,\).get();
// 拿到方法编号
int funCode = IBinder.FIRST_CALL_TRANSACTION+21;
// 准备方法参数数据
Parcel data = Parcel.obtain();
// 首先要写入的数据必须是binder服务端的descriptor
data.writeInterfaceToken(\);
// 接下来是方法的参数
data.writeStrongBinder((IBinder)Reflect.on(this).field(\).get());
// 用于接受返回数据
Parcel reply = Parcel.obtain();
// 发起RPC调用,同步调用,直到调用结束,期间一直阻塞
try {
sm.transact(funCode,data,reply,0);
} catch (RemoteException e) {
e.printStackTrace();
}
// 读取返回数据
reply.readException();
// 解析返回数据
ComponentName res = ComponentName.readFromParcel(reply);
// 回收parcle
data.recycle();
reply.recycle();
Log.i(\,\Activity name: \+res.getClassName());
}
}
通过binder代理对象发起RPC操作
对于前面例子中获取调用者的情况,实际开发中都是通过Activiy.getCallingActivity()来获取的:
public ComponentName getCallingActivity() {
try {
return ActivityManagerNative.getDefault().getCallingActivity(mToken);
} catch (RemoteException e) {
returnnull;
}
}
其中ActivityManagerNative.getDefault()返回的是
ActivityManagerProxy对象。
ActivityManagerProxy是AMS的binder代理类。
binder代理对象通过内聚的binder引用对象间接发起RPC操作。对于系统服务来说,它的binder代理对象都是事先定义好的。binder代理对象还要实现服务接口,实际上就是对binder引用对象发起RPC操作的二次封装。
classActivityManagerProxyimplementsIActivityManager{
...............public ComponentName getCallingActivity(IBinder token)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
mRemote.transact(GET_CALLING_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}
...............
可以看到代理类中已经帮我们封装好了getCallingActivity()的操作。因为直接通过binder引用发起RPC操作的话,需要开发者知道方法的编号,而方法的编号又是随着Android版本的变化而可能发生改变的。所以一般来说都会为binder服务封装一个binder代理类。这样做还有一个好处是通过一个binder引用对象,可以创建多个binder代理对象。
binder服务分类
分为两大类:
向ServiceManager注册的binder服务
Android系统中自带的绝大多数服务,例如AMS,PMS等都会向ServiceManager注册,注册时会传入一个service名字,例如AMS注册是传入的是“activity”。
客户端可以通过名字向ServiceManager查询对象的binder服务,ServiceManager会返回一个IBinder对象。
至于说返回的IBinder对象究竟是实体bidner呢还是引用binder,按照下面的规则决定:
当binder服务端同进程请求该服务时,返回的是binder实体对象。
当请求者与binder服务端在一个进程时,返回的是引用对象。
没有向ServiceManager注册的的bidner服务,又被称为匿名binder服务