一個AIDL的代碼實例

一. AIDL是快速實現(xiàn)binder,實現(xiàn)跨進程通信的工具

AIDL:Android Interface Definition Language,安卓接口描述語言


二. 實現(xiàn)一個簡單的AIDL通信示例

前提:IPersonManager類用于客戶端(由PersonManager.aidl自動生成),PersonManagerService類用于服務端

  1. 實現(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)相關方法

  1. 開發(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);
  2. 實現(xiàn)一個PersonManagerService.java類,作為服務端,其中重要的是定義一個類成員變量Binder mBinder = new IPersonManager.Stub() {......},這是一個Stub類對象,其中真正實現(xiàn)各個調(diào)用的方法,如getName()等

  3. 客戶端在使用時調(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步:

  1. 客戶端新建一個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(...);
        }
    };
  1. 注冊代理
    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)過程:
  1. Activity(基類是Context,其中方法真正實現(xiàn)在ContextImpl中)中調(diào)用bindService
  2. ContextImpl#bindServiceCommon中,利用binder通信,調(diào)用ActivityManager#bindService方法
  3. System_server進程中ActivityManagerService#bindService -> ActiveServices#bindServiceLocked方法,其中會檢查權(quán)限,啟動目標Service等,然后回調(diào)客戶端ServiceConnection#onServiceConncetd方法(one-way通信),過程結(jié)束



作者:kevin song,2018.11.11于南京建鄴區(qū)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容