四大元件之Service_AIDL

嶽小川發表於2019-03-04

四大元件之Service_AIDL

[文章內容來自Developers]

AIDL(Android 介面定義語言)與您可能使用過的其他 IDL 類似。 您可以利用它定義客戶端與服務使用程式間通訊 (IPC) 進行相互通訊時都認可的程式設計介面。 在 Android 上,一個程式通常無法訪問另一個程式的記憶體。 儘管如此,程式需要將其物件分解成作業系統能夠識別的原語,並將物件編組成跨越邊界的物件。 編寫執行這一編組操作的程式碼是一項繁瑣的工作,因此 Android 會使用 AIDL 來處理。

:只有允許不同應用的客戶端用 IPC 方式訪問服務,並且想要在服務中處理多執行緒時,才有必要使用 AIDL。 如果您不需要執行跨越不同應用的併發 IPC,就應該通過實現一個 Binder建立介面;或者,如果您想執行 IPC,但根本不需要處理多執行緒,則使用 Messenger 類來實現介面。無論如何,在實現 AIDL 之前,請您務必理解繫結服務

在您開始設計 AIDL 介面之前,要注意 AIDL 介面的呼叫是直接函式呼叫。 您不應該假設發生呼叫的執行緒。 視呼叫來自本地程式還是遠端程式中的執行緒,實際情況會有所差異。 具體而言:

  • 來自本地程式的呼叫在發起呼叫的同一執行緒內執行。如果該執行緒是您的主 UI 執行緒,則該執行緒繼續在 AIDL 介面中執行。 如果該執行緒是其他執行緒,則其便是在服務中執行您的程式碼的執行緒。 因此,只有在本地執行緒訪問服務時,您才能完全控制哪些執行緒在服務中執行(但如果真是這種情況,您根本不應該使用 AIDL,而是應該通過實現 Binder 類建立介面)。
  • 來自遠端程式的呼叫分派自平臺在您的自有程式內部維護的執行緒池。 您必須為來自未知執行緒的多次併發傳入呼叫做好準備。 換言之,AIDL 介面的實現必須是完全執行緒安全實現。
  • oneway關鍵字用於修改遠端呼叫的行為。使用該關鍵字時,遠端呼叫不會阻塞;它只是傳送事務資料並立即返回。介面的實現最終接收此呼叫時,是以正常遠端呼叫形式將其作為來自 Binder
    執行緒池的常規呼叫進行接收。 如果 oneway
    用於本地呼叫,則不會有任何影響,呼叫仍是同步呼叫。

定義 AIDL 介面


您必須使用 Java 程式語言語法在 .aidl檔案中定義 AIDL 介面,然後將它儲存在託管服務的應用以及任何其他繫結到服務的應用的原始碼(src/目錄)內。
您開發每個包含 .aidl檔案的應用時,Android SDK 工具都會生成一個基於該 .aidl檔案的 IBinder介面,並將其儲存在專案的 gen/目錄中。服務必須視情況實現 IBinder介面。然後客戶端應用便可繫結到該服務,並呼叫 IBinder中的方法來執行 IPC。
如需使用 AIDL 建立繫結服務,請執行以下步驟:

  • 建立 .aidl 檔案
    此檔案定義帶有方法簽名的程式設計介面。
  • 實現介面
    Android SDK 工具基於您的 .aidl檔案,使用 Java 程式語言生成一個介面。此介面具有一個名為 Stub 的內部抽象類,用於擴充套件 Binder類並實現 AIDL 介面中的方法。您必須擴充套件 Stub類並實現方法。
  • 向客戶端公開該介面
    實現 Service並重寫 onBind()以返回 Stub類的實現。

注意:在 AIDL 介面首次釋出後對其進行的任何更改都必須保持向後相容性,以避免中斷其他應用對您的服務的使用。 也就是說,因為必須將您的 .aidl檔案複製到其他應用,才能讓這些應用訪問您的服務的介面,因此您必須保留對原始介面的支援。

1. 建立 .aidl 檔案
AIDL 使用簡單語法,使您能通過可帶引數和返回值的一個或多個方法來宣告介面。 引數和返回值可以是任意型別,甚至可以是其他 AIDL 生成的介面。
您必須使用 Java 程式語言構建 .aidl檔案。每個 .aidl檔案都必須定義單個介面,並且只需包含介面宣告和方法簽名。
預設情況下,AIDL 支援下列資料型別:

  • Java 程式語言中的所有原語型別(如 int、long、char、boolean等等)
  • String
  • CharSequence
  • List
    List中的所有元素都必須是以上列表中支援的資料型別、其他 AIDL 生成的介面或您宣告的可打包型別。 可選擇將 List 用作“通用”類(例如,List)。另一端實際接收的具體類始終是 ArrayList,但生成的方法使用的是 List介面。
  • Map
    Map中的所有元素都必須是以上列表中支援的資料型別、其他 AIDL 生成的介面或您宣告的可打包型別。 不支援通用 Map(如Map<string,integer>形式的 Map)。 另一端實際接收的具體類始終是 HashMap,但生成的方法使用的是 Map 介面。

相關文章