深入 Android 系统 Binder-2- 使用,阿里 P7 亲自讲解
Binder
中提供了asInterface
方法来完成Binder代理对象
的转换,asInterface
会检查参数中的IBinder对象
的服务类型是否相符,如果不符将返回NULL
。
正常情况下,`ServiceManage
r进程会在所有应用启动前启动,而且不会停止服务,因此使用
defaultServiceManager()不必检查返回为
NULL的情况,但是对于方法
getService()的返回值需要检查是否为
NULL`,因为服务可能不存在或者未启动。
[](
)Binder
的混合调用
Binder
是可以混合调用的,在C++
中可以调用Java
实现的Binder服务
,在Java
中也可以调用C++
实现的Binder服务
。
以ActivityManagerService
服务为例,其中定义的方法为
public int checkPermission(String permission, int pid, int uid, int mode);
,我们看下C++
调用的大体流程(有注释哈):
//获取 Binder 引用对象
sp<Binder> binder = defaultServiceManager()->getService("activity");
//创建 Parcel data 放置方法调用是的参数信息
Parcel data = Parcel.obtain();
//创建 Parcel reply 接收返回信息
Parcel reply = Parcel.obtain();
//添加接口识别 Token
data.writeInterfaceToken("android.app.IActivityManager");
//添加请求的权限、pid、uid、mode 等方法调用信息
data.writeString16(permission);
data.writeInt32(pid);
data.writeInt32(uid);
data.writeInt32(mode);
//调用远程函数号为 54 的远程服务
binder->transact(54, data, &reply, 0);
示例代码中最重要的是54
这个参数,叫做远程函数号
。这个号码在服务端代码中定义,而且随着系统版本不同可能会有所改变,所以示例方法并不是一个很科学和常用的方法,不要学坏哈。只是想说明Binder
很强大。。。
[](
)Java 层的 Binder 服务
我们先用组件Service
来回顾一下流程:
首先,编写一个AIDL
文件
interface ICommandService {
void setResult_bool(String cmdid, boolean result);
void setResult_byte(String cmdid, in byte[] resultMsg);
void setResult_string(String cmdid, String resultMsg);
void finishCommand(String cmdid, String param);
}
然后,我们创建一个自定义的 Service,然后这样写:
public class CommandService extends Service{
protected final ICommandService.Stub mBinder = new ICommandService.Stub() {
@Override
public void setResult_bool(String cmdid, boolean result) throws RemoteException {
//do something
}
@Override
public void setResult_byte(String cmdid, byte[] resultMsg) throws RemoteException {
//do something
}
@Override
public void setResult_string(String cmdid, String resultMsg) throws RemoteException {
//do something
}
@Override
public void finishCommand(String cmdid, String param) throws RemoteException {
评论