SDK 執行階段總覽

提供意見

Android 平台採用應用程式沙箱的概念,確保應用程式程式碼能在程序邊界妥善執行,同時維持程式碼的安全性邊界。應用程式往往包含 SDK 形式 (例如廣告 SDK 或數據分析 SDK) 的第三方程式碼。透過重複使用現有第三方程式碼,應用程式開發人員在利用各領域專家既有成果的同時,可以更專注於增添應用程式的獨特性,這樣不僅能實現原本靠自己就能輕鬆達成的目標,還可讓應用程式更為出眾。

和大多數作業系統一樣,在 Android 中,SDK 是在主應用程式的沙箱中執行,並會繼承主應用程式的權限,還可存取主應用程式的記憶體和儲存空間。這個架構雖然讓 SDK 和應用程式能夠彈性整合,但也可能導致未揭露的使用者資料收集和分享行為。此外,應用程式開發人員未必充分瞭解第三方 SDK 的功能和所存取資料的規模,因而難以妥善規劃應用程式的資料收集和分享做法。

在 Android 13 中,我們加入了全新的平台功能,允許第三方 SDK 在名為 SDK 執行階段的專屬執行階段環境中執行。SDK 執行階段可針對使用者資料的收集和分享行為,提供下列兩項更完善的防護和保證:

  • 經過修改的執行環境
  • 定義完善的 SDK 權限和資料存取權

我們目前正致力針對這項設計,向行動應用程式廣告社群徵求意見回饋。我們也歡迎廣大的開發人員社群提供意見,協助我們改進未來的 SDK 執行階段版本,包括支援其他使用情境。

目標

本提案旨在達成以下目標:

  • 透過程序隔離和定義完善的 API 與資料存取權控管機制,避免第三方 SDK 以未揭露的方式存取及分享使用者的應用程式資料。如要進一步瞭解程序隔離,請參閱本文另一節的說明。
  • 限制第三方 SDK 存取不重複永久 ID,避免這些 SDK 以未揭露的方式追蹤使用者的應用程式使用情形。
  • 減輕應用程式開發人員和使用者的負擔,透過安全的方式更新 SDK,並更快發布至應用程式。如要進一步瞭解我們提議的受信任 SDK 發布模型,請參閱本文另一節的說明。
  • 協助應用程式開發人員更妥善規劃應用程式的資料存取與分享做法。
  • 限制某些不安全的語言結構 (例如 JNI 程式碼),協助 SDK 開發人員防範自己的 SDK 遭到其他 SDK 竄改。
  • 透過充分控管顯示媒體的遠端檢視畫面,協助廣告 SDK 偵測及防範無效流量和廣告詐欺行為。
  • 盡可能避免對應用程式和 SDK 開發人員造成不當影響。

SDK 會透過獨立程序執行

我們提議的 SDK 執行階段可讓相容 SDK (下稱「支援執行階段 (RE) 的 SDK」) 透過獨立於應用程式之外的程序運作。平台會協助應用程式程序與 SDK 執行階段進行雙向通訊。詳情請參閱下方的「通訊」一節。非 RE SDK 仍會像現在一樣在應用程式的程序中運作。以下圖表說明這些變更:

顯示執行應用程式程序的所有流程圖
將呼叫 SDK 的程式碼和接收此程式碼呼叫的 SDK 加入 SDK 執行階段之前,都具備應用程式程序

圖表顯示應用程式程序和 SDK 執行階段程序拆分的程序
將呼叫 SDK 執行階段的程式碼新增至 SDK 執行階段後,呼叫 SDK 的程式碼會在應用程式的前景程序中與 SDK 介面通訊。這些介面會跨越處理程序邊界,進入 SDK 執行階段程序呼叫 SDK 本身。

適用於 SDK 的全新受信任發布模型

這項將 SDK 與應用程式區隔開來的提案促成另一項區隔概念:分離的 SDK 和應用程式發布機制。我們的提案要求採用受信任的發布和安裝機制,以確保應用程式 SDK 執行階段中所安裝的 SDK 正確無誤。這有助於保護使用者和應用程式開發人員,避免他們載入無效的 SDK,同時讓應用程式商店大幅減輕應用程式開發人員發布 SDK 的負擔。

