AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。官方文档特别提醒我们何时使用AIDL是必要的:只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。
3. 抛出的异常是不能返回给调用者(跨进程抛异常处理是不可取的)。
工作中用到了一个service为多个app提供服务的情况,每个app都有自己的aidl定义,这里用简单的demo展示aidl的调用过程
首先看app1,app1定义了一套详细的aidl,service需要根据aidl完成接口。app1的aidl
interface AidlDcService{
/** 获取串口测试操作实例 */
IBinder getDcSystem();
}
import com.dc.pos.aidl.CommTestObserver;
//系统设备
interface AidlDcSystem{
//结束测试
void endCommTest();
//开始测试
void startCommTest(int type,CommTestObserver observer);
}
interface CommTestObserver{
//成功
void onTestFinished();
//错误
void onTestError(int errorCode);
}
三个aidl文件已经创建完毕,在app和service端均要保证报名和文件的一致。
app1的activity1和app2的activity2里面在onResume里面绑定不同的服务,activity1绑定DcSetvice,activity2绑定DeviceService;两者仅仅是setAction不同。
//绑定服务
public void bindService(){
Intent intent = new Intent();
intent.setAction(DC_SERVICE_ACTION);
boolean flag = bindService(intent, conn, Context.BIND_AUTO_CREATE);
if(flag){
Debug.d(LOG_TAG, "服务绑定成功");
}else{
Debug.d(LOG_TAG, "服务绑定失败");
}
}
这里没用直接使用service的class作为绑定参数,而是以setAction的方式。在service里可以针对不同的action绑定不同的服务
<service android:name=".DeviceService" >
<intent-filter>
<action android:name="lkl_cloudpos_device_service" />
</intent-filter>
</service>
<service android:name=".DcService" >
<intent-filter>
<action android:name="dc_pos_device_service" />
</intent-filter>
</service>
activict1里面完成绑定结果的监听
private ServiceConnection conn = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder serviceBinder) {
Debug.d(LOG_TAG, "AidlService服务连接成功");
if(serviceBinder != null){ //绑定成功
AidlDcService serviceManager = AidlDcService.Stub.asInterface(serviceBinder);
onDeviceConnected(serviceManager);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Debug.d(LOG_TAG, "AidlService服务断开");
}
};
同样的activity2里面也是如此
//设别服务连接桥
private ServiceConnection conn = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder serviceBinder) {
Debug.d("aidlService服务连接成功");
if(serviceBinder != null){ //绑定成功
AidlDeviceService serviceManager = AidlDeviceService.Stub.asInterface(serviceBinder);
onDeviceConnected(serviceManager);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Debug.d("AidlService服务断开了");
}
};
在这里调用了onDeviceConnected创建对应的AidlDcSystem对象systemInf
public void onDeviceConnected(AidlDcService serviceManager) {
try {
systemInf = AidlDcSystem.Stub.asInterface(serviceManager
.getDcSystem());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
AidlDcSystem对象创建好之后,就可以通过systemInf调用AidlDcSystem.aidl中定义的接口文件。
同样在activiry2中调用了onDeviceConnected创建对应的AidlSystem对象isys
通过isys调用AidlDeviceService.aidl中定义的接口文件。
下面再来看service中的实现
首先创建两个service,分别针对app1和app2的绑定
这里贴出DcService
public class DcService extends Service {
public static final boolean needAuthorize = false;
private final static String TAG = "DcService";
private final static int CMD_INIT_OK = 0;
private final static int CMD_INIT_FAIL = 1;
private Context context;
private IDevice dcpos = null;
private CommTestImpl commTestImpl = new CommTestImpl(this);
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case CMD_INIT_OK:
DeviceInstance.setInstance(dcpos);
break;
case CMD_INIT_FAIL:
DeviceInstance.setInstance(null);
Toast.makeText(DcService.this, "init SDK Fail", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
super.handleMessage(msg);
}
};
@Override
public void onCreate() {
// TODO Auto-generated method stub
// acquireWakeLock();
initSdk();
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
flags = START_STICKY;
return super.onStartCommand(intent, flags, startId);
}
private void initSdk() {
//这里是绑定后的进一步操作,和本文无关,隐去
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
Debug.e(TAG, "onBind()");
return new AidlDcServiceImpl();
}
/*
* (non-Javadoc)
*
* @see android.app.Service#onUnbind(android.content.Intent)
*/
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Debug.e(TAG, "onUnbind()");
return super.onUnbind(intent);
}
private class AidlDcServiceImpl extends AidlDcService.Stub {
@Override
public IBinder getDcSystem() throws RemoteException {
// TODO Auto-generated method stub
return commTestImpl;
}
}
}
DcService在绑定时通过new AidlDcServiceImpl()创建对象返回给绑定的app1的activity1,这时activity1就可以根据此对象来调用相应的接口完成需要的功能。
同样的app2也可以绑定相应的DeviceService。
这样一个后台服务就可以通过不同的aidl与不同的app绑定。对于app来说互相之间是完全屏蔽的。
aidl中使用java类,需要实现Parcelable接口,并且在定义类相同包下面对类进行声明,此问题将在下一篇中讲述