Play Feature Delivery 總覽

Google Play 的應用程式提供模型會使用 Android App Bundle,根據每位使用者的裝置設定產生並提供最佳化 APK,讓使用者只下載執行應用程式所需的程式碼和資源。

Play Feature Delivery 使用應用程式套件的進階功能,以便視情況提供或隨選下載應用程式的特定功能。為此,您必須先將這些功能從基礎應用程式隔離,並納入功能模組。

功能模組建構設定

使用 Android Studio 建立新的功能模組時,IDE 會將下列 Gradle 外掛程式套用至模組的 build.gradle 檔案。

// The following applies the dynamic-feature plugin to your feature module.
// The plugin includes the Gradle tasks and properties required to configure and build
// an app bundle that includes your feature module.

plugins {
  id 'com.android.dynamic-feature'
}

標準應用程式外掛程式可用的許多屬性也適用於功能模組。以下各節說明應該與不應納入功能模組建構設定的屬性。

不應包含在功能模組建構設定中的內容

由於每個功能模組取決於基礎模組,因此也會沿用特定設定。所以您應在功能模組的 build.gradle 檔案中省略下列項目:

  • 簽署設定:應用程式套件是根據基本模組中指定的簽署設定完成簽署。
  • minifyEnabled 屬性:您可以透過基本模組的建構設定,為整個應用程式專案啟用程式碼縮減功能。因此,您應在功能模組中省略這個屬性。不過,您可以為每個功能模組指定其他 ProGuard 規則
  • versionCodeversionName:建立應用程式套件時,Gradle 會使用基礎模組提供的應用程式版本資訊。您應從功能模組的 build.gradle 檔案中省略這些屬性。

建立與基礎模組的關係

Android Studio 建立功能模組時,為了讓基本模組偵測到該模組,會將 android.dynamicFeatures 屬性新增至基本模組的 build.gradle 檔案,如下所示:

// In the base module’s build.gradle file.
android {
    ...
    // Specifies feature modules that have a dependency on
    // this base module.
    dynamicFeatures = [":dynamic_feature", ":dynamic_feature2"]
}

此外,Android Studio 也納入基礎模組做為功能模組的依附元件,如下所示:

// In the feature module’s build.gradle file:
...
dependencies {
    ...
    // Declares a dependency on the base module, ':app'.
    implementation project(':app')
}

指定其他 ProGuard 規則

雖然只有基本模組的建構設定可啟用應用程式專案的程式碼縮減功能,但您可以利用 proguardFiles 屬性,透過各個功能模組提供自訂 ProGuard 規則,如下所示。

android.buildTypes {
     release {
         // You must use the following property to specify additional ProGuard
         // rules for feature modules.
         proguardFiles 'proguard-rules-dynamic-features.pro'
     }
}

請注意,在建構期間,這些 ProGuard 規則會與其他模組 (包括基礎模組) 中的規則合併。因此,雖然每個功能模組可能都會指定一組新規則,但這些規則會套用至應用程式專案中的所有模組。

部署應用程式

在開發支援功能模組的應用程式時,您可以照常為已連結的裝置部署應用程式,方法是從選單列中依序選取「Run」>「Run」(或者點選工具列中的「Run」圖示 )。

如果您的應用程式專案包含一或多個功能模組,可以按照下列步驟修改現有的執行/偵錯設定,選擇要在部署應用程式時納入哪些功能:

  1. 在選單列中,依序選取「Run」>「Edit Configurations」
  2. 在「Run/Debug Configurations」(執行/偵錯設定) 對話方塊的左側面板中,選取所需「Android App」設定。
  3. 在「General」分頁的「Dynamic features to deploy」下方,找到部署應用程式時要納入的各項功能模組,然後勾選旁邊的方塊。
  4. 按一下「OK」

根據預設,Android Studio 不會使用應用程式套件部署應用程式。相反地,IDE 會在裝置中建構並安裝針對部署速度 (而非 APK 大小) 最佳化的 APK。如要將 Android Studio 設定改為透過應用程式套件建構及部署 APK 與免安裝體驗,請修改執行/偵錯設定

將功能模組用於自訂提供功能

使用功能模組特有的好處,就是能自訂將應用程式的不同功能下載到搭載 Android 5.0 (API 級別 21) 以上版本的裝置上的方式和時機。舉例來說,如要縮減應用程式的初始下載大小,可以設定某些功能,讓使用者視需求隨選下載,或是只透過支援拍照/擴增實境等特定功能的裝置下載。

儘管在預設情況下,只要以應用程式套件的形式上傳應用程式,即可取得經過高度最佳化的下載內容,但若要使用更進階的自訂功能提供選項,就必須使用「功能模組」,對應用程式的功能進行額外設定及模組化作業。也就是說,功能模組可提供用於建立模組化功能的構成元素,方便您設定各項功能,讓使用者視需求下載。