開發人員再也不必先將應用程式與 SDK 建立靜態連結或封裝在一起,然後才上傳到應用程式商店發行。變更後的流程如下:

  1. SDK 開發人員可以將版本化 SDK 上傳到應用程式商店,與應用程式本身區隔開來。
  2. 應用程式開發人員可以建立、建構及上傳不含實際 SDK 依附元件的應用程式版本,藉此指定 SDK 依附元件。
  3. 使用者下載這個應用程式時,安裝程序就能利用應用程式的指定 SDK 依附元件,然後從應用程式商店下載這些項目。

新發布機制的好處在於,SDK 開發人員對 SDK 進行非破壞性變更 (即 API 和語意保持不變) 後,可以直接將 SDK 發布到裝置上,過程不需要應用程式開發人員的參與。SDK 開發人員可以直接部署或復原這些非破壞性 SDK 變更,無須等待應用程式開發人員使用新的 SDK 重新建構應用程式,也不必等候使用者更新應用程式。雖然破壞性變更仍須由應用程式開發人員更新,但 SDK 開發人員能以更快、更統一的方式,向更多使用者發布最新的非破壞性變更和修正項目,盡可能減少版本支援問題。

下圖說明我們提議的 SDK 發布流程:

「變更前」圖表
導入 SDK 執行階段之前,開發人員會將 SDK 直接傳送至應用程式。

「變更後」圖表
導入 SDK 執行階段後,SDK 開發人員就能使用 SDK 上傳 UI,將 SDK 發布至應用程式商店。接著,應用程式商店會處理將應用程式以及任何 SDK 依附元件發布至使用者裝置的發布作業。

SDK 和應用程式的建構、執行與發布方式異動

這是彈性 SDK 執行階段和發布技術的初始提案。下方各節提出的一系列異動涵蓋下列幾種廣泛類別:

  • 存取權:權限、記憶體、儲存空間
  • 執行:語言、執行階段變更、生命週期、媒體算繪
  • 通訊:應用程式對 SDK 和 SDK 對 SDK
  • 開發:在這個模型中如何進行建構、偵錯及測試
  • 發布:如何發布、更新、復原各個版本的 Android、應用程式和 SDK

本文件中也有「常見問題」一節,可協助您解決常見問題。

這是初始設計提案,我們瞭解對生態系統的部分成員來說這可能是個重大的異動。因此我們積極徵求您的意見,歡迎您透過 Issue Tracker 與我們分享想法。

存取權

管理系統的隱私權機制,意味著要管理各方存取不同資源的方式。為了實現我們在隱私保護方面的價值主張,我們提議更新用於存取應用程式、SDK 和使用者資料的模型,採用最低權限原則,以防有人以未經揭露的方式存取可能具私密性的資料。

SDK 權限

做為獨立程序,SDK 執行階段將具有一組明確定義的專屬權限,而不是繼承使用者授予應用程式的權限。初步調查廣告相關 SDK 使用的權限後,我們提議預設讓 SDK 執行階段中的 SDK 取得下列權限:

  • INTERNET:網際網路存取權,可與 Web 服務通訊。
  • ACCESS_NETWORK_STATE:網路資訊存取權。
  • 隱私維護 API 的存取權限。這類 API 可以提供核心廣告功能,而且不需要跨應用程式 ID。
  • AD_ID:能要求廣告 ID。這同樣受制於應用程式是否具有此權限。
  • BIND_GET_INSTALL_REFERRER_SERVICE:能使用 Google Play Install Referrer API 確定應用程式的安裝來源。

我們正在調查是否需要授予其他權限,以及其他權限的授予方法,盡可能降低使用者在隱私權和使用性方面受到的影響。如果有這組權限未能涵蓋的使用情境,請向我們提供意見

記憶體

SDK 執行階段有專屬程序,因此具備自己的獨立記憶體空間。根據預設,這個結構會拒絕 SDK 存取應用程式的記憶體空間,而且應用程式同樣無法存取 SDK 的記憶體空間。我們提議保留這項預設行為,以符合最低權限原則。

儲存空間

本提案旨在透過永久儲存空間,讓 SDK 能夠存取儲存空間以維持正常運作,同時減少跨應用程式和跨程序追蹤的情形。針對目前的儲存空間存取方式,我們提議做出以下調整:

  • 讓應用程式無法直接存取 SDK 儲存空間,反之亦然。
  • 讓 SDK 無法存取裝置的外部儲存空間。
  • 讓每個 SDK 執行階段都有供所有 SDK 存取的儲存空間,以及僅供特定 SDK 存取的私人儲存空間。

如同目前的儲存空間模型,這個儲存空間本身在大小方面沒有一定限制。SDK 可以利用儲存空間,以便快取資產。系統會在 SDK 未主動執行時,定期清除這個儲存空間。

