AIDL灵活运用,避免创建多个Service

    前面转载了一篇AIDL的入门文章,从那时开始接触的AIDL。

 AIDL的使用一般是一个客户端,一个服务端。服务端返回一个AIDL接口,客户端拿到该接口调用方法。

但是,如果项目中有大量的AIDL文件,那么就要建相应个数的Service,这显然是不合理,现在介绍一种方法,优化AIDL的使用。先帖服务端的目录结构图


MainActivity是默认的,没添加任何代码,直接忽略。首先先看三个AIDL文件,都是很简单的。

ICompute.aidl文件代码为:

interface ICompute {
   int add(int a,int b);
}
,只定义了一个方法。

ISecurityCenter.aidl文件代码:

interface ISecurityCenter {
   String encrypt(String content);
   String decrypt(String password);
}
,定义两个方法,加密跟解密

IBinderPool.aidl文件代码为:

interface IBinderPool {
  IBinder queryBinder(int binderCode);
}
,这个是本次博客的重点,通过该接口来达到需要的结果。 服务端返回这个接口给客服端,客服端需要的其他任何接口都是通过调用IBinderPool接口的queryBinder方法返回的。

然后再看三个JAVA类的代码

public class ComputeImpl extends ICompute.Stub {
    @Override
    public int add(int a, int b) throws RemoteException {
        return a+b;
    }
}
   是AIDL文件ICompute的实现类;

public class SecurityCenterImpl extends 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);
    }
}
       是AIDL文件ISecurityCenter的实现类,这两个类的作用就是实现接口中的方法,以便于客户端调用。BinderPoolService类则是唯一的Service类,客户端就是通过与该Service类绑定从而得到的IBinderPool接口。通过调用IBinderPool这个接口中的queryBinder方法,达到根据传入不同的code得到不同的AIDL接口。

BinderService.java代码:

public class BinderPoolService extends Service {
    public static final int BINDER_COMPUTE = 0;
    public static final int BINDER_SECURITY_CENTER = 1;

    private static final String TAG="BinderPoolService";
    private Binder mBinderPool = new IBinderPool.Stub() {
        @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;
                default:
                    break;
            }
            return binder;
        }
    };

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

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

这个Service类也很简单,首先是实现IBinderPool接口,并实现其中的queryBinder方法,方法中根据不同的binderCode生成不同的AIDL接口,并返回。Service主要是在OnBind方法中IBinderPool接口返回。到此,服务端就完成了,再来看看客服端的代码,也很简单,首先目录结构。写代码前首先把服务端的AIDL文件夹整个拷贝过来。然后看看BinderPool的代码:

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;

    public Context mContext;
    private IBinderPool mBinderPool;
    private static volatile BinderPool sInstance;
    private CountDownLatch mConnectBinderPoolCountDownLatch;

    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() {
        mConnectBinderPoolCountDownLatch = new CountDownLatch(1);

        Intent intent = new Intent();
        intent.setAction("com.lypeer.aidl1");
        intent.setPackage("com.example.administrator.aidlserviceone");
        mContext.bindService(intent, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
        try {
            mConnectBinderPoolCountDownLatch.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) {

            Log.i("--->","连接成功");
            mBinderPool = IBinderPool.Stub.asInterface(service);
            try {
                mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            mConnectBinderPoolCountDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("--->","连接失败");
        }
    };


    private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
            mBinderPool = null;
            connectBinderPoolService();
        }
    };
}
这个相当于工具类,负责绑定服务端的Service,以及获取其他的AIDL接口。

MainActivity.java代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        doWork();
                    }
                }).start();
            }
        });
    }

    private void doWork(){
        BinderPool binderPool=BinderPool.getInstance(MainActivity.this);
        IBinder securityBinder=binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
        ISecurityCenter mSecurityCenter= ISecurityCenter.Stub.asInterface(securityBinder);

        String msg="helloword-安卓";
        try {
            String password=mSecurityCenter.encrypt(msg);
            Log.i("---->",password);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        IBinder computeBinder=binderPool.queryBinder(BinderPool.BINDER_COMPUTE);
        ICompute mCompute=ICompute.Stub.asInterface(computeBinder);

        try {
            Log.i("3+5--->",""+ mCompute.add(3,5));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}
主要是执行work方法。

  好了,运行起来看一看吧。如果要添加AIDL问价,只需要在服务端的Service里queryBinder方法中添加一个bindercode,当然还有一点比较重要,就是服务端和客户端要约定好不同的AIDL文件对应不同的一个bindercode,而且两端的bindercode要一致,才能保证一一对应。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值