假設某個應用程式允許使用者透過線上市集買賣商品。您可以合理地將應用程式的下列各功能模組化,成為獨立的功能模組:

  • 帳戶登入和建立
  • 瀏覽市集
  • 上架銷售商品
  • 處理付款

下表說明功能模組支援的不同提供選項,以及如何利用這些選項,將範例市集應用程式的初始下載大小最佳化。

提供選項 行為 用途範例 開始使用
安裝時提供 根據預設,若未設定上述任何提供選項,系統會在安裝應用程式時下載功能模組。這項行為相當重要,因為這意味著您可以逐步採用進階提供選項。舉例來說,您必須先使用 Play Feature Delivery 程式庫完整實作隨選下載程序,才能受益於應用程式功能的模組化作業,並啟用隨選提供功能。

此外,應用程式日後也可以要求解除安裝各項功能。因此,假如只在應用程式安裝期間需要 (安裝後就不需要) 特定功能,可以要求從裝置上移除該功能,縮減安裝大小。

如果應用程式提供特定訓練活動,例如有關如何在市集中買賣商品的互動式指南,您可以預設在應用程式安裝時加入該功能。

不過,如要縮減應用程式安裝大小,應用程式可以在使用者完成訓練後要求刪除該功能。

運用未設定進階提供選項的功能模組,將應用程式模組化

如要瞭解如何移除使用者不再需要的特定功能模組,進而縮減應用程式安裝大小,請參閱「管理已安裝的模組」。

隨選提供 允許應用程式視需要要求和下載功能模組。 如果使用市集應用程式的人中只有 20% 上架商品來販售,有個不錯的策略可以為大多數使用者縮減初始下載大小,那就是將拍照、輸入商品說明,以及上架待售商品的功能設為「隨選下載」。也就是說,您可以設定只在使用者有意將商品上架到市集販售時,才下載應用程式銷售功能的功能模組。

此外,如果使用者在經過一段時間後不再銷售商品,應用程式可以要求解除安裝該功能,以縮減其安裝大小。

建立功能模組並設定隨選提供功能。這樣一來,應用程式就能使用 Play Feature Delivery 程式庫,要求以隨選的方式下載模組。
條件式提供 可讓您指定硬體功能、語言代碼和最低 API 級別等特定使用者裝置需求,判定是否在應用程式安裝時下載模組化功能。 如果市集應用程式提供全球服務,可能需要支援只在當地或特定區域風行的付款方式。為了縮減應用程式初始下載大小,您可以建立獨立的功能模組,用於處理特定類型的付款方式,並根據使用者登錄的語言代碼,有條件地安裝在使用者的裝置上。 建立功能模組並設定條件式提供
免安裝提供 Google Play 免安裝技術可讓使用者無須在裝置上安裝應用程式,就能與應用程式互動。他們只需透過 Google Play 商店中的「立即體驗」按鈕或您建立的網址,就能體驗應用程式。以這種方式提供內容,能夠更輕鬆地提高應用程式使用者的參與度。

透過免安裝提供,您可運用 Google Play 免安裝技術,讓使用者無須安裝就能立即體驗應用程式的某些功能。

假設遊戲的輕量功能模組中含有遊戲的前幾個關卡。您可以將該模組設為免安裝即用,讓使用者不必安裝應用程式,就能透過網址連結或「立即體驗」按鈕體驗遊戲。 建立功能模組並設定免安裝提供功能。這樣一來,應用程式就能使用 Play Feature Delivery 程式庫,要求以隨選的方式下載模組。

請留意,利用功能模組將應用程式功能模組化只是第一步。如要支援 Google Play 免安裝技術,應用程式基本模組和相應免安裝即用功能的下載大小,都必須符合嚴格的大小限制。詳情請參閱「縮減應用程式或遊戲大小來提供免安裝體驗」。

建立資源的 URI

如果想透過 URI 存取功能模組中儲存的資源,以下是利用 Uri.Builder() 產生功能模組資源 URI 的方式:

Kotlin

val uri = Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                .authority(context.getPackageName()) // Look up the resources in the application with its splits loaded
                .appendPath(resources.getResourceTypeName(resId))
                .appendPath(String.format("%s:%s",
                  resources.getResourcePackageName(resId), // Look up the dynamic resource in the split namespace.
                  resources.getResourceEntryName(resId)
                  ))
                .build()

Java

String uri = Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                .authority(context.getPackageName()) // Look up the resources in the application with its splits loaded
                .appendPath(resources.getResourceTypeName(resId))
                .appendPath(String.format("%s:%s",
                  resources.getResourcePackageName(resId), // Look up the dynamic resource in the split namespace.
                  resources.getResourceEntryName(resId)
                  ))
                .build().toString();