執行

為確保應用程式、SDK 和使用者之間形成一個私密系統,執行脈絡本身 (程式碼格式、語言結構、可存取的 API 和系統資料) 必須鞏固相關隱私權邊界,或至少不會產生規避這些邊界的機會。但同時,我們也想保留豐富平台功能的存取權,並讓 SDK 能繼續使用目前可存取的大部分執行階段功能。為了取得平衡,在此我們提議對執行階段環境做出一些更新。

程式碼

Android 程式碼 (應用程式和 SDK) 主要是由 Android 執行階段 (ART) 解讀,無論程式碼是以 Kotlin 或 Java 編寫皆然。ART 的豐富性和提供的語言結構,以及比其他替代選項 (特別是原生程式碼) 多出的可驗證性,似乎能兼顧功能和隱私。因此,建議您在支援執行階段的 SDK 程式碼中僅使用 Dex 位元碼,不要支援 JNI 存取。

我們知道有些情況 (例如使用自訂封裝的 SQLite) 若使用原生程式碼,就必須改用替代方案,例如 Android SDK 內建的 SQLite 版本。

SELinux

在 Android 中,每個程序 (包括做為根層級執行的程序) 都會與特定 SELinux 情境一起執行,讓核心能夠管理系統服務、檔案、裝置和其他程序的存取權。為了繼續支援大部分的 SDK 使用情境,同時盡量防止我們設法導入的隱私保護機制遭到規避,我們提議在非系統應用程式的 SELinux 情境下,針對 SDK 執行階段做出下列更新:

  • 少數系統服務將可供存取 (仍在設計中)。
  • SDK 只能載入並執行其 APK 中的程式碼。
  • 少數系統資源將可供存取 (仍在設計中)。

API

我們允許在 SDK 執行階段中使用反射和叫用 API。但是,SDK 無法在其他支援執行階段的 SDK 上使用反射或叫用 API。我們會在日後更新中提供有關禁用 API 的完整提案。

此外,為了加強隱私保護,近期的 Android 平台版本逐漸增加對永久 ID 存取權的限制。在 SDK 執行階段方面,我們建議進一步限制存取可用於跨應用程式追蹤的 ID。

只有在前景執行的應用程式能存取 SDK Runtime API。在背景執行的應用程式若嘗試存取 SdkSandboxManager API,結果便是擲回 SecurityException

最後,RE SDK 無法使用通知 API 隨時向使用者傳送通知。

生命週期

應用程式 SDK 目前會跟進主應用程式的生命週期,也就是說,當應用程式進入或離開前景、關閉,或因記憶體壓力而遭作業系統強制停止,應用程式的 SDK 也會如此。我們建議將應用程式的 SDK 分拆至另外的程序,而這代表生命週期會有下列異動:

  • 應用程式可由使用者或作業系統終止,SDK 執行階段隨即會自動終止。
  • 作業系統可基於多種原因 (例如記憶體壓力或 SDK 無法處理的例外狀況) 終止 SDK 執行階段。

    在 Android 13 中,當應用程式在前景運作時,SDK 執行階段會以高優先順序執行,而且不太可能終止;當應用程式進入背景時,SDK 執行階段程序的優先順序則會降低,並符合終止條件。即使應用程式回到前景,SDK 執行階段程序的優先順序依然不會回升。因此當記憶體有壓力時,SDK 執行階段會比應用程式更有可能遭到終止。

    如果是 Android 14 以上版本,應用程式和 SDK 執行階段的程序優先順序會保持一致。應用程式和 SDK 執行階段的 ActivityManager.RunningAppProcessInfo.importance 程序優先順序應大致相同。

    遇到 SDK 執行階段已終止,但應用程式仍在執行 (SDK 遇到無法處理的例外狀況) 的情況時,SDK 執行階段的狀態 (包括先前載入的所有 SDK 和遠端檢視畫面) 就會遺失。應用程式開發人員可以透過下列任一方式處理 SDK 執行階段終止的情形:

    • 只要應用程式開發人員採用我們的建議,就能使用相關的生命週期回呼方法,進而偵測 SDK 執行階段的終止時間。
    • 如果 SDK 執行階段在廣告顯示時終止,廣告可能無法正常運作。舉例來說,檢視畫面可能會在螢幕上凍結,且不再支援互動功能。如果廣告檢視畫面不會影響使用者體驗,應用程式可以將其移除。
    • 應用程式可以再次嘗試載入 SDK 並提出廣告要求。
    • 對於 Android 14,如果 SDK 執行階段在有 SDK 載入時終止,且應用程式開發人員尚未註冊上述生命週期回呼方法,則應用程式預設會終止。只有已載入 SDK 的應用程式程序才會正常終止並結束。
    • SDK 為了通訊而傳回的繫結物件 (例如 SandboxedSdk) 會在用於應用程式時擲回 DeadObjectException

    這個生命週期模型可能在後續的更新中有所調整。

    假如持續發生問題,應用程式開發人員應規劃以不使用 SDK 的方式優雅降級;如果 SDK 對於應用程式的核心功能至關重要,則要設法通知使用者。如要進一步瞭解這項應用程式對 SDK 的互動,請參閱本文的「通訊」一節

