binder分为几个部分:client,service,serviceManager,driver,
以通过AIDL实现方式为例,我们如果已经创建客户端MyClient和服务端MyService,并且通过AIDL得到我们需要的引用文件(ServiceManager),这个引用文件ServiceManager.java从代码上看是个接口,其中有个继承Binder并实现本身接口的抽象类Stub,这个目的就是为了让我们在客户端和服务端根据其不同需求实现Stub并重写其中的方法,通过这些方法使客户端和服务端在Binder驱动创建的共享数据缓冲区进行数据读取。
图片来自http://blog.csdn.net/huachao1001/article/details/51504469
另外很重要的一点客户端调用服务端或者服务端调用客户中的一些方法(比如listener)当前线程是被挂起的,如果有耗时操作容易发生ANR,所以不要在主线程调用这些方法。
还有就是binder可能意外死亡,我们需要通过linkToDeath和unlinkToDeath设置死亡代理,去监听并做一些处理比如重新连接
大致过程如下:
首先声明一个DeathRecipient对象,这是个接口我们需要实现内部的方法binderDied,在onServiceConnected中通过linkToDeath设置代理,当binder意外死亡时会调用binderDied,我们需要在其中通过unlinkToDeath移除之前绑定的binder代理并重新绑定服务
private IBinder.DeathRecipient mDeathRecipient = new DeathRecipient() {
@Override
public void binderDied() {
// TODO Auto-generated method stub
Log.i(TAG, "binder is died");
if (mIAidlManager == null)
return;
mIAidlManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
mIAidlManager = null;
// TODO:重新绑定远程服务
……
}
};
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIAidlManager = mIAidlManager.Stub.asInterface(service);
try {
service.linkToDeath(mDeathRecipient, 0);
// TODO ……
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
哦对了,关于binder通信的安全性方面,可以通过onBind是否返回null或者通过重写Stub中的onTransact方法是否返回false来进行权限验证,具体方式就不展开了,累……
总结一下(觉得下面这哥们写的听通俗的直接引用过来)如果有哪位同学觉得不对欢迎指正:
以下来自http://blog.csdn.net/hao707822882/article/details/40109045
binder机制概要:传送的数据都是通过存放在driver的内核缓冲区中的,这样client会向binder发送命令往这个共享区域写数据,service的binder线程也会从这里读数据,过程是阻塞的,这样线程安全。
第一点,在客户端调用,实际是在和driver交互,不是在和service交互。
第二点:我们是怎么获取我们想要的service:所有的service都在servicemanager中注册了,要找,向他要,那怎么要呢?第三点
第三点:这要牵扯到serviceManager的注册,serviceManager的注册可以理解为:在serviceManager启动的时候,就会自告奋勇的申请成为driver的上下文,至于上下文里面的内容就是”xxxxx.xxx.xxxservice”=service这样的引用,这些引用是怎么生成的呢?第四点
第四点:当service要启动的时候,会主动的先向driver得到serviceManager的引用,然后再向serviceManafger发送第三点当中提到的引用,而在service的启动过程中,会通过driver在driver的内核空间创建一个共享的数据缓冲区(binder概要中提到的缓冲区就是这个),其实我个人观点,你要是把第三点当中提到的注册在servicemanager中的引用理解为这个缓冲区的引用,也不错,就是那么回事
第五点:在service启动的过程中,还启动了许多的线程来处理binder驱动卸载缓冲区的数据,这就是binder线程