資源路徑的每個部分都是在執行階段建構,確保在載入分割 APK 後,才會產生正確的命名空間。

為了說明 URI 的產生方式,先假設您有具備下列名稱的應用程式和功能模組:

  • 應用程式套件名稱:com.example.my_app_package
  • 功能的資源套件名稱:com.example.my_app_package.my_dynamic_feature

如果上述程式碼片段中的 resId 參照功能模組中名為「my_video」的原始檔案資源,則上述的 Uri.Builder() 程式碼會輸出下列內容:

android.resource://com.example.my_app_package/raw/com.example.my_app_package.my_dynamic_feature:my_video

這樣一來,應用程式就能利用此 URI 存取功能模組的資源。

如要驗證 URI 中的路徑,可以使用 APK 分析工具檢查功能模組 APK,並判定套件名稱:

APK 分析工具檢查已編譯資源檔案的內容時的螢幕截圖。
圖 1. 使用 APK 分析工具檢查已編譯資源檔案中的套件名稱。

功能模組的注意事項

您可以透過功能模組加快建構與工程作業,並廣泛自訂應用程式功能提供方式,縮減應用程式大小。不過,使用功能模組時,請留意相關限制和極端案件:

  • 如果以條件式/隨選提供功能在單一裝置上安裝 50 個以上的功能模組,可能會引發效能問題。未設為可移除的安裝期間模組會自動納入基本模組,並在每部裝置上只計為一個功能模組。
  • 將設為可移除的安裝時提供模組數量限制在 10 個以下,否則應用程式的下載與安裝時間可能加長。
  • 只有搭載 Android 5.0 (API 級別 21) 以上版本的裝置,才能隨選下載和安裝功能。若要讓功能適用於較舊的 Android 版本,請在建立功能模組時,啟用「融合」功能。
  • 啟用 SplitCompat,讓應用程式能夠存取隨選提供的已下載功能模組。
  • android:exported 設為 true 時,功能模組不應在資訊清單中指定活動。原因在於,當其他應用程式嘗試啟動活動時,不保證裝置已下載功能模組。此外,應用程式在嘗試存取特定功能的程式碼和資源前,應先確認已下載該功能。詳情請參閱「管理已安裝的模組」。
  • Play Feature Delivery 規定您必須使用應用程式套件發布應用程式,因此請務必瞭解這類套件的已知問題

功能模組資訊清單參考資料

使用 Android Studio 建立新的功能模組時,IDE 會包含模組所需的大多數資訊清單屬性,以便呈現功能模組的行為模式。此外,建構系統也會在編譯期間插入部分屬性,因此您不需自行指定或修改這些屬性。下表說明重要的功能模組資訊清單屬性。

屬性 說明
<manifest 這是一般的 <manifest> 區塊。
xmlns:dist="http://schemas.android.com/apk/distribution" 指定新的 dist: XML 命名空間 (將於下文說明)。
split="split_name" 當 Android Studio 建立應用程式套件時,其中會包含這項屬性。因此,請勿自行加入或修改這項屬性

定義模組名稱,應用程式使用 Play Feature Delivery 程式庫要求隨選模組時,會指定這個名稱。

Gradle 如何判定這個屬性的值:

根據預設,當您透過 Android Studio 建立功能模組時,IDE 會使用您指定的模組名稱,在 Gradle 設定檔中將該模組視為 Gradle 子專案。

建構應用程式套件時,Gradle 會使用子專案路徑的最後一個元素,將此資訊清單屬性插入模組的資訊清單。舉例來說,假設您在 MyAppProject/features/ 目錄中建立新的功能模組,並將「dynamic_feature1」指定為模組名稱,IDE 就會在 settings.gradle 檔案中新增 ':features:dynamic_feature1' 做為子專案。這樣一來,Gradle 就會在建構應用程式套件時,將 <manifest split="dynamic_feature1"> 插入模組的資訊清單。

android:isFeatureSplit="true | false"> 當 Android Studio 建立應用程式套件時,其中會包含這項屬性。因此,請勿手動加入或修改這項屬性

指定這個模組為功能模組。基礎模組和設定 APK 中的資訊清單可能會省略這個屬性,或是將其設為 false

<dist:module 定義屬性,判定模組以 APK 的形式包裝和發布的方式。
dist:instant="true | false" 指定是否應透過 Google Play 免安裝技術提供模組,做為免安裝體驗。

如果應用程式包含一或多個免安裝即用的功能模組,您也必須將基本模組設為免安裝即用。使用 Android Studio 3.5 以上版本時,IDE 會在您建立免安裝即用的功能模組時,為您完成這項操作。