非 RE SDK 可繼續使用所屬應用程式可用的標準 OS 基本功能 (包括服務、活動和播送),RE SDK 則不行。

特殊情況

我們目前無法針對以下情況提供支援,這些情況可能會導致非預期的行為:

  • 如果多個應用程式共用相同的 UID,SDK 執行階段可能無法正常運作。但請放心,日後可能會增加對共用 UID 的支援功能。
  • 如果應用程式擁有多個程序,則應在主要程序中載入 SDK。

媒體算繪

某些 SDK 會在應用程式指定的檢視畫面中算繪文字、圖片和影片等內容。如要達到這種效果,我們建議採用遠端算繪做法。也就是說,SDK 會從 SDK 執行階段中算繪媒體,但使用 SurfaceControlViewHost API,以便在應用程式指定的檢視畫面中算繪媒體。這使得 SDK 能夠以對使用者隱蔽的方式算繪媒體,同時有助於防止及偵測使用者與算繪媒體之間的無效或詐欺性互動。

SDK 執行階段中的 SDK 可以支援原生廣告,也就是那些不是由 SDK 算繪,而是由應用程式算繪的廣告。原生廣告的信號收集與廣告素材擷取程序和非原生廣告完全相同。我們正積極展開這方面的調查。

串流內影片廣告是在影片中播放的廣告,並會透過應用程式中的播放器顯示。由於影片是透過應用程式中的播放器 (而非 SDK 中的播放器或檢視區塊) 播放,因此所採用的算繪模型與其他廣告格式並不相同。我們正積極探索相關機制,設法同時支援伺服器端廣告插入和 SDK 式廣告插入功能。

系統健康狀態

我們希望降低 SDK 執行階段對使用者裝置系統健康狀態的影響,並致力設計因應方法。但某些系統資源極有限的入門級 Android 13 裝置 (例如搭載 Android Go 版本的裝置) 很可能會因為對系統健康狀態的影響,而無法支援 SDK 執行階段。我們會盡快提供成功使用 SDK 執行階段的最低需求條件。

通訊

應用程式和 SDK 目前是透過同一程序執行,因此兩者之間可不受限制地直接進行通訊。此外,Android 支援跨應用程式通訊 (即使通訊是透過 SDK 啟動及結束)。這個自由順暢的通訊模型可支援各種使用情境,但也可能導致應用程式之間、以及單一應用程式和不同應用程式中的 SDK 之間發生未揭露的資料分享行為。我們提議對這個通訊模型做出下列調整,設法在這類通訊的價值和我們想達到的目標之間取得平衡。

應用程式對 SDK

應用程式和 SDK 之間的介面是 SDK 最常使用的通訊路徑,而向使用者提供的獨特創新功能大多是靠 SDK 的 API 來實現。我們希望讓 SDK 能夠繼續做為創新和差異化的關鍵,因此提議讓 SDK 向應用程式提供 API,確保應用程式可受惠於所有創新發展。

考慮到 SDK 執行階段的程序邊界結構,我們提議建構可在應用程式中存取的管理層,用於在應用程式和 SDK 之間的這個邊界傳送 API 呼叫和回應/回呼。此外,我們提議由 SDK 開發人員定義這個管理層的介面,再透過我們開發的官方開放原始碼建構工具產生介面。

透過本提案,我們希望讓應用程式和 SDK 開發人員不必進行樣板管理作業,同時為 SDK 開發人員帶來更多彈性,並確保 SDK 程式碼可在 SDK 執行階段中執行,實現我們的隱私權目標。如果我們要採取這項做法,就必須聽取您的意見來設計 API 定義語言和工具。

