一. AIDL是快速实现binder,实现跨进程通信的工具
AIDL:Android Interface Definition Language,安卓接口描述语言
二. 实现一个简单的AIDL通信示例
前提:IPersonManager类用于客户端(由PersonManager.aidl自动生成),PersonManagerService类用于服务端
- 实现一个PersonManager.aidl,定义所需的接口和方法,例如:
import com.kevin.test.testAIDL.Person;
interface IPersonManager {
String getName();
int getAge();
void print();
void changeName(in Person person);
}
注意:Person类是自定义类,需实现Parcel接口,并实现相关方法
-
开发工具,如Android Studio,会根据AIDL文件,自动帮我们实现IPersonManager.java类,继承自android.os.IInterface。其中有一个内部静态类Stub,Stub类有2个重要方法asInterface,onTransact和一个内部静态类Proxy。以下是它们的关系:
- asInterface方法:将服务端的Binder对象转换为客户端所需的AIDL接口类型的对象。区分进程,如果二者在同一进程,返回服务端的Stub对象本身,如果跨进程,返回Stub.Proxy对象
- onTransact方法运行在服务端的binder线程池中
- 跨进程通信,会在Stub.Proxy中走transact过程,例如getName的核心实现是
mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
-
实现一个PersonManagerService.java类,作为服务端,其中重要的是定义一个类成员变量Binder mBinder = new IPersonManager.Stub() {......},这是一个Stub类对象,其中真正实现各个调用的方法,如getName()等
-
客户端在使用时调用bindService接口,此时会传入一个ServiceConncetion对象,如bind成功,ServiceConncetion#onServiceConnected方法会被回调,在其中可将服务端返回的IBinder对象利用asInterface方法进行转换,如:
IPersonManager personManager = IPersonManager.Stub.asInterface(iBinder);
三. 设置死亡代理
当服务端Service运行时出现异常,例如抛出DeadObjectException异常,进程终止等,这时已连接的客户端,如何接到通知,并进行一系列操作,如重新bindService等。这里用到Binder的死亡代理,分为2步:
- 客户端新建一个IBinder.DeathRecipient成员变量
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (null == mPersonManager)
return;
// unlink binder death recipient
mPersonManager.asBinder().unlinkToDeath(mDeathRecipient, 0);
// reconnect
bindService(...);
}
};
- 注册代理
public ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mPersonManager = IPersonManager.Stub.asInterface(iBinder);
try {
// link binder death recipient
mPersonManager.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
// ...
}
}
当服务端进程中止时,IBinder.DeathRecipient#binderDied方法会被回调
四. bindService的实现过程:
- Activity(基类是Context,其中方法真正实现在ContextImpl中)中调用bindService
- ContextImpl#bindServiceCommon中,利用binder通信,调用ActivityManager#bindService方法
- System_server进程中ActivityManagerService#bindService -> ActiveServices#bindServiceLocked方法,其中会检查权限,启动目标Service等,然后回调客户端ServiceConnection#onServiceConncetd方法(one-way通信),过程结束
网友评论