日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > ChatGpt >内容正文

ChatGpt

两种AIDL用法分析(原)

發布時間:2025/3/15 ChatGpt 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 两种AIDL用法分析(原) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? ? 我們在前面介紹了關于AIDL的兩種用法,第一種用法主要用在應用層中( 應用層的AIDL調用 ),第二種用法主要用在framework中( Framework中的AIDL調用 )。但是這兩種用法中都提到了Stub、asInterface等關鍵字,在這一節中我們主要針對AIDL內部機制的分析來深入理解AIDL調用的過程。
? ? ? ? 為了便于分析,我們還拿第一節中我們自己搭建的例子去分析。
? ? ? ? 當時我們在Eclipse Android工程的Java包目錄中建立了一個擴展名為aidl的文件(IMyService.aidl),并寫下需要的接口。Eclipse會在gen目錄下生成一個IMyService.Java的文件。

一、整體結構

? ? ? ? 我們打開IMyService.Java文件查看,發現他的結構是這樣的:

[java]?view plaincopy
  • public?interface?IMyService?extends?android.os.IInterface?{??
  • ????//可以看出,Stub其實是一個實現了IMyService的Binder抽象類。??
  • ????public?static?abstract?class?Stub?extends?android.os.Binder?implements?aidl.pac.IMyService?{??
  • ????????public?Stub()?{??
  • ????????}??
  • ????????//把遠程Service的Binder對象傳遞進去,得到的是遠程服務的本地代理??
  • ????????public?static?aidl.pac.IMyService?asInterface(android.os.IBinder?obj)?{??
  • ????????}??
  • ????????public?android.os.IBinder?asBinder()?{??
  • ????????}??
  • ????????//兩個不同進程之間傳遞是通過onTransact接口完成的??
  • ????????public?boolean?onTransact(int?code,?android.os.Parcel?data,????android.os.Parcel?reply,?int?flags)??
  • ????????????????throws?android.os.RemoteException?{??
  • ????????}??
  • ????????//遠程服務的本地代理,當然也會繼承自IMyService??
  • ????????private?static?class?Proxy?implements?aidl.pac.IMyService?{??
  • ????????????private?android.os.IBinder?mRemote;??
  • ????????????//構造函數??
  • ????????????Proxy(android.os.IBinder?remote)?{??
  • ????????????}??
  • ????????????public?android.os.IBinder?asBinder()?{??
  • ????????????}??
  • ????????????public?java.lang.String?getInterfaceDescriptor()?{??
  • ????????????}??
  • ????????????//調用的getValue其實就是這里。??
  • ????????????public?java.lang.String?getValue()??
  • ????????????????????throws?android.os.RemoteException?{??
  • ????????}??
  • ????????//可以看到,系統將我們的方法轉換成以FIRST_CALL_TRANSACTION為基準的數字。??
  • ????????static?final?int?TRANSACTION_getValue?=?(android.os.IBinder.FIRST_CALL_TRANSACTION?+?0);??
  • ????}??
  • ????public?java.lang.String?getValue()?throws?android.os.RemoteException;??
  • }??
  • ? ? ? ? 下面是一個結構圖:? ? ? ? ? ? ? 整體上來看,IMyService.java文件中的IMyService類有一個Stub的內部類,還有一個getValue方法。這個方法就是我們在aidl中定義的方法。同時我們看到,生成的IMyService繼承自IInterface,說明這也是一個接口,并沒有對getValue進行實現。

    ? ? ? ? 對于getValue這個方法,當我們在服務端的內部類中繼承了IMyService.Stub抽象類以后,就需要對未曾實現的getValue方法進行定義。
    ? ? ? ? 再來看IMyService的內部類Stub。這個內部類是一個實現了IMyService接口的Binder抽象類。內部有3個方法asInterface、asBinder、onTransact,還有一個內部類Proxy。

    二、得到的遠端Service對象

    ? ? ? ? 現在我們來看一下客戶端當初得到的服務端對象的情況,當我們連接上服務端后,會被動調用onServiceConnected方法:

    [java]?view plaincopy
  • public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{??
  • ????mIMyService?=?IMyService.Stub.asInterface(service);??
  • }??
  • ? ? ? ? 在這里得到的service對象其實就是MyServiceImpl對象,他是實現了IMyService.Stub具體接口的IBinder。再來看一下asInterface:

    [java]?view plaincopy
  • public?static?aidl.pac.IMyService?asInterface(android.os.IBinder?obj)?{??
  • ????//通過asInterface得到的其實是遠程Service的本地“代理”,而代理對象的參數是遠程的服務端“obj”??
  • ????return?new?aidl.pac.IMyService.Stub.Proxy(obj);??
  • }??
  • ? ? ? ? 可以看出,onServiceConnected參數是遠程服務端的IBinder對象,返回值是IMyService.Stub.Proxy(obj),這里的Proxy是Stub的內部類:

    [java]?view plaincopy
  • private?static?class?Proxy?implements?aidl.pac.IMyService?{}??
  • ? ? ? ? 內部除了構造方法以外,只有getValue方法: [java]?view plaincopy
  • //調用的getValue其實就是這里。??
  • public?java.lang.String?getValue()????throws?android.os.RemoteException?{??
  • ????_data.writeInterfaceToken(DESCRIPTOR);??
  • ????//mRemote是遠程的服務對象的binder,通過transact與服務端交換數據??
  • ????mRemote.transact(Stub.TRANSACTION_getValue,?_data,?_reply,0);??
  • ????_reply.readException();??
  • ????_result?=?_reply.readString();??
  • ????return?_result;??
  • }??
  • ? ? ? ? 到這里我們看到,Proxy內部確實擁有服務端的各個方法,但 這些方法并不是真實的實現,而只是通過mRemote.transact傳輸出去

    ? ? ? ? 也就是說, 在客戶端通過mIMyService = IMyService.Stub.asInterface(service)得到的就是Proxy對象,可以通過這個對象間接的調用服務端的各個方法,而具體調用過程就是經過mRemote.transact傳輸給真正的Service(也就是MyService.MyServiceImpl類)
    ? ? ? ? 那么,具體來說,我們是如何通過這個代理對象調用到真實的getValue呢?

    三、如何通過代理對象調用遠端Service方法

    ? ? ? ? 在代理類的getValue方法中看到,他是調用了mRemote.transact的方法。

    ? ? ? ? 而mRemote.transact的方法通過底層的Binder通訊,將數據傳輸給服務端進程,并調用服務端的onTransact方法:

    [java]?view plaincopy
  • public?boolean?onTransact(int?code,?android.os.Parcel?data,????android.os.Parcel?reply,?int?flags){??
  • ????switch?(code)?{??
  • ????????//客戶端調用的getValue方法,最終由這里傳輸給服務端??
  • ????????case?TRANSACTION_getValue:?{??
  • ????????????data.enforceInterface(DESCRIPTOR);??
  • ????????????java.lang.String?_result?=?this.getValue();??
  • ????????????reply.writeNoException();??
  • ????????????reply.writeString(_result);??
  • ????????????return?true;??
  • ????????}??
  • ????}??
  • ????return?super.onTransact(code,?data,?reply,?flags);??
  • }??
  • ? ? ? ? 因為當初得到的遠程服務對象是MyServiceImpl的對象,因此這里的this就指向了MyServiceImpl類。 因此getValue方法就進入到了MyServiceImpl的內部,也就是遠程服務端的內部。由此完成了一次完整的調用過程。

    四、AIDL總結 ? ?

    ? ? ? ? 1、AIDL要是實現的最終目標是 跨進程訪問 ,簡單的說就是得到另一個進程的對象,并調用其方法。
    ? ? ? ? 2、AIDL與接口類似, 本質屬性都是一個Interface (AIDL文件是IInterface,而Interface是繼承自Interface的),而且都只定義了抽象方法,沒有具體的實現,需要子類去實現。
    ? ? ? ? 3、與接口不同的是: 由AIDL生成的stub類本質上是一個Binder !這個類所生成的對象有兩種方式可以傳遞給另外一個進程:
    ? ? ? ? ? ? ? ? 3.a、一種是通過bindService的方式,綁定一個服務,而在綁定后,服務將會返回給客戶端一個Binder的對象,此時可以把繼承自stub的Binder傳遞給客戶端。
    ? ? ? ? ? ? ? ? 3.b、另外一種就是把繼承自stub的類提升為系統服務,此時,我們通過ServiceManager去得到當前的系統服務,ServiceManager就會把目標Service的Binder對象傳遞給客戶端。

    ? ? ? ? 4、經過上面兩種方法得到的Binder對象,就像得到了本地的某個對象一樣,可以調用其遠程的方法。


    原文地址:?http://blog.csdn.net/u010961631/article/details/12082161

    總結

    以上是生活随笔為你收集整理的两种AIDL用法分析(原)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。