一般互動模型如下:

  • 應用程式透過介面呼叫 SDK,並傳入回呼。
  • SDK 以非同步方式達成要求,並使用回呼進行回應。
  • 這可概略解釋成發布者/訂閱者模型,亦即應用程式可透過回呼訂閱 SDK 中的事件,當這類事件發生時,就會觸發回呼。

本提案採用全新的跨程序結構,這意味著需要管理兩個程序生命週期:應用程式本身的生命週期,以及 SDK 執行階段的生命週期。我們的提案希望盡可能讓這方面的相關作業能夠自動進行,減少應用程式和 SDK 開發人員受到的影響。下圖說明我們正在考慮的做法:

圖表
應用程式和 SDK 啟動時的應用程式對 SDK 互動流程圖。

平台會向應用程式提供新的 API,用於將 SDK 動態載入至 SDK 執行階段程序、接收程序狀態異動通知,以及與載入至 SDK 執行階段的 SDK 互動。

上圖中的圖表展示了在不使用管理層的情況下,較低層級的應用程式對 SDK 通訊流程。

應用程式會透過下列步驟,與在 SDK 執行階段程序中執行的 SDK 進行通訊:

  1. 應用程式必須先要求平台載入 SDK,才能與 SDK 互動。為確保系統完整性,應用程式必須在資訊清單檔案中指定要載入的 SDK,之後能載入的 SDK 將僅限於這些指定項目。

    以下程式碼片段提供說明用 API 範例:

    SdkSandboxManager.loadSdk(String sdkName, Bundle data, Executor executor,
        OutcomeReceiver<SandboxedSdk, LoadSdkException> receiver)
    
  2. SDK 會收到指出本身已載入的通知,並傳回其介面。 這個介面僅供應用程式程序使用。如要在程序邊界以外共用介面,則介面必須以 IBinder 物件的形式傳回。

    繫結服務指南列有多種提供 IBinder 的方式。無論您選擇哪種方式,都必須在 SDK 與呼叫端應用程式之間保持一致。這些圖表使用 AIDL 做為範例。

  3. SdkSandboxManager 接收 IBinder 介面,並將其傳回應用程式。

  4. 應用程式取得 IBinder 並投放到 SDK 介面,並呼叫其函式:

    IBinder binder = sandboxSdk.getInterface();
    ISdkInterface mySdkInterface = ISdkInterface.Stub.asInterface(binder);
    mySdkInterface.something();
    

應用程式也可以透過下列步驟,從 SDK 算繪媒體:

  1. 如本文「媒體算繪」一節所述,應用程式可以呼叫 requestSurfacePackage() 並擷取適當的 SurfaceControlViewHost.SurfacePackage,藉此要求 SDK 在檢視畫面中算繪媒體。

    以下程式碼片段提供說明用 API 範例:

    SdkSandboxManager.requestSurfacePackage(String sdkName, Bundle extraParams,
            Executor executor,
            OutcomeReceiver<Bundle, RequestSurfacePackageException> receiver)
    
  2. 應用程式接著可以在 SurfaceView 中透過 setChildSurfacePackage API,將傳回的 SurfacePackage 嵌入 SurfaceView 中。

    以下程式碼片段提供說明用 API 範例:

    SurfaceView.setChildSurfacePackage(SurfacePackage surfacePackage)
    

在我們的提案中,IBinderrequestSurfacePackage() API 為一般 API,且不是由應用程式直接呼叫,而要由在「墊片」層產生的 API 參考資料 (如上所述) 呼叫,減輕應用程式開發人員的負擔。

SDK 對 SDK

同一應用程式中的兩個 SDK 往往需要進行通訊。如果特定 SDK 是由多個 SDK 構成,或是不同方的兩個 SDK 需要協同運作,以滿足呼叫應用程式所提出的要求,就可能會發生這個情形。

要考量的重要情況有以下兩種:

  • 兩個 SDK 都支援執行階段。在這種情況下,兩個 SDK 都是在 SDK 執行階段中執行,並適用所有相關保護措施。這些 SDK 無法如目前在應用程式中一般進行通訊,因此我們特別在 SdkSandboxController 中新增了一個 API,用來針對所有載入的 RE SDK 擷取 SandboxedSdk 物件。如此一來,SDK 就能與載入 SDK 工作階段的其他 SDK 進行通訊。
  • 只有一個 SDK 支援執行階段
    • 如果呼叫端的 SDK 正在應用程式中執行,整個流程就和應用程式本身呼叫 SDK 執行階段中的第二個 SDK 沒有不同。
    • 如果呼叫端的 SDK 正在 SDK 執行階段中執行,我們建議使用「應用程式對 SDK」一節所述的 IBinder 來提供方法,讓應用程式中的程式碼監聽、處理及回應系統提供的回呼。
    • 未支援執行階段的廣告 SDK 可能無法自行註冊,因此建議您建立中介 SDK 並處理註冊事宜,這個 SDK 會加入任何合作夥伴或應用程式 SDK,做為應用程式的直接依附元件,並以轉接程式的形式,在不支援執行階段的 SDK (或其他應用程式依附元件) 與支援執行階段的中介服務之間建立通訊。