您無法同時將此 XML 元素設為 true,又設定 <dist:on-demand/>。不過,還是可以使用 Play Feature Delivery 程式庫,要求隨選下載免安裝即用的功能模組「做為免安裝體驗」。根據預設,當使用者下載並「安裝」應用程式時,裝置會下載並安裝應用程式的免安裝即用功能模組,以及基本 APK。

dist:title="@string/feature_name"> 指定使用者看到的模組標題。例如,裝置要求下載確認時,裝置可能會顯示這個標題。

您必須在基礎模組的 module_root/src/source_set/res/values/strings.xml 檔案中納入這個標題的字串資源。

<dist:fusing dist:include="true | false" /> 指定是否將模組納入適用於搭載 Android 4.4 (API 級別 20) 以下版本的裝置的多個 APK。

此外,當您使用 bundletool 從應用程式套件產生 APK 時,只會在通用 APK 中納入將這個屬性設為 true 的功能模組-這是單體式 APK,內含應用程式支援的所有裝置設定的程式碼和資源。

<dist:delivery> 封裝自訂模組提供的選項,如下所示。請留意,每個功能模組只能設定一種自訂提供選項。
<dist:install-time> 指定應可在安裝期間使用該模組。如果功能模組未指定另一種自訂提供選項,就會採取這項預設行為。

如要進一步瞭解安裝期間下載作業,請參閱「設定安裝時提供功能」。

這個節點也可以指定條件,限制模組只能下載至符合特定需求的裝置,相關需求包括裝置功能、使用者國家/地區或最低 API 級別。詳情請參閱設定條件式提供功能

<dist:removable dist:value="true | false" />

如果這個屬性設為 false 或未設定,bundletool 會在透過套件產生分割 APK 時,將安裝期間模組融入基本模組。融合後產生的分割 APK 較少,因此這項設定有助提升應用程式效能。

removable 設為 true 時:不會將安裝時間模組融入基礎模組。如果日後想要解除安裝模組,請設為 true。不過,如果將過多模組設為可移除,則可能會延長應用程式的安裝時間。

預設為 false。只有在您想停用功能模組的融合功能時,才需要在資訊清單中設定這個值。

注意:只有使用 Android Gradle 外掛程式 4.2 或透過指令列使用 bundletool v1.0 時,才能使用這項功能。

</dist:install-time>  
<dist:on-demand /> 指定模組應以隨選下載的形式提供。也就是說,無法在安裝時使用模組,但應用程式之後可能會要求下載該模組。

如要進一步瞭解隨選下載作業,請參閱「設定隨選提供功能」。

</dist:delivery>
</dist:module>
<application
android:hasCode="true | false">
...
</application>
如果功能模組不會產生任何 DEX 檔案,也就是未包含之後編譯成 DEX 檔案格式的程式碼,請務必執行下列操作 (否則可能發生執行階段錯誤):
  1. 在功能模組的資訊清單中,將 android:hasCode 設為 "false"
  2. 將以下內容加入基本模組的資訊清單:
    <application
      android:hasCode="true"
      tools:replace="android:hasCode">
      ...
    </application>
    
...
</manifest>

其他資源

若要進一步瞭解如何使用功能模組,請參考下列資源。

網誌文章

影片

服務條款與資料安全性

存取或使用 Play Feature Delivery 程式庫,即表示您同意《Play Core 軟體開發套件服務條款》。存取該程式庫前,請詳閱並瞭解所有適用的條款和政策。

資料安全性

Play Core 程式庫是應用程式與 Google Play 商店之間的執行階段介面。因此,在應用程式中使用 Play Core 時,Play 商店會執行自己的程序,包括依據《Google Play 服務條款》的規範處理資料。以下資訊說明 Play Core 程式庫如何處理資料,以因應來自應用程式的特定要求。

其他語言 API

收集到資料的使用情況 已安裝的語言清單
資料收集目的 收集到的資料會用於提供不同語言版本的應用程式,並在應用程式更新後保留已安裝的語言。
資料加密 資料已加密。
資料分享 資料不會轉移給任何第三方。
資料刪除 過了固定的保留期限後,系統會刪除資料。

Play Feature Delivery

收集到資料的使用情況 裝置中繼資料
應用程式版本
資料收集目的 收集到的資料會用於為裝置提供適當的模組,並在更新、備份及還原之後保留已安裝的模組。
資料加密 資料已加密。
資料分享 資料不會轉移給任何第三方。
資料刪除 過了固定的保留期限後,系統會刪除資料。

我們會請您在 Google Play「資料安全性」專區的表單中,說明應用程式收集、分享使用者資料的方式和安全性做法。雖然最好能夠盡量公開透明,但如何填答仍由您決定。