Android跨进程通信之Binder连接池及选择合适的IPC方式
借鉴自开发艺术
AIDL是最常用的多进程通信的技术,但是每次使用都要创建一个Service,开销太大,应该把所有的AIDL都放到一个Service里。
每个业务模块都创建自己的AIDL接口并实现,业务模块间不能有耦合,然后向服务器提供自己的唯一标识和对应的Binder对象。对于服务端,1个Service足够了。服务端提供一个queryBinder接口,从中可以获取业务模块对应的Binder。拿到Binder就可以远程调用了。所以,Binder连接池的作用是把所有业务模块的Binder请求统一转发到远程Service中去执行。
原理图
两个AIDL接口及其实现类
// ISecurityCenter.aidl package com.example.test; // Declare any non-default types here with import statements interface ISecurityCenter { String encrypt(String content); String decrypt(String password); }
// ICompute.aidl package com.example.test; // Declare any non-default types here with import statements interface ICompute { int add(int a, int b); }
public class ComputeImpl extends ICompute.Stub { @Override public int add(int a, int b) throws RemoteException { return a + b; } }
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); } }
一个Binder池接口
// IBinderPool.aidl package com.example.test; // Declare any non-default types here with import statements interface IBinderPool { IBinder queryBinder(int binderCode); }
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_CENTER = 1; private Context mContext; private IBinderPool mBinderPool; private static volatile BinderPool sInstance; private CountDownLatch mConnectionBinderPoolCountDownLatch; private BinderPool (Context context) { mContext = context.getApplicationContext(); connectBinderPoolService(); } public static BinderPool getInstance(Context context) { if (sInstance == null) { synchronized (BinderPool.class) { if (sInstance == null) { sInstance = new BinderPool(context); } } } return sInstance; } private synchronized void connectBinderPoolService() { mConnectionBinderPoolCountDownLatch = new CountDownLatch(1); Intent service = new Intent(mContext, BinderPoolService.class); mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE); try { mConnectionBinderPoolCountDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } public IBinder queryBinder(int binderCode) { IBinder binder = null; if (mBinderPool != null) { try { 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(mBinderPoolDeathRecipient, 0); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { Log.w(TAG, "binderDied: "); mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 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_SECURITY_CENTER : binder = new SecurityCenterImpl(); break; case BINDER_COMPUTE : binder = new ComputeImpl(); break; } return binder; } } }
service
public class BinderPoolService extends Service { private static final String TAG = "xbh"; private Binder mBinderPool = new BinderPool.BinderPoolImpl(); @Override public void onCreate() { super.onCreate(); } public BinderPoolService() { } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind: "); return mBinderPool; } @Override public void onDestroy() { super.onDestroy(); } }
调用
public class MainActivity extends AppCompatActivity { private static final String TAG = "xbh"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { doWork(); } }).start(); } private void doWork() { BinderPool binderPool = BinderPool.getInstance(this); IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER); ISecurityCenter mSecurityCenter = SecurityCenterImpl.asInterface(securityBinder); Log.i(TAG, "visit ISecurityCenter"); String msg = "helloworld-安卓"; Log.i(TAG, msg); try { String password = mSecurityCenter.encrypt(msg); Log.i(TAG, password); Log.i(TAG, mSecurityCenter.decrypt(password)); } catch (RemoteException e) { e.printStackTrace(); } Log.i(TAG, "visit ICompute"); IBinder computeBindedr = binderPool.queryBinder(BinderPool.BINDER_COMPUTE); ICompute mCompute = ComputeImpl.asInterface(computeBindedr); try { Log.i(TAG, mCompute.add(3,5) + ""); } catch (RemoteException e) { e.printStackTrace(); } } }
选择合适的IPC方式