AidlAndroid interface definition language)是一种android内部进程间通信(ipcInter-Process Communication)接口的描述语言,通过它我们可以定义进程间的通信接口,Aidl是最常用的ipc的方式;

Binder是什么呢?借鉴任玉刚的解读:binderAndroid中的一个类,实现了IBinder接口;从ipc角度来说,binderAndroid中的一种ipc方式;从Android framework角度来说,binderServiceManager连接各种managerActivityManagerWindowManager等)和相应的ManagerService的桥梁;从Android应用层来说,binder是客户端与服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,客户端就可以获取服务端条国内的服务或者数据,这里的服务包括普通服务和基于aidl的服务;

Aidlbinder的关系是什么?Aidl的本质是系统为我们提供了一种快速实现binder的工具,仅此而已;

进入正题之前,先来回顾一下aidl的大致流程:首先创建一个Serviceaidl接口,接着创建一个类继承自aidl接口中的Stub类并实现其中的抽象方法,在serviceonbind方法中返回这个类的对象,然后客户端就可以绑定服务端service,建立连接之后就可以访问远程服务端的方法了;

再来看看开发过程中可能遇到的一种场景:公司的项目做的非常之大了,有10个不同的业务模块都需要使用aidl来进行ipc,该怎么处理呢?一种最简单的思路就是:按照aidl的实现方式一个个来吧,需要创建10service,如果是100aidl,那么我们就创建100service,但是我们不能无限制的增加serviceservece是四大组件之一,是一种系统资源,太多的service会使我们的应用看起来非常的重量级,哎,算了,这种思路肯定是没有实际应用价值的,于是binder连接池千呼万唤始出来。

 基于aidl机制的binder连接池的实现_第1张图片

简单分析一下Binder连接池的工作机制:每个业务模块创建自己的aidl接口并实现此接口,不同业务模块之间不能有耦合,所有实现细节单独开发,然后向服务端提供自己唯一标识和对应的binder对象,对于服务端来说,只需要一个service就可以了,服务端提欧共一个queryBinder接口,这个接口能够根据不同业务模块的特征来返回相应的binder对象给客户端,不同业务模块拿到所需的binder对象后就可以进行远程方法的调用了;

接下来我们走起一个具体的实例:

首先,提供两个aidl接口(IsecurityCenter,ICompute);

package com.curry.ipc.binderpool;// Declare any non-default types here with import statementsinterface IsecuriteCenter {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    String encrypt(String content);    String decrypt(String content);}

package com.curry.ipc.binderpool;// Declare any non-default types here with import statementsinterface ICompute {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    int add(int a,int b);}
然后,是两个aidl接口的具体实现:

package com.curry.ipc.binderpool;import android.os.RemoteException;/** * Created by Curry on 2017/9/11. */public class SecuriteCenterImpl extends IsecuriteCenter.Stub {    private static final char SECRET_CODE='^';    @Override    public String encrypt(String content) throws RemoteException {        return "hallo android";    }    @Override    public String decrypt(String content) throws RemoteException {        return "hallo world";    }}
package com.curry.ipc.binderpool;import android.os.RemoteException;/** * Created by Curry on 2017/9/11. */public class ComputeImpl extends ICompute.Stub{    @Override    public int add(int a, int b) throws RemoteException {        return a+b;    }}
业务模块的aidl接口定义和实现都已经完成,但是并没有为每一个aidl单独创建service,接下来就是服务端和binder连接池;

首先,为binder连接池创建aidl接口IbinderPool;

// IBinderPool.aidlpackage com.curry.ipc.binderpool;// Declare any non-default types here with import statementsinterface IBinderPool {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    IBinder queryBinder(int binderCode);}

然后,为binder连接池创建远程service并实现ibinderpool;

public class BinderPoolService extends Service {    private static final String Tag="BinderPoolService";    private Binder mBinderPool=new BinderPool.BinderPoolImpl();    @Override    public void onCreate() {        super.onCreate();    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return mBinderPool;    }    @Override    public void onDestroy() {        super.onDestroy();    }}

接着,就是binder连接池的具体实现了;

