使用BinderPool管理AIDL

1,239 阅读3分钟

个人博客: www.milovetingting.cn

使用BinderPool管理AIDL

前言

平时我们用到AIDL,一般的流程可能是这样:

  • 定义AIDL接口

  • 定义服务,在onBind方法中返回实现了AIDL接口的Stub类的实例

  • 调用bindService方法,在ServiceConnectiononServiceConnected回调中获取到Binder对象

  • 通过Binder对象调用接口中的方法

如果我们只是用到比较少的AIDL调用,那么上面的方法的确是可行的,但是,如果需要调用数量较多的AIDL,那么可以通过先访问一个BinderPool,然后再由BinderPool来查询相关的Binder服务,再将Binder服务返回。通过这种统一管理的方式,可以方便地管理AIDL。

下面详细介绍BinderPool具体的定义

定义IBinderPool

定义IBinderPoolqueryBinder方法返回IBinder对象

interface IBinderPool {
    IBinder queryBinder(int queryCode);
}

定义BinderPool

BinderPool定义为单例模式。通过getInstance获取到BinderPool的实例,并在构造方法中连接BinderPoolService

private static class BinderPoolHolder {
        static final BinderPool INSTANCE = new BinderPool();
    }

public static BinderPool getInstance(Context context) {
        mContext = context.getApplicationContext();
        return BinderPoolHolder.INSTANCE;
    }

private BinderPool() {
        connectBinderPoolService();
    }

private synchronized void connectBinderPoolService() {
        countDownLatch = new CountDownLatch(1);
        Intent intent = new Intent(mContext, BinderPoolService.class);
        mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

BinderPoolService返回IBinderPool对象

public class BinderPoolService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new BinderPool.BinderPoolImpl();
    }
}

BinderPoolImpl实现IBinderPool接口方法,queryBinder根据queryCode返回对应的Binder

static class BinderPoolImpl extends IBinderPool.Stub {

        @Override
        public IBinder queryBinder(int queryCode) throws RemoteException {
            IBinder binder = null;
            switch (queryCode) {
                case QUERY_CODE_BINDER_A:
                    binder = new BinderA();
                    break;
                case QUERY_CODE_BINDER_B:
                    binder = new BinderB();
                    break;
                default:
                    break;
            }
            return binder;
        }
    }

ServiceConnectiononServiceConnected返回Binder对象,并绑定DeathRecipient

private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binderPool = IBinderPool.Stub.asInterface(service);
            try {
                binderPool.asBinder().linkToDeath(deathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            countDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

DeathRecipient

private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            binderPool.asBinder().unlinkToDeath(deathRecipient, 0);
            binderPool = null;
            connectBinderPoolService();
        }
    };

完整的BinderPool代码

public class BinderPool {

    public static final int QUERY_CODE_BINDER_A = 1;

    public static final int QUERY_CODE_BINDER_B = 2;

    private static Context mContext;

    private CountDownLatch countDownLatch;

    private IBinderPool binderPool;

    public static BinderPool getInstance(Context context) {
        mContext = context.getApplicationContext();
        return BinderPoolHolder.INSTANCE;
    }

    private BinderPool() {
        connectBinderPoolService();
    }

    private synchronized void connectBinderPoolService() {
        countDownLatch = new CountDownLatch(1);
        Intent intent = new Intent(mContext, BinderPoolService.class);
        mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public IBinder queryBinder(int queryCode) {
        IBinder binder = null;
        if (binderPool != null) {
            try {
                binder = binderPool.queryBinder(queryCode);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return binder;
    }

    private static class BinderPoolHolder {
        static final BinderPool INSTANCE = new BinderPool();
    }

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binderPool = IBinderPool.Stub.asInterface(service);
            try {
                binderPool.asBinder().linkToDeath(deathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            countDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            binderPool.asBinder().unlinkToDeath(deathRecipient, 0);
            binderPool = null;
            connectBinderPoolService();
        }
    };

    static class BinderPoolImpl extends IBinderPool.Stub {

        @Override
        public IBinder queryBinder(int queryCode) throws RemoteException {
            IBinder binder = null;
            switch (queryCode) {
                case QUERY_CODE_BINDER_A:
                    binder = new BinderA();
                    break;
                case QUERY_CODE_BINDER_B:
                    binder = new BinderB();
                    break;
                default:
                    break;
            }
            return binder;
        }
    }
}

定义IBinderA及实现类

interface IBinderA {
    int calc(int a,int b);
}
public class BinderA extends IBinderA.Stub {
    @Override
    public int calc(int a, int b) throws RemoteException {
        return a + b;
    }
}

定义IBinderB及实现类

interface IBinderB {
    String getInfo(String info);
}
public class BinderB extends IBinderB.Stub {
    @Override
    public String getInfo(String info) throws RemoteException {
        return info + "-handled";
    }
}

客户端调用BinderPool

由于在连接BinderPoolService时,是通过调用CountDownLatch.await(),等待onServiceConnected的回调,因此如果直接在主线程调用BinderPool的方法,会导致主线程阻塞,发生ANR,因此需要放到子线程去处理。

new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    IBinder binder = BinderPool.getInstance(getApplicationContext()).queryBinder(BinderPool.QUERY_CODE_BINDER_A);
                    final int calc = IBinderA.Stub.asInterface(binder).calc(1, 2);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(), "calc:" + calc, Toast.LENGTH_SHORT).show();
                        }
                    });
                    IBinder binderB = BinderPool.getInstance(getApplicationContext()).queryBinder(BinderPool.QUERY_CODE_BINDER_B);
                    final String info = IBinderB.Stub.asInterface(binderB).getInfo("hello");
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(), "info:" + info, Toast.LENGTH_SHORT).show();
                        }
                    });
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }).start();

总结

通过定义BinderPool来管理所有的AIDL连接,当需要新增AIDL时,只需要增加对应的AIDL接口及对应的实现Binder,然后在BinderPool的queryBinder增加对应的queryCode处理即可。