SDK 執行階段的回溯相容性

本文件提議新的 Jetpack 程式庫,協助開發人員遷移至 SDK 執行階段。並說明 SDK 執行階段如何支援先前的 Android 平台版本 (從建構到執行),以及開發人員可以預期的環境環境差異或限制。這個程式庫可讓開發人員建立單一應用程式或 SDK 版本,並在無論是否支援 SDK 執行階段的裝置上執行。

可透過下列元件達成回溯相容性:

  • Android Gradle 外掛程式 (AGP) + Bundletool 會整合 SDK 執行階段至 APK,針對不支援 SDK 執行階段的裝置建構應用程式變化版本。

  • SDK 執行階段用戶端程式庫 (androidx.privacysandbox.sdkruntime:sdkruntime-client) 會從應用程式資產載入隨附的 SDK,並在不支援 SDK 執行階段的裝置中模擬 SDK 執行階段。

  • SDK 執行階段供應商程式庫 (androidx.privacysandbox.sdkruntime:sdkruntime-provider) 為 SDK 提供一個 API,允許從 SDK 執行階段用戶端程式庫載入。

透過 Bundletool 提交 SDK

在支援 SDK 執行階段的裝置中,系統會將 SDK 做為獨立的套件提供及安裝。

為了支援缺少 SDK 執行階段支援的平台版本,Bundletool 會建構一或多個應用程式 APK 組合變化版本,其中包含應用程式所需的所有 SDK。每個 SDK 都會封裝為獨立的 APK 分割視窗。此外,系統會執行以下轉換:

  1. 將 SDK 位元碼 (DEX) 檔案以素材資源的形式複製到 SDK 分割中。
  2. 將 SDK Java 資源以資產的形式複製到 SDK 分割中。
  3. 重新對應 SDK 資源,並與應用程式資源合併。
  4. 產生 SDK 執行階段用戶端程式庫的設定。

使用 SDK 執行階段用戶端程式庫載入 SDK

SDK 執行階段用戶端程式庫提供與平台 API 類似的 API,但支援 SDK 執行階段環境中的 SDK 以及與變化版本應用程式隨附的 SDK。

如要使用 SDK 執行階段用戶端程式庫,請新增依附元件 androidx.privacysandbox.sdkruntime:sdkruntime-client,並使用 SdkSandboxManagerCompat 而非 SdkSandboxManager

當應用程式嘗試載入 SDK 時,程式庫會先檢查 SDK 在建構期間是否隨附於應用程式。如果程式庫已隨附,程式庫會從 SDK 分割中擷取 SDK,並載入至應用程式處理程序中。如果 SDK 未隨附於應用程式,程式庫會委派平台 API 載入 SDK。

從資產中擷取 SDK

當應用程式嘗試載入隨附的 SDK 時,SDK 執行階段用戶端程式庫會檢查 SDK 的 DEX 檔案是否已擷取到裝置儲存空間 (code_cache),如果沒有,就會從資產中擷取這些項目。

通常在應用程式安裝或更新完成後,程式庫才會擷取檔案一次。

如果可用儲存空間低於允許的門檻 (目前為 100 MB),而且未擷取任何 DEX 檔案,程式庫會嘗試直接在支援的裝置 (API 27 以上版本) 上透過資產載入 SDK,這會導致記憶體用量增加。

SDK 類別的類別載入器

為避免 SDK 和應用程式類別之間發生衝突,系統會使用獨立類別載入器 (與主要應用程式類別載入器完全無關) 載入所有 SDK 類別。

在目前的 SDK 執行階段設計中,應用程式和 SDK 之間的所有通訊都會使用 Binder IPC 呼叫進行。隨附的 SDK 會使用相同的 SDK Binder 物件,而 Binder 交易序列化可讓應用程式開發人員將 SDK Binder 物件投放到應用程式端的 SDK Binder 介面。

針對其他內部互動 (例如初始化 SDK、向 SDK 提供控制器 API 等),程式庫會使用 Reflection 和 Dynamic Proxy 在不同類別載入器之間運作。

SDK 環境

