典型代表就是App中通过aidl实现的service组件。
aidl实际上帮我们完整实现了服务代理类,以及是是实现了binder服务类中与语义处理相关的所有操作,例如方法编号的分配,方法参数从parcel中的提取,以及返回值打入parcel中等所有的操作。开发者只需要实现服务接口即可。
因为app是没有权限向ServiceManager注册服务的,那么怎么获取app中的额service实体的引用binder呢???
那就是直接传递binder实体,将binder实体对象打入到Parcel中,跨进程传入到AMS中去。
Binder实体在Binder驱动中的传输,会被特殊处理,最终返回到AMS中的是一个binder引用对象。(详细过程后续在分析喽!!!)
其他App进程中的组件便可以通过AMS拿到要请求的service服务的binder引用对象了。要注意的是,此过程中是AMS将所请求的binder服务的引用对象打入Parcel,然后通过Binder驱动传递到请求者进程中。
简单的说就是Binder实体对象的传递过程,伴随着binder服务在Binder驱动中相关数据结构初始化以及binder引用对象的创建过程。
不通过aidl实现一个service,来熟悉一下整个过程:
1. 首先顶定义一个服务接口,即服务要对外提供哪些方法。
IBinderService.java:
publicinterfaceIBinderServiceextendsIInterface{
String getMessage();
/**
* 服务的描述,客户端在使用parcel跨进程传输数据的时候
* 必须首先写入服务的描述,即该数据是发给哪个binder的。
* 将来服务端收到数据后会检查这个服务描述是否和自己的一致,不一致就不做处理了
*/
String DESCRIPITON = \;
// 定义方法编号
int GET_MESSAGE = IBinder.FIRST_CALL_TRANSACTION+0;
}
binder服务接口必须继承自IInterface接口,该接口中只有一个方法:
public IBinder asBinder()
binder服务接口一般要包含三部分内容:
首先是该binder服务的描述DESCRIPITON,发送数据时必须先发送该描述,接收数据时必须先对该描述进行检查,和自己不匹配的话那就不用继续进行了。
然后是方法编号,这个编号实际含义要在binder实体对象中的onTransact()方法中才能体现出来。可以理解为onTransact()根据这个编号调用不同的处理分支。
最后就是该服务对外提供的具体方法声明了。
binder实体端和代理对象端必须都继承这个服务接口,并实现其中的方法。另外服务端还要重载binder的onTransact()方法。
2. 实现bidner服务端
binder服务端的重点在于实现onTransact()方法,该方法中会依据客户端传入的方法编号,调用恰当的分支进行处理。
处理过程也是很简单的,就是从parcel中解析参数,调用对应的方法执行,将执行结果打入parcel中。
publicclassBinderServiceStubextendsBinderimplementsIBinderService{
publicBinderServiceStub(){
// 调用该方法后binder实体端的binder.queryLocalInterface()
// 返回就不会为null。
attachInterface(this,DESCRIPITON);
}
// 实现服务接口方法
public String getMessage() {
return\i am from Message!!!!!\;
}
/**
* 顾名思义,将自身转换为一个IBinder对象,
* 因为Binder继承子Binder,Binder继承自IBinder
*/
@Override
public IBinder asBinder() {
returnthis;
}
@Override
protectedbooleanonTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code){
case GET_MESSAGE:{
// 客户端先发送的是服务描述,所以这里先接收服务描述并判断是否和自己一致
data.enforceInterface(DESCRIPITON);
// 开始执行客户端请求的服务端的方法
String msg = getMessage();
// 将结果打入Parcel
reply.writeNoException();
reply.writeString(msg);
returntrue;
}
}
/**