SDK 對 SDK 通訊的功能組分成下列幾類:

  • SDK 執行階段中的 SDK 對 SDK 通訊 (適用於最新的開發人員預覽版)
  • 應用程式和 SDK 執行階段中的 SDK 互相通訊 (適用於最新的開發人員預覽版)
  • 如何將檢視畫面和遠端算繪用於中介服務 (開發中的提案)

以下是在設計基本功能時要考慮的用途:

  1. 中介服務和出價。很多廣告 SDK 都提供中介服務或出價功能,即廣告 SDK 會呼叫各種其他 SDK 來讓廣告曝光 (中介服務),或是收集信號以進行競價 (出價)。一般來說,負責協調的 SDK 會透過自身提供的轉接程式呼叫其他 SDK。具有上述基本功能時,負責協調的 SDK (無論是否為 RE SDK) 應能存取所有 RE SDK 和其他 SDK,從而正常運作。我們正積極調查如何在這種情況下進行算繪。
  2. 功能探索。有些 SDK 產品是由較小的 SDK 組成,後者會透過跨 SDK 探索程序,確定向應用程式開發人員提供的最終功能組。註冊和探索基本功能應支援此用途。
  3. 發布元件訂閱模型。有些 SDK 的設計包含核心的事件發布元件,其他 SDK 或應用程式只要訂閱這個元件,就能透過回呼接收通知。上述基本功能應支援此用途。

應用程式對應用程式

所謂應用程式對應用程式通訊,是指兩個進行通訊的程序中至少有一個是支援執行階段的 SDK,而且是未揭露資料共用機制的潛在媒介。正因如此,SDK 執行階段無法與用戶端應用程式以外的任何應用程式建立直接通訊管道,也無法在為其他應用程式建立的另一 SDK 執行階段中與 SDK 建立這類管道。以下方法可確保 SDK 執行階段滿足上述條件:

  • SDK 無法在其資訊清單中定義 <service><contentprovider><activity> 等元件。
  • SDK 無法發布 ContentProvider 或傳送廣播。
  • SDK 可啟動屬於其他應用程式的活動,但會限制可在意圖中傳送哪些內容。舉例來說,您無法在這個意圖中新增額外或自訂動作。
  • SDK 只能啟動或繫結至服務的許可清單。
  • SDK 只能存取系統 ContentProvider 的子集 (例如 com.android.providers.settings.SettingsProvider),其中取得的資料會缺少 ID,且無法用於建構使用者的指紋。這些檢查也適用於使用 ContentResolver 存取 ContentProvider 的情況。
  • SDK 只能存取部分受保護的廣播接收器 (例如 android.intent.action.AIRPLANE_MODE) 子集。

資訊清單標記

SDK 安裝之後,PackageManager 會剖析 SDK 的資訊清單,但當禁用的資訊清單標記出現時,就無法順利安裝 SDK。舉例來說,SDK 可能不會定義 <service>, <activity>, <provider><receiver> 等元件,也可能不會在資訊清單中宣告 <permission>。雖然 SDK 執行階段不支援安裝失敗的標記,日後的 Android 版本可能會支援未安裝失敗、但默默遭到忽略的標記。

這些檢查可能也適用於任何 SDK 採用的建構時間工具,SDK 會利用這些工具建立 SDK 套件;而對於上傳至應用程式商店的情況,或許也能進行這類檢查。

活動支援

SDK 執行階段環境中的 SDK 無法將活動標記新增至專屬的資訊清單檔案中,也不能使用 Context.startActivity 啟動自己的活動。取而代之的是,平台會在收到要求時為 SDK 建立活動並與 SDK 共用。

平台活動屬於 android.app.Activity 類型。這類活動會從其中一個應用程式活動啟動,而且屬於應用程式工作的一環。我們不支援 FLAG_ACTIVITY_NEW_TASK

