您的位置:首页 > 大数据 > 人工智能

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

2017-10-12 11:44 183 查看
    前面转载了一篇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 Strin
4000
g(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要一致,才能保证一一对应。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: