1. aidl實現(xiàn)流程概述
首先建立一個aidl接口和一個Service,接著實現(xiàn)一個類A繼承aidl接口中的Stub類并實現(xiàn)其中的方法,在Service綁定時返回類A的對象,然后客戶端就可以綁定服務(wù)端,建立連接后就可以訪問遠(yuǎn)程服務(wù)端的方法了。
2. 可能出現(xiàn)的問題及解決方式
公司項目越來越大,100個aidl,按照上面的思路,得100個Service。這顯然不可以,解決方式是binder 連接池。
整個工作機制是這樣的:每個業(yè)務(wù)模塊創(chuàng)建自己的aidl接口并實現(xiàn)此接口,這個時候不同業(yè)務(wù)模塊之間是不能有耦合的,然后向服務(wù)端提供自己的唯一標(biāo)識和其對應(yīng)的Binder對象;對于服務(wù)端來說,只需要一個Service,服務(wù)端提供一個queryBinder接口,這個接口能夠根據(jù)業(yè)務(wù)模塊特征來返回相應(yīng)的Binder對象給他們,不同的業(yè)務(wù)模塊拿到所需的Binder對象后就可以進(jìn)行遠(yuǎn)程方法調(diào)用了。
Binder連接池的主要作用就是將每個業(yè)務(wù)模塊的Binder請求同一轉(zhuǎn)發(fā)到遠(yuǎn)程Service中去,避免重復(fù)創(chuàng)建Service的過程。
3. 定義兩個業(yè)務(wù)aidl接口并實現(xiàn)
package qingfengmy.developmentofart._2activity.binderpool.aidl;
interface ICompute {
int add(int a, int b);
}
// ISecurityCenter.aidl
package qingfengmy.developmentofart._2activity.binderpool.aidl;
interface ISecurityCenter {
String encrypt(in String content);
String decrypt(in String password);
}
public class SecurityCenterImpl extends ISecurityCenter.Stub {
@Override
public String encrypt(String content) throws RemoteException {
char[] chars = content.toCharArray();
for (int i=0; i<chars.length;i++) {
chars[i] = (char) (chars[i]+1);
}
return new String(chars);
}
@Override
public String decrypt(String password) throws RemoteException {
char[] chars = password.toCharArray();
for (int i=0; i<chars.length;i++) {
chars[i] = (char) (chars[i]-1);
}
return new String(chars);
}
}
public class ComputerImpl extends ICompute.Stub {
@Override
public int add(int a, int b) throws RemoteException {
return a+b;
}
}
4. 定義BinderPool接口并實現(xiàn)
package qingfengmy.developmentofart._2activity.binderpool.aidl;
interface IBinderPool {
IBinder queryBinder(int binderCode);
}
public static class BinderPoolImpl extends IBinderPool.Stub{
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
switch (binderCode) {
case 0:
return new SecurityCenterImpl();
case 1:
return new ComputerImpl();
}
return null;
}
}
5. 服務(wù)實現(xiàn)
public class PoolService extends Service {
private Binder mBinderPool = new BinderPool.BinderPoolImpl();
public PoolService() {
}
@Override
public IBinder onBind(Intent intent) {
return mBinderPool;
}
}
6. BinderPool的實現(xiàn)
public class BinderPool {
// 定義BinderCode
private 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;
// volatile 用來修飾被不同線程訪問和修改的變量
private static volatile BinderPool sInstance;
/**
* CountDownLatch類是一個同步計數(shù)器,構(gòu)造時傳入int參數(shù),該參數(shù)就是計數(shù)器的初始值,每調(diào)用一次countDown()方法,計數(shù)器減1,計數(shù)器大于0 時,await()方法會阻塞程序繼續(xù)執(zhí)行
* CountDownLatch如其所寫,是一個倒計數(shù)的鎖存器,當(dāng)計數(shù)減至0時觸發(fā)特定的事件。利用這種特性,可以讓主線程等待子線程的結(jié)束。
*/
private CountDownLatch mConnectBinderPoolCountDownLatch;
private BinderPool(Context context) {
mContext = context.getApplicationContext();
connectBinderPoolService();
}
public static BinderPool getsInstance(Context context) {
if (sInstance == null) {
synchronized (BinderPool.class) {
if (sInstance == null) {
sInstance = new BinderPool(context);
}
}
}
return sInstance;
}
public IBinder queryBinder(int binderCode) {
try {
return mBinderPool.queryBinder(binderCode);
} catch (RemoteException e) {
e.printStackTrace();
}
return null;
}
private synchronized void connectBinderPoolService() {
// 只有一個線程有效
mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
Intent intent = new Intent(mContext, PoolService.class);
mContext.bindService(intent, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
// 等待,直到CountDownLatch中的線程數(shù)為0
mConnectBinderPoolCountDownLatch.await();
}
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPool = IBinderPool.Stub.asInterface(service);
mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
// 執(zhí)行一次countDown,其計數(shù)減一
mConnectBinderPoolCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
// 解除死亡綁定
mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
mBinderPool = null;
// 重連
connectBinderPoolService();
}
};
public static class BinderPoolImpl extends IBinderPool.Stub {
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
switch (binderCode) {
case BINDER_SECURITY_CENTER:
return new SecurityCenterImpl();
case BINDER_COMPUTE:
return new ComputerImpl();
}
return null;
}
}
}
7. Activity中調(diào)用
private void doWork() {
BinderPool binderPool = BinderPool.getsInstance(this);
IBinder computeBinder = binderPool.queryBinder(BinderPool.BINDER_COMPUTE);
ICompute compute = ComputerImpl.asInterface(computeBinder);
try {
int result = compute.add(1, 2);
Log.e("aaa", "1+2=" + result);
} catch (RemoteException e) {
e.printStackTrace();
}
IBinder securityCenterBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
ISecurityCenter iSecurityCenter = SecurityCenterImpl.asInterface(securityCenterBinder);
try {
String content = "i love this book";
Log.e("aaa","加密前:"+content);
content = iSecurityCenter.encrypt(content);
Log.e("aaa","加密后:"+content);
content = iSecurityCenter.decrypt(content);
Log.e("aaa","解密后:"+content);
} catch (RemoteException e) {
e.printStackTrace();
}
}
普通寫法
public void onServiceConnected(ComponentName name, IBinder service) {
iBookManager = IBookManager.Stub.asInterface(service);
}
可見使用BinderPool客戶端中的處理還是一樣,通過Stub的asInterface方法把IBinder轉(zhuǎn)為業(yè)務(wù)接口。
這樣有新業(yè)務(wù)aidl時,只需加aidl_code,并在queryBinder中增加返回的aidl即可。不需寫Servicce,所以如果使用aidl,必須推薦使用BinderPool模式。