一個AIDL簡單的例項
一. 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通訊),過程結束