Binder小结以及Binder连接池

文章目录

  • Binder小结
  • Binder线程池
    • 创建各功能的AIDL以及Binder连接池AIDL文件
    • 创建功能实体类
    • 创建连接池实体类
    • 建立BinderProxy
    • 为BinderProxy加上中断重连

Binder小结

从开始学习Binder以来,一直看到的都是ServerServiceManagerClient,这在一开始就有点加重理解负担。

  1. Binder就是一种IPC(Inter-Process Communication 进程间通讯)解决方案,如:共享内存、socket、管道等。
    Binder小结以及Binder连接池_第1张图片
  2. Android上的所有应用都是由各类服务(Server)共同工作完成的,例如:相机、屏幕、音箱等。Server在各自独立的进程中运行,每个App也都是运行在拥有独立进程的虚拟机中,所以要在App中使用各种Server就需要进程间通讯(IPC),考虑到安全、效率以及管理等问题,Android系统采用了Binder来实现这个通讯过程,Binder只是IPC的方法,为了让Server能被其他进程以Binder方式访问,Server同时也是一个Binder实体,与Server进行通讯的通常是对应的Manager对象。
  • 服务Server由来:硬件→驱动→HAL→Server。(服务运行在自己的进程中)
  1. Client获取Server的C/S架构。
  • ServerManager本身是一个Server,一个进程使用 BINDERSETCONTEXT_MGR 命令通过 Binder驱动将自己注册成为 ServiceManager
  • Client首先使用0ServerManager的全局代理—通过Binder驱动实现在ServerManager实体中查询需要的Server引用(第一次Binder通讯)。
  • Client然后通过Server代理调用Server(Binder)实体(第二次Binder通讯)。
  1. 日常开发中的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架构。

Binder线程池

在复习《Android开发艺术》时,又认真写了一次Binder连接池。

创建各功能的AIDL以及Binder连接池AIDL文件

使需要被远程调用的类继承Binder类,成为Binder对象,同时Binder类需要实现IInterface接口,这一工作通过建立AIDL文件完成。

在创建AIDL文件时,若内部含有自定义的Parcelable类,需要为该类建立一个同packagesimple的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.aidlICompute.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)回调时得到BinderPoolImplBinder代理。通过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

建立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;
    }
}

为BinderProxy加上中断重连

在连接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();
        }
    };

你可能感兴趣的:(Android,Android基础)