SDKRuntime Provider 程式庫為 SDK 開發人員提供 API。這些 API 與平台 API 類似,但可讓 SDK 執行階段環境和 SDK 執行階段用戶端程式庫載入 SDK。

如要使用程式庫 SDK,您必須新增 androidx.privacysandbox.sdkruntime:sdkruntime-provider 依附元件,並擴充 SandboxedSdkProviderCompat (而非 SandboxedSdkProvider)。

您也必須使用 SandboxedSdkProviderAdapter 做為 SDK 供應商,以便在 SDK 執行階段環境中載入相容性供應商。

SdkSandboxControllerCompat 會委派給平台 API,當 SDK 在 SDK 執行階段中載入,或在 SDK 做為封裝的 SDK 載入時委派給 SDK 執行階段用戶端程式庫。

如果是隨附 SDK,程式庫會修改 SDK 環境,模擬與 SDK 執行階段環境類似的行為。

以下各節將說明 SDKRuntime 用戶端程式庫載入 SDK 時的預期行為。

SDK 資源

在應用程式程序中載入 SDK 時,系統會支援 SDK 資源 (res/)。Bundletool 將所有 SDK 資源與應用程式資源合併。

為避免衝突,系統會變更所有資源 ID 中的 packageId 前置字元,藉此重新對應 SDK 資源。

當 SDK Runtime 用戶端程式庫載入 SDK 時,系統會在執行階段更新 packageId,以使用 R 類別處理重新對應的資源。

Java 資源

在應用程式程序中載入 SDK 時,系統會支援 Java 資源。Bundletool 會將所有 SDK Java 資源複製到應用程式資產中的特殊目錄。SDKRuntime 用戶端程式庫會使用中繼類別載入器,將所有 Java 資源相關呼叫重新導向至新的根目錄。

SDK 素材資源

SDK 素材資源會與應用程式素材資源合併,不會重新對應。

SDK 儲存空間

為了支援 SDK 儲存空間,SDK 執行階段用戶端程式庫會為應用程式儲存空間中的每個隨附 SDK 建立專屬根目錄,並提供特殊內容,將此目錄當做儲存空間根目錄。

這個背景資訊可以從 SandboxedSdkProviderCompat#getContext 擷取。

支援的儲存空間相關方法:

  • getDataDir
  • getCacheDir
  • getCodeCacheDir
  • getNoBackupFilesDir
  • getDir
  • getFilesDir
  • openFileInput
  • openFileOutput
  • deleteFile
  • getFileStreamPath
  • fileList
  • getDatabasePath
  • openOrCreateDatabase
  • moveDatabaseFrom - 僅在 SDK 結構定義之間
  • deleteDatabase
  • databaseList
  • getSharedPreferences
  • moveSharedPreferencesFrom - 僅在 SDK 結構定義之間
  • deleteSharedPreferences

您可以針對內容呼叫 createDeviceProtectedStorageContext(),建立受裝置保護的儲存空間結構定義。

SdkSandboxControllerCompat

SDKRuntime 用戶端程式庫會針對在應用程式程序中載入的隨附 SDK 提供 SdkSandboxControllerCompat 實作方式。

如果用戶端程式庫不支援 API (例如使用比應用程式版本更舊的程式庫版本建構的 SDK),則會使用最合適的備用項 (無人工管理或例外狀況)。

版本管理

當 SDKRuntime 用戶端程式庫載入隨附的 SDK 時,會透過 SDK 中的 SDKRuntime 提供者程式庫執行握手。在握手期間,程式庫會交換版本並調整行為,以最合適的備用方案 (無人工管理或例外狀況) 取代無法使用的 API。

強烈建議您為應用程式和 SDK 開發人員使用最新版程式庫,否則可能無法在這兩部分使用需要支援的功能。

任何版本的 SDKRuntime 用戶端程式庫,都可以透過任何版本的 SDKRuntime 提供者程式庫載入 SDK,反之亦然。

日後,系統會將此變更至以特定版本的供應器程式庫載入 SDK 所需的最低用戶端程式庫版本。

這樣做可以盡量減少片段作業,並協助確保隨附的 SDK 成功載入後,大多數 API 都能獲得支援。