為了讓 SDK 啟動活動,SDK 應註冊 SdkSandboxActivityHandler 類型的執行個體,以便在應用程式為了啟動活動而呼叫 SdkSandboxManager::startSdkSandboxActivity(Activity, IBinder) 時,用於通知活動建立事宜。

下圖是要求活動的流程。

圖表
顯示活動啟動流程的循序圖。

開發

本提案的一大原則,是要盡可能減少對開發人員生態系統的影響。因此,本提案將為開發人員提供一組全方位的開發工具,用於編寫、建構和偵錯 RE 應用程式與 SDK。不過,為了確保本提案的完整性,RE 應用程式和 SDK 的設定、編寫和建構方式會有一些異動。

編寫

Android Studio 和相關工具將更新為支援感知 SDK 執行階段,確保開發人員能夠正確設定 RE 應用程式和 SDK,舊有或不受支援的呼叫亦更新為新的替代方案。在編寫階段,我們的提案將要求開發人員採取幾個步驟。

應用程式開發人員

應用程式必須在應用程式資訊清單中指定 RE SDK 和 SDK 憑證依附元件。在本提案中,我們將此視為應用程式開發人員提供的可靠資訊來源。例如:

  • 名稱:SDK 或程式庫的套件名稱。
  • 主要版本:SDK 的主要版本代碼。
  • 憑證摘要:SDK 版本的憑證摘要。我們提議讓 SDK 開發人員透過相關應用程式商店取得及登錄特定版本的值。

這僅適用於透過應用程式商店發布的 SDK (無論是否為 RE SDK)。透過靜態方式連結 SDK 的應用程式將使用目前的依附元件機制。

我們的目標是盡可能降低對開發人員造成的影響,因此必須做到在應用程式指定支援 SDK 執行階段的目標 API 級別時,確保應用程式開發人員只需要準備一個版本,不因執行該版本的裝置是否支援 SDK 執行階段而異。

SDK 開發人員

在我們提出的設計中,RE SDK 開發人員必須在資訊清單中明確宣告代表 SDK 或程式庫實體的新元素。另外還必須提供做為依附元件的一組類似值和子版本:

  • 名稱:SDK 或程式庫的套件名稱。
  • 主要版本:SDK 的主要版本代碼。
  • 子版本:SDK 的子版本代碼。

如果 RE SDK 開發人員有其他做為建構階段依附元件的 RE SDK,則可能必須進行宣告,做法如同應用程式開發人員宣告相同依附元件的方式。仰賴非 RE SDK 的 RE SDK 必須以靜態方式建立連結。如果非 RE SDK 需要使用 SDK 執行階段不支援的功能,或是必須在應用程式的程序中執行,這種靜態連結就可能產生問題,而系統會在建構時間或測試通過期間偵測到問題。

RE SDK 開發人員可能會想繼續支援非 RE 裝置 (例如搭載 Android 12 以下版本的裝置),以及系統資源極有限的入門級 Android 13 裝置 (如本文的「系統健康狀態」一節所述)。我們正在設法確保 SDK 開發人員能夠繼續使用單一程式碼集來支援 RE 和非 RE 環境。

建構

應用程式開發人員

應用程式開發人員在建構階段應該幾乎不會感覺到任何差異。無論 SDK 依附元件是透過本機或應用程式商店發布 (RE 或非 RE),都需存在於機器上才能進行程式碼檢查、編譯和建構作業。我們提議讓 Android Studio 簡化這些細節,為具有一般使用需求的應用程式開發人員減輕負擔,並盡可能維持透明公開。

雖然我們預期偵錯版本需要包含所有程式碼和符號才可進行偵錯,但開發人員建構發布子版本時,可選擇將所有透過應用程式商店發布的 SDK (RE 或非 RE) 從最終成果中移除。

我們目前仍在初期設計階段,等有相關成果時會再提供更多資訊。

SDK 開發人員

我們正在設法確保開發人員能將非 RE 和 RE 版本的 SDK 整合成單一成果來發布。這樣一來,應用程式開發人員就不必分別支援 SDK 的 RE 和非 RE 版本。

與應用程式類似,透過應用程式商店發布的依附元件 SDK 必須存在於機器上,才能進行程式碼檢查、編譯和建構作業,而我們預期 Android Studio 應可流暢協助處理這項作業。

測試

應用程式開發人員

