一个Service管理多个AIDL接口

通常情况下,每个AIDL接口对应一个Service进行进程间通信,若有多个ADIL接口,也要创建多个Service,但Service是系统资源,无限制增加的话,会占用过多内存。下面就介绍下Binder连接池,以及怎样实现一个Service管理多个ADIL接口。

Binder连接池,是将各个业务模块的Binder请求统一转发到远程Service中去执行,可避免重复创建Sevice。

1 首先提供ISecurity、IPay两个接口,用于密码校验和支付

interface ISecurity {
    String encode(String psw);
    String decode(String psw);
}

interface IPay {
    void buy();
}

2 SecurityImpl、PayImpl是两个接口的实现

public class SecurityImpl extends ISecurity.Stub {//Stub内部类,其实就是一个Binder类
    private static final String TAG = "SecurityImpl lyl123";

    @Override
    public String encode(String psw) throws RemoteException {
        Log.e(TAG, "encode, psw = " + psw);
        char[] chars = psw.toCharArray();
        for (int i = 0;i < chars.length; i++){
            chars[i] ^= '^';
        }
        return new String(chars);
    }

    @Override
    public String decode(String psw) throws RemoteException {
        Log.e(TAG, "decode: psw = " + psw);
        return encode(psw);
    }
}


public class PayImpl extends IPay.Stub {//Stub内部类,其实就是一个Binder类
    private static final String TAG = "PayImpl lyl123";

    @Override
    public void buy() throws RemoteException {
        Log.e(TAG, "buy something");
    }
}

3 提供一个AIDL接口IBinderPool,并提供一个获取Binder的方法

interface IBinderPool {
    IBinder queryBinder(int binderCode);
}

4. Binder连接池的实现

public class BinderPool {
    private static final String TAG = "BinderPool lyl123";

    public static final int BIND_PAY = 1;
    public static final int BIND_SECURITY = 2;

    private Context mContext;
    private static volatile BinderPool instance;
    private ServiceConnection conn;
    private IBinderPool mBinderPool;
    private CountDownLatch mCountDownLatch;//用于线程间同步

    //for client
    //1. lazy singleton mode
    public static BinderPool getInstance(Context context){
        if (null == instance){
            synchronized (BinderPool.class) {
                if (null == instance) {
                   instance = new BinderPool(context);
                }
            }
        }
        return instance;
    }

    private BinderPool(Context context){
        mContext = context.getApplicationContext();
        bindPoolService();
    }

    private synchronized void bindPoolService() {
        Log.e(TAG, "bindPoolService");
        if (null == conn) {
            mCountDownLatch = new CountDownLatch(1);//1.定目标:把计数器初始化为1

            Intent service = new Intent(mContext, BinderPoolService.class);
            conn = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    mBinderPool = IBinderPool.Stub.asInterface(service);
                    Log.e(TAG, "mBinderPool = " + mBinderPool);

                    try {
                        Log.e(TAG, "为Binder对象设置死亡代理");
                        mBinderPool.asBinder().linkToDeath(mBinderDeathRecipient, 1);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }

                    mCountDownLatch.countDown();//3. go!
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {
                }
            };
            mContext.bindService(service, conn, Context.BIND_AUTO_CREATE);

            try {
                mCountDownLatch.await();//2.准备:所有线程准备
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            Log.e(TAG, "bind Pool Service!");
        } else {
            Log.e(TAG, "have bind Pool Service!");
        }
    }

    //死亡代理
    private IBinder.DeathRecipient mBinderDeathRecipient = new IBinder.DeathRecipient(){

        @Override
        public void binderDied() {
            if (null == mBinderPool){
                return;
            }
            //清除死亡代理标志
            mBinderPool.asBinder().unlinkToDeath(mBinderDeathRecipient, 1);
            mBinderPool = null;
            conn = null;
            bindPoolService();
        }
    };

    //获取Binder
    public IBinder queryBinder(int binderCode){
        IBinder binder = null;
        try {
            if (null != mBinderPool){
                binder = mBinderPool.queryBinder(binderCode);
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return binder;
    }


    //for server 
    public static class BinderPoolImpl extends IBinderPool.Stub {//Stub内部类,其实就是一个Binder类
        BinderPoolImpl(){
            super();
        }

        @Override
        public IBinder queryBinder(int binderCode) throws RemoteException {
            Binder binder = null;
            switch (binderCode){
                case BIND_PAY://大小写转换:Ctrl + Shift + U
                    binder = new PayImpl();//PayImpl继承了IPay.Stub, IPay.Stub继承了Binder
                    break;
                case BIND_SECURITY:
                    binder = new SecurityImpl();
                    break;
            }
            return binder;
        }
    }
}

Binder连接池的静态内部类BinderPoolImpl,用于服务端,继承了IBinderPool.Stub,并实现了queryBinder方法,即通过不同的binerCode获取不同业务模块对应的Binder。

其余部分都用于客户端。通过单例模式获取BinderPool实例后,绑定服务,同时为服务设置死亡代理,同时提供queryBinder方法,用于调用服务端的queryBinder方法,获取Binder。

5. 服务端的实现

public class BinderPoolService extends Service {
    private static final String TAG = "BinderPoolService lyl123";

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        return new BinderPool.BinderPoolImpl();
    }
}

Binder连接池中第40行的mBinderPool,即为服务端onBind方法中返回的new BinderPool.BinderPoolImpl()

mBinderPool = IBinderPool.Stub.asInterface(service);

6. 客户端的实现

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity lyl123";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread(new Runnable() {
            @Override
            public void run() {
                work();
            }
        }).start();
    }

    private void work() {
        Log.e(TAG, "work");
        BinderPool binderPool = BinderPool.getInstance(MainActivity.this);
        Log.e(TAG, "binderPool = " + binderPool);

        IBinder binder = binderPool.queryBinder(BinderPool.BIND_SECURITY);//获取Binder后使用
        //将服务端的Binder对象转换成客户端所需的AIDL类型的的对象
        ISecurity iSecurity = SecurityImpl.asInterface(binder);//ISecurity.Stub.asInterface
        Log.e(TAG, "binder = " + binder + ", iSecurity = " + iSecurity);
        try {
            String encode = iSecurity.encode("password");
            String decode = iSecurity.decode(encode);
            Log.e(TAG, "decode = " + decode);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        binder = binderPool.queryBinder(BinderPool.BIND_PAY);
        IPay iPay = PayImpl.asInterface(binder);
        Log.e(TAG, "binder = " + binder + ", iPay = " + iPay);
        try {
            iPay.buy();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

Binder连接池中,通过CountDownLatch将bindService这一异步操作转换成了同步操作,这就意味着它有可能是耗时的,同时Binder方法的调用也可能是耗时的,因此,在子线程中执行。

7. 清单文件

8. 参考

《Android开发艺术探索》

CountDownLatch的简单理解

你可能感兴趣的:(android)