aidl通信进阶,使用binder连接池

背景是这样的,我们使用aidl时候,如果只有一个远程服务,如上篇介绍aidl的文章中的王者荣耀使用阿里支付宝支付,支付成功了就ok了

但现在王者荣耀是腾讯的,必须支持微信支付。实际上我们做一个产品涉及支付的时候,支付宝,微信支付都是标配。

再类似扩展开来,如果我们的产品涉及很多远程服务,那是否每个远程服务都要新建呢?显然得综合管理。

因此我们把所有的远程服务抽象出来,之前的对外暴露的具体的服务换为连接池服务。

我们首先建立这个连接池服务aidl文件

package yunnex.com.testalipay;
interface IBinderPoolService
{
    IBinder queryBinder(int binderId);
}

根据该服务,客户端可以根据需求调度不同的服务,为简单起见,服务端设定binderId=1时,返回支付宝服务,binderId=2时,返回微信支付服务。

然后我们建立唯一对客户端的远程服务BinderPoolService

public class BinderPoolService extends Service
{
   //连接池管理的aidl对象
   private IAlipayService mAlipayService;
   private IWxService     mWxService;

   private Binder mBinderPool = new IBinderPoolService.Stub()
   {

      @Override
      public IBinder queryBinder(int binderId) throws RemoteException
      {
         IBinder binder=null;

         switch (binderId)
         {
            case 1:
               if (mAlipayService == null)
               {
                  mAlipayService = new AlipayServiceImpl();
               }
               binder = (IBinder) mAlipayService;
               break;
            case 2:
               if (mWxService == null)
               {
                  mWxService = new WxServiceImpl();
               }
               binder = (IBinder) mWxService;
               break;
         }

         Log.e("binderPool", "server BinderPoolService queryBinder:" + binder);
         return binder;
      }
   };

   @Override
   public IBinder onBind(Intent intent)
   {
      return mBinderPool;
   }
}

两个支付接口实现类分别如下:

public class AlipayServiceImpl extends IAlipayService.Stub
{
   private int mMoney;

   @Override
   public boolean payMoney(int money) throws RemoteException
   {
      mMoney = money;
      return money > 0;
   }

   @Override
   public Diamond getDiamond() throws RemoteException
   {
      return new Diamond(mMoney * 10);
   }
}

public class WxServiceImpl extends IWxService.Stub
{
   private int mMoney;

   @Override
   public boolean payMoney(int money) throws RemoteException
   {
      mMoney = money;
      return money > 0;
   }

   @Override
   public Diamond getDiamond() throws RemoteException
   {
      return new Diamond(mMoney * 10);
   }
}

这样服务端就完成了。

客户端调用(记得拷贝生成的文件):

bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

当绑定时,此时连接后的回调返回的就不再是具体的服务了,而是连接池服务。

ServiceConnection mConnection = new ServiceConnection()
{
   @Override
   public void onServiceConnected(ComponentName name, IBinder service)
   {
      mBinderPool = IBinderPoolService.Stub.asInterface(service);
   }

   @Override
   public void onServiceDisconnected(ComponentName name)
   {
      mBinderPool = null;
   }
};

public void payWithPool(View view)
{
   try
   {
      int bindCode = 2;
      IBinder binder = mBinderPool.queryBinder(bindCode);
      Log.e(TAG, "client payWithPool binder:" + binder);
      switch (bindCode)
      {
         case 1:
            //Caused by: java.lang.ClassCastException:
            //android.os.BinderProxy cannot be cast to
            //yunnex.com.testalipay.IAlipayService
            //((IAlipayService) binder).payMoney(108);
            IAlipayService alipayService = IAlipayService.Stub.asInterface(binder);
            Log.e(TAG, "client payWithPool Service:" + alipayService);
            int money = 102;
            boolean b = alipayService.payMoney(money);
            if (b)
            {
               Toast.makeText(MainActivity.this, "使用支付宝支付成功" + money + ",得到钻石:" + alipayService.getDiamond().getNum() + "", Toast.LENGTH_SHORT).show();
            }
            else
            {
               Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
            }
            break;

         case 2:
            IWxService wxService = IWxService.Stub.asInterface(binder);
            Log.e(TAG, "client payWithPool Service:" + wxService);
            int money2 = 103;
            boolean b2 = wxService.payMoney(money2);
            if (b2)
            {
               Toast.makeText(MainActivity.this, "使用微信支付成功" + money2 + ",得到钻石:" + wxService.getDiamond().getNum() + "", Toast.LENGTH_SHORT).show();
            }
            else
            {
               Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
            }
            break;
      }

   }
   catch (RemoteException e)
   {
      e.printStackTrace();
   }
}

这样支付宝支付和微信支付就使用连接池完成了。

当后续再出现xxx支付时或者什么远程服务时,不需再为其提供一个service组件,只需配置好aidl文件,实现接口,在连接池中加入case分支即可。




你可能感兴趣的:(IPC)