如我們的提案中所述,應用程式開發人員將可在搭載 Android 13 的裝置上照常測試應用程式。應用程式建構完成後,即可在 RE 裝置上或模擬器中安裝。這項安裝程序可確保在裝置或模擬器的 SDK 執行階段中安裝的 SDK 正確無誤 (無論 SDK 是提取自遠端 SDK 存放區,還是來自建構系統的快取)。

SDK 開發人員

SDK 開發人員通常會在裝置上和模擬器中,使用內部測試應用程式來測試開發成果。這點不會因為我們的提案而有所改變。此外,應用程式內驗證流程也會依照上方應用程式開發人員部分所述的步驟進行,且開發人員只需針對 RE 和非 RE 應用程式建構單一版本成果。SDK 開發人員將可逐步執行程式碼 (無論程式碼是否在 SDK 執行階段中),只不過在進階偵錯和剖析工具方面可能會受到一些限制。我們目前正積極對這方面進行調查。

發布

我們提出將應用程式與 SDK 分開的設計提案,使得開發人員可以透過應用程式商店發布 SDK。無論在哪一間應用程式商店,都可以採用這種做法。這樣做所帶來的優點相當明確:

  • 確保 SDK 品質優異且具有一致性。
  • 為 SDK 開發人員簡化發布流程。
  • 讓開發人員可加速推出安裝版應用程式的 SDK 子版本更新。

為了支援 SDK 發布功能,應用程式商店可能必須設有相關機制來提供下列大部分的功能:

  • 讓 SDK 開發人員將可透過應用程式商店發布的 SDK 上傳至商店、進行更新、復原並視需要移除。
  • 確保 SDK 及其來源和應用程式及其來源的完整性,並且解析前述項目的依附元件。
  • 以穩定一致且高效能的方式將 SDK 部署到裝置上。

與時俱進的限制機制

我們預計會隨著日後的 Android 版本,不斷改進 SDK 執行階段中程式碼的相關限制。但為了確保應用程式相容性,我們不會透過特定 SDK 級別的主系列模組更新,來變更這些限制。在應用程式商店政策對特定 targetSdkVersion 的支援淘汰之前,系統會保留與該 targetSdkVersion 相關聯的行為,但 targetSdkVersion 的淘汰速度可能會比應用程式更快。這些限制預計會隨 Android SDK 版本頻繁變更,在前幾個發布的版本中尤其如此。

此外,我們正在打造初期測試機制,讓外部和內部測試人員能夠加入群組,取得下一個 Android 版本適用的一系列建議限制。這有助於我們取得意見回饋,放心地依照建議對這一系列限制做出變更。

常見問題

  1. 什麼是廣告相關 SDK?

    廣告相關 SDK 可在非由廣告客戶擁有的應用程式中傳達商業性質的訊息,協助進行使用者指定作業的任一環節,包括但不限於數據分析 SDK (可建立使用者群組供日後做為指定目標)、廣告放送 SDK、適用於廣告的反濫用和反詐欺 SDK、參與度 SDK 和歸因 SDK。

  2. 任何 SDK 都能在 SDK 執行階段中執行嗎?

    雖然我們一開始將重心放在廣告相關 SDK 上,但如果非廣告相關 SDK 的開發人員想協助維護使用者隱私,並認為自己的 SDK 能在上述條件下運作,那麼也歡迎向我們提供意見,說明自己的 SDK 在 SDK 執行階段中的運作情形。不過,SDK 執行階段並非與所有 SDK 設計都相容。除了本文所述的限制以外,如果 SDK 需要與主應用程式進行即時通訊或高處理量通訊,那麼可能也不適合使用 SDK 執行階段。

  3. 為什麼選擇程序隔離,而不是在程序的 Java 執行階段中隔離?

    目前 Java 執行階段無法協助維持必要的安全性邊界,無法實現 Android 使用者希望擁有的隱私權保證。如果要嘗試導入這類機制,可能得花上好幾年的時間,而且不保證會成功。因此,Privacy Sandbox 採用長期證實有效,且為人熟知的程序邊界技術。

  4. 將 SDK 移入 SDK 執行階段程序,可以節省下載大小或空間嗎?

    如果多個應用程式都整合到相同版本且支援執行階段的 SDK,就能節省下載大小和磁碟空間。

  5. SDK 可以在 SDK 執行階段中存取哪種應用程式生命週期事件 (例如應用程式進入背景的情況)?

    我們正積極設計支援功能,設法在用戶端應用程式發生應用程式層級的生命週期事件時 (例如應用程式進入背景/前景) 通知 SDK 執行階段。即將推出的開發人員預覽版會提供設計和程式碼範例。