从开始学习Binder
以来,一直看到的都是Server
、ServiceManager
、Client
,这在一开始就有点加重理解负担。
Binder
就是一种IPC
(Inter-Process Communication 进程间通讯
)解决方案,如:共享内存、socket、管道等。Android
上的所有应用都是由各类服务(Server
)共同工作完成的,例如:相机、屏幕、音箱等。Server
在各自独立的进程中运行,每个App
也都是运行在拥有独立进程的虚拟机中,所以要在App
中使用各种Server
就需要进程间通讯(IPC
),考虑到安全、效率以及管理等问题,Android
系统采用了Binder
来实现这个通讯过程,Binder
只是IPC
的方法,为了让Server
能被其他进程以Binder
方式访问,Server
同时也是一个Binder
实体,与Server
进行通讯的通常是对应的Manager
对象。
- 服务
Server
由来:硬件→驱动→HAL→Server。(服务运行在自己的进程中)
Client
获取Server
的C/S架构。
ServerManager
本身是一个Server
,一个进程使用BINDERSETCONTEXT_MGR
命令通过Binder
驱动将自己注册成为ServiceManager
;Client
首先使用0
—ServerManager
的全局代理—通过Binder
驱动实现在ServerManager
实体中查询需要的Server
引用(第一次Binder
通讯)。Client
然后通过Server
代理调用Server
(Binder
)实体(第二次Binder
通讯)。
Binder
通讯:当在进程1中调用进程2中的
Binder
时对象时,通常会有如下代码:
- Process 1:
@Override public void onServiceConnected(ComponentName name, IBinder service) { }
中的service
就是Binder
代理;- Process 2:
@Override public IBinder onBind(Intent intent) { return mBinder; }
中的mBinder
就是Binder
实体。
这里只使用了Binder
实现IPC
通讯,并没有直接参与第3点中的C/S架构。
在复习《Android开发艺术》时,又认真写了一次Binder
连接池。
使需要被远程调用的类继承Binder
类,成为Binder
对象,同时Binder
类需要实现IInterface
接口,这一工作通过建立AIDL文件完成。
在创建AIDL文件时,若内部含有自定义的
Parcelable
类,需要为该类建立一个同package
同simple
的AIDL文件,例如:在com.wimi.jian.myapplication.aidl
有://Book.java package com.wimi.jian.myapplication.aidl; public class Book implements Parcelable{......}
则需要:
// Book.aidl package com.wimi.jian.myapplication.aidl; parcelable Book;
建立ISecurityCenter.aidl
与ICompute.aidl
// ISecurityCenter.aidl
package com.wimi.jian.myapplication.aidl;
interface ISecurityCenter {
String encrypt(String content);
String decrypt(String password);
}
// ICompute.aidl
package com.wimi.jian.myapplication.aidl;
interface ICompute {
int add(int a, int b);
}
建立连接池IBinderPool.aidl
// IBinderPool.aidl
package com.wimi.jian.myapplication.aidl;
interface IBinderPool {
IBinder queryBinder(int binderCode);
}
为Binder
实体建立相关的类,即建立继承Stub
的非抽象类。
//:ComputeImpl.java
public class ComputeImpl extends ICompute.Stub {
@Override
public int add(int a, int b) throws RemoteException {
return a + b;
}
}
//:SecurityCenterImpl.java
public class SecurityCenterImpl extends ISecurityCenter.Stub {
private static final char SECRET_CODE = '^';
@Override
public String encrypt(String content) throws RemoteException {
char[] chars = content.toCharArray();
for (int i = 0; i < chars.length; i ++){
chars[i] ^= SECRET_CODE;
}
return new String(chars);
}
@Override
public String decrypt(String password) throws RemoteException {
return encrypt(password);
}
}
创建BinderPool
实体类BinderPoolImpl
。当用户连接Service
时,将BinderPoolImpl
对象返回,用户在onServiceConnected(ComponentName name, IBinder service)
回调时得到BinderPoolImpl
的Binder
代理。通过Binder
代理操作Binder
实体,并返回相关数据。
//:MBinderService.java
public class MBinderService extends Service {
private Binder mBinderPool = new BinderPoolImpl();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinderPool;
}
public static class BinderPoolImpl extends IBinderPool.Stub{
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode){
case BinderProxy.BINDER_SECURITY_CENTER:
binder = new SecurityCenterImpl();
break;
case BinderProxy.BINDER_COMPUTE:
binder = new ComputeImpl();
break;
default:break;
}
return binder;
}
}
}
建立BinderProxy
单例代理,封装连接Service
以及查询的逻辑。由于连接与实际调用需要同步,而连接过程本身是个异步操作,所以需要使用CountDownLatch
将异步过程同步化。
//:BinderProxy.java
/**
* 作为连接代理,帮助Activity连接其他业务的binder
* */
public class BinderProxy {
public static final int BINDER_SECURITY_CENTER = 0;
public static final int BINDER_COMPUTE = 1;
private IBinderPool mBinderPool;
private static volatile BinderProxy sInstance;
private Context mContext;
//BinderPool#queryBinder的代理效果是通过mBinderPool完成的,
//mBinderPool的赋值由bindService过程中异步调用onServiceConnected后完成
//用户使用如下操作完成调用,getInstance中调用bindService:
// BinderPool binderPool = BinderPool.getInstance(BinderActivity.this);
// IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
//为避免BinderPool#queryBinder调用时,mBinderPool为空,此处需要将异步过程变为同步。
private CountDownLatch mCountDownLatch;
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPool = IBinderPool.Stub.asInterface(service);
mCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
public BinderProxy(Context context) {
this.mContext = context.getApplicationContext();
connectBinderPoolService();
}
private void connectBinderPoolService() {
mCountDownLatch = new CountDownLatch(1);
Intent service = new Intent(mContext, MBinderService.class);
mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
try {
mCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static BinderProxy getInstance(Context context){
if (sInstance == null){
synchronized (BinderProxy.class){
if (sInstance == null){
sInstance = new BinderProxy(context);
}
}
}
return sInstance;
}
public IBinder queryBinder(int binderCode){
IBinder binder = null;
if (mBinderPool != null){
try {
binder = mBinderPool.queryBinder(binderCode);
} catch (RemoteException e) {
e.printStackTrace();
}
}
return binder;
}
}
在连接Service
后,为连接设置终端监听,并实现中断重连。
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPool = IBinderPool.Stub.asInterface(service);
try {
mBinderPool.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
mCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
mBinderPool.asBinder().unlinkToDeath(mDeathRecipient, 0);
mBinderPool = null;
connectBinderPoolService();
}
};