一. AIDL是快速實現(xiàn)binder,實現(xiàn)跨進程通信的工具
AIDL:Android Interface Definition Language,安卓接口描述語言
二. 實現(xiàn)一個簡單的AIDL通信示例
前提:IPersonManager類用于客戶端(由PersonManager.aidl自動生成),PersonManagerService類用于服務端
- 實現(xiàn)一個PersonManager.aidl,定義所需的接口和方法,例如:
import com.kevin.test.testAIDL.Person;
interface IPersonManager {
String getName();
int getAge();
void print();
void changeName(in Person person);
}
注意:Person類是自定義類,需實現(xiàn)Parcel接口,并實現(xiàn)相關方法
-
開發(fā)工具,如Android Studio,會根據(jù)AIDL文件,自動幫我們實現(xiàn)IPersonManager.java類,繼承自android.os.IInterface。其中有一個內(nèi)部靜態(tài)類Stub,Stub類有2個重要方法asInterface,onTransact和一個內(nèi)部靜態(tài)類Proxy。以下是它們的關系:
- asInterface方法:將服務端的Binder對象轉(zhuǎn)換為客戶端所需的AIDL接口類型的對象。區(qū)分進程,如果二者在同一進程,返回服務端的Stub對象本身,如果跨進程,返回Stub.Proxy對象
- onTransact方法運行在服務端的binder線程池中
- 跨進程通信,會在Stub.Proxy中走transact過程,例如getName的核心實現(xiàn)是
mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
實現(xiàn)一個PersonManagerService.java類,作為服務端,其中重要的是定義一個類成員變量Binder mBinder = new IPersonManager.Stub() {......},這是一個Stub類對象,其中真正實現(xiàn)各個調(diào)用的方法,如getName()等
客戶端在使用時調(diào)用bindService接口,此時會傳入一個ServiceConncetion對象,如bind成功,ServiceConncetion#onServiceConnected方法會被回調(diào),在其中可將服務端返回的IBinder對象利用asInterface方法進行轉(zhuǎn)換,如:
IPersonManager personManager = IPersonManager.Stub.asInterface(iBinder);
三. 設置死亡代理
當服務端Service運行時出現(xiàn)異常,例如拋出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方法會被回調(diào)
四. bindService的實現(xiàn)過程:
- Activity(基類是Context,其中方法真正實現(xiàn)在ContextImpl中)中調(diào)用bindService
- ContextImpl#bindServiceCommon中,利用binder通信,調(diào)用ActivityManager#bindService方法
- System_server進程中ActivityManagerService#bindService -> ActiveServices#bindServiceLocked方法,其中會檢查權(quán)限,啟動目標Service等,然后回調(diào)客戶端ServiceConnection#onServiceConncetd方法(one-way通信),過程結(jié)束
作者:kevin song,2018.11.11于南京建鄴區(qū)