网上相当多关于android利用AIDL实现进程间通信文章,基本上都是activity去bind一个service,然后调用客户端,也就是activity这边调用服务端的方法。但我心里一直有个疑问,这种模式是单向的,如何实现AIDL的双向通信?于是跑了下面的Demo。
大致原理是两个Service,Service1和Service2,Service1bind好Service2后,拿到Service2的Binder对象,在本地转成AIDL对象,然后通过这个AIDL对象再传递一个AIDL对象到Serivce2,传过来的这个AIDL的“根”Stub,就是接口的实现,是在Service1这边,这样Service2通过接口可以调用Service1的方法。
下面是代码:
两个AIDL接口的定义:
// IMyAidlInterface.aidl
package com.acxingyun.servicecomunication;
import com.acxingyun.servicecomunication.IRegistAidl;
// Declare any non-default types here with import statements
//传递AIDL接口到对端,需要在文件开始import这个AIDL文件
interface IMyAidlInterface {
void registAidl(IRegistAidl aidl);
}
// IRegistAidl.aidl
package com.acxingyun.servicecomunication;
// Declare any non-default types here with import statements
interface IRegistAidl {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void func();
}
Service1:
public class MyService1 extends Service {
private String TAG = getClass().getSimpleName();
//Service2 AIDL在本地的接口对象
private IMyAidlInterface service2AIDL = null;
//本地AIDL接口根对象
private IRegistAidl service1AIDLStub = new IRegistAidl.Stub() {
@Override
public void func() throws RemoteException {
Log.i(TAG, "service1AIDLStub func...");
}
};
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected");
service2AIDL = IMyAidlInterface.Stub.asInterface(service);
try {
//传递本地AIDL根对象到Service2
service2AIDL.registAidl(service1AIDLStub);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
public MyService1() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
Log.i(TAG, "onCreate...");
super.onCreate();
Intent intent = new Intent(getApplicationContext(), MyService2.class);
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
Service2:
public class MyService2 extends Service {
//Serivce1 AIDL在本地的接口对象
IRegistAidl service1AIDL = null;
private String TAG = getClass().getSimpleName();
//本地AIDL根对象
private IBinder service2AIDLStub = new IMyAidlInterface.Stub() {
@Override
public void registAidl(IRegistAidl aidl) throws RemoteException {
Log.i(TAG, "registAidl");
//接收Service1的AIDL对象
service1AIDL = aidl;
test();
}
};
public MyService2() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return service2AIDLStub;
}
public void test(){
Log.i(TAG, "test...");
try {
//通过Serivice1 AIDL在本地的对象调用Service1方法,实现双向通信
service1AIDL.func();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onCreate() {
Log.i(TAG, "oncreate...");
super.onCreate();
}
}
结果:
01-18 10:30:51.141 16626-16626/com.acxingyun.servicecomunication I/MyService1: onCreate...
01-18 10:30:51.144 16626-16626/com.acxingyun.servicecomunication I/MyService2: oncreate...
01-18 10:30:51.147 16626-16626/com.acxingyun.servicecomunication I/MyService1: onServiceConnected
01-18 10:30:51.147 16626-16626/com.acxingyun.servicecomunication I/MyService2: registAidl
01-18 10:30:51.147 16626-16626/com.acxingyun.servicecomunication I/MyService2: test...
01-18 10:30:51.147 16626-16626/com.acxingyun.servicecomunication I/MyService1: service1AIDLStub func...
两个Serivce,两个AIDL,每个Serice有个AIDL的根对象和另一个AIDL的接口对象,需要注意的是,Service2要返回一个IBinder类型的对象,所以Service2这边要把AIDL接口类型写为IBinder:
private IBinder service2AIDLStub = new IMyAidlInterface.Stub() {
@Override
public void registAidl(IRegistAidl aidl) throws RemoteException {
Log.i(TAG, "registAidl");
service1AIDL = aidl;
test();
}
};
不同进程间的双向通信类似。