public class BinderPool {    private static final String Tag="BinderPool";    public static final int BINDER_NONE=-1;    public static final int BINDER_COMPUTE=0;    public static final int BINDER_SECURITY=1;    private Context mContext;    private IBinderPool mBinderPool;    private static volatile BinderPool mInstance;    private CountDownLatch mLatch;    private BinderPool(Context context){        mContext=context.getApplicationContext();        connectBinderPoolService();//第一次测试的时候竟然忘记了调用连接的方法,我了个擦    }    public static BinderPool getmInstance(Context context){        if (mInstance==null){            synchronized (BinderPool.class){                if (mInstance==null){                    mInstance=new BinderPool(context);                }            }        }        return mInstance;    }    private synchronized void connectBinderPoolService(){        mLatch=new CountDownLatch(1);        Intent service=new Intent(mContext,BinderPoolService.class);        mContext.bindService(service,mBinderPoolConnection,Context.BIND_AUTO_CREATE);        try {            mLatch.await();        }catch (InterruptedException e){            e.printStackTrace();        }    }    public IBinder queryBinder(int binderCode){        IBinder binder=null;        try {            if (mBinderPool!=null){                binder=mBinderPool.queryBinder(binderCode);            }        }catch (RemoteException e){            e.printStackTrace();        }        return binder;    }    private ServiceConnection mBinderPoolConnection=new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mBinderPool=IBinderPool.Stub.asInterface(service);            try {                mBinderPool.asBinder().linkToDeath(deathRecipient,0);            }catch (RemoteException e){                e.printStackTrace();            }            mLatch.countDown();        }        @Override        public void onServiceDisconnected(ComponentName name) {        }    };    private IBinder.DeathRecipient deathRecipient=new IBinder.DeathRecipient() {        @Override        public void binderDied() {            mBinderPool.asBinder().unlinkToDeath(deathRecipient,0);            mBinderPool=null;            connectBinderPoolService();        }    };    public static class BinderPoolImpl extends IBinderPool.Stub{        public BinderPoolImpl(){            super();        }        @Override        public IBinder queryBinder(int binderCode) throws RemoteException {            IBinder binder=null;            switch (binderCode){                case BINDER_COMPUTE:                    binder=new ComputeImpl();                    break;                case BINDER_SECURITY:                    binder=new SecuriteCenterImpl();                    break;                default:                    break;            }            return binder;        }    }}

最后,就是见证奇迹的时刻了,新建一个Main5Activity来验证一下效果;

public class Main5Activity extends AppCompatActivity {        public IsecuriteCenter mSecurityCenter;    public ICompute computeCenter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main4);        new Thread(r).start();//        i = new Intent(this, BookManagerService.class);//        bindService(i, connection, Context.BIND_AUTO_CREATE);    }    private Runnable r=new Runnable() {        @Override        public void run() {            doWork();        }    };    private void doWork(){        BinderPool binderPool=BinderPool.getmInstance(Main5Activity.this);        IBinder securityBinder=binderPool.queryBinder(BinderPool.BINDER_SECURITY);        if (securityBinder==null){            return;        }        mSecurityCenter=(IsecuriteCenter)SecuriteCenterImpl.asInterface(securityBinder);        Log.d(Tag,"visit security");        String msg="hallo android";        Log.d(Tag,"content:"+msg);        try {            String password=mSecurityCenter.encrypt(msg);            Log.d(Tag,"content1:"+password);            Log.d(Tag,"content11:"+mSecurityCenter.decrypt(password));        }catch (RemoteException E){            E.printStackTrace();        }        Log.d(Tag,"visit compute");        IBinder computeBinder=binderPool.queryBinder(BinderPool.BINDER_COMPUTE);        if (securityBinder==null){            return;        }        computeCenter=(ICompute)ComputeImpl.asInterface(computeBinder);        try {            Log.d(Tag,"compute:"+computeCenter.add(3,9));        }catch (RemoteException e){            e.printStackTrace();        }
    }
}
   
来看看代表成功的log;

09-11 19:12:15.217 3685-3698/? D/Main5Activity: visit security09-11 19:12:15.217 3685-3698/? D/Main5Activity: content:hallo android09-11 19:12:15.237 3685-3698/? D/Main5Activity: content1:hallo android09-11 19:12:15.237 3685-3698/? D/Main5Activity: content11:hallo world09-11 19:12:15.237 3685-3698/? D/Main5Activity: visit compute09-11 19:12:15.237 3685-3698/? D/Main5Activity: compute:12

本文的思路和案例来源于任玉刚的《Android开发艺术探索》,没读过的同学推荐读读此书。


更多相关文章

  1. Android 抽象回调函数以及接口回调更新UI
  2. [Android]RecyclerView基本使用+adapter回调接口实现点击事件
  3. Android学习笔记之网络接口(Http接口,Apache接口,Android接口)
  4. Android 接口回调机制
  5. Android 网络编程 API笔记 - java.net 包相关 接口 api
  6. Android WebView与服务端交互Demo
  7. 第三部分:Android 应用程序接口指南---第四节:动画和图形---第五章
  8. Android 驱动之旅: 第三章 硬件抽象层(HAL)增加接口模块访问硬件

随机推荐

  1. [置顶] Android本地文件管理器思路解析一
  2. 第十一章、Android的线程和线程池
  3. Android菜鸟的成长笔记(22)——Android进程
  4. Android图形显示系统——上层显示1:界面绘
  5. Android五种布局管理器之『LinearLayout
  6. android广播发送与接收演示DEMO
  7. android中自定义数据类型在两个activity
  8. Android图片特效处理之图片叠加
  9. Android硬件抽象Hardware库加载过程源码
  10. Android串口丢包重发的重传协议,一种流式