bundletool

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

bundletool 是 Android Gradle 外掛程式 Android Studio 及 Google Play 用於建構 Android App Bundle 的基礎工具,會將應用程式套件轉換為部署至裝置的各種 APK。Android SDK 套件和套件的 APK 也都使用 bundletool 建構而成。您也可以把 bundletool 當做指令列工具運用,以便自行建構應用程式套件和 SDK 套件,並可重新建立下列兩者的 Google Play 伺服器端版本:應用程式 APK,和支援執行階段的 SDK APK。

下載 bundletool

如果您尚未從 GitHub 存放區下載 bundletool 檔案,請先完成這項操作。

建構並測試應用程式套件

您可以運用 Android Studio 或 bundletool 指令列工具建構 Android App Bundle,並測試用這個應用程式套件產生的 APK。

建構應用程式套件

您應使用 Android Studio 和 Gradle 適用的 Android 外掛程式,建構並簽署 Android App Bundle。然而,如果無法使用 IDE,例如您使用的是持續建構伺服器,那麼您也可以透過指令列建構應用程式套件然後使用 jarsigner 簽署。

如要進一步瞭解如何使用 bundletool 建構應用程式套件,請參閱使用 bundletool 建構應用程式套件

透過應用程式套件產生一組 APK

建構 Android App Bundle 後,您必須測試 Google Play 使用 Android App Bundle 產生 APK 的情形,以及這些 APK 部署到裝置上之後的行為。建議您考慮透過 bundletool 指令列工具在本機端測試應用程式套件,以及透過 Google Play 將套裝組合上傳至 Play 管理中心,並使用測試群組。本節說明如何使用 bundletool 在本機測試您的應用程式套件。

bundletool 從您的應用程式套件產生 APK 時,會將 APK 納入名為「APK 集的封存檔案」容器,而容器會使用 .apks 副檔名。如果希望從應用程式套件產生的 APK 集可以適用您應用程式支援的所有裝置設定,請使用 bundletool build-apks 指令,如下所示。

bundletool build-apks --bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks

如要將 APK 部署到裝置,您必須一併加入應用程式的簽署資訊,如下方指令所示。如未指定簽署資訊,bundletool 會嘗試使用偵錯金鑰簽署您的 APK。

bundletool build-apks --bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks
--ks=/MyApp/keystore.jks
--ks-pass=file:/MyApp/keystore.pwd
--ks-key-alias=MyKeyAlias
--key-pass=file:/MyApp/key.pwd

下表詳細說明了在使用 bundletool build-apks 指令時,您可以設定的各種標記和選項。

標記 說明
--bundle=path (必要) 指定您透過 Android Studio 建構的應用程式套件路徑。詳情請參閱「建構專案」
--output=path (必要) 指定輸出「.apks」檔案的名稱,其中包含應用程式的所有 APK 構件。如要在裝置上測試這個檔案中的構件,請參閱如何將 APK 部署至已連結的裝置的章節。
--overwrite 如要覆寫使用 --output 選項指定的相同路徑的任何現有輸出檔案,請加入此標記。如果您未提供這個標記,且輸出檔案已存在,您會收到建構錯誤。
--aapt2=path 指定 AAPT2 的自訂路徑。 根據預設,bundletool 包含自己的 AAPT2 版本。
--ks=path 指定用來簽署 APK 的部署 KeyStore 路徑。這個標記是選用的。如未提供,bundletool 會使用偵錯簽署金鑰簽您的 APK。
--ks-pass=pass:password

--ks-pass=file:/path/to/file
指定 KeyStore 密碼。如果您要以純文字指定密碼,請使用 pass: 進行認證。 如要將路徑傳送至含有密碼的檔案,請使用 file: 進行認證。如果您使用 --ks 標記指定 KeyStore,但沒有指定 --ks-passbundletool 會提示您透過指令列輸入密碼。
--ks-key-alias=alias 指定要使用的簽署金鑰別名。
--key-pass=pass:password

--key-pass=file:/path/to/file
指定簽署金鑰的密碼。如果您要以純文字指定密碼,請使用 pass: 進行認證。 如要將路徑傳送至含有密碼的檔案,請使用 file: 進行認證。

如果這組密碼與 KeyStore 本身的密碼相同,請略過這個標記。

--connected-device 指示 bundletool 建構以已連結裝置設定為目標的 APK。如果您未提供這個標記,bundletool 會針對應用程式支援的所有裝置設定產生 APK。
--device-id=serial-number 如果您有多部已連結的裝置,請使用此標記來指定您要部署應用程式的裝置序號。
--device-spec=spec_json 使用標記提供 .json 檔案的路徑,以指定您要指定的裝置設定。詳情請參閱「建構及使用裝置規格 JSON 檔案」一節。
--mode=universal 如果希望 bundletool 僅建構包含您應用程式所有程式碼及資源的單一 APK,以便該 APK 與您在應用程式支援的所有裝置相容,請將模式設為 universal

附註:bundletool 只有功能模組在通用 APK 的資訊清單中指定 <dist:fusing dist:include="true"/>。詳情請參閱功能模組資訊清單

請注意,這些 APK 比針對特定裝置設定最佳化的 APK 還要大。然而,您可以輕鬆與內部測試人員分享資訊,例如,他們可以利用多種裝置設定來測試應用程式。

--local-testing 使用這項標記來啟用應用程式套件,進行本機測試。 本機測試可讓您快速上傳至 Google Play 伺服器,以反覆進行測試。

如需如何使用 --local-testing 標記測試模組安裝的範例,請參閱本機測試模組安裝

將 APK 部署到已連結的裝置

產生一組 APK 後,bundletool 即可從該集合部署正確的 APK 組合到已連結的裝置。

舉例來說,如果您的已連結的裝置搭載 Android 5.0 (API 級別 21) 或以上版本,bundletool 會推送基礎 APK、功能模組 APK 和設定 APK,以便在裝置上執行應用程式。或者,如果您的已連結的裝置搭載的是 Android 4.4 (API 級別 20) 或以下版本,則 bundletool 會尋找相容的多個 APK,並將其部署至您的裝置。

如要從 APK 集部署應用程式,請使用 install-apks 指令並使用 --apks=/path/to/apks 標記指定 APK 設定的路徑,如下所示 (如果您連接多部裝置,請加入 --device-id=serial-id 標記來指定目標裝置)。

bundletool install-apks --apks=/MyApp/my_app.apks

產生裝置專用的一組 APK

如果您不想為應用程式支援的所有裝置設定建構一組 APK,可以使用 --connected-device 選項建構僅指定已連結的裝置設定 APK,如下所示 (如果您連接多部裝置,請加入 --device-id=serial-id 標記來指定目標裝置)。

bundletool build-apks --connected-device
--bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks

產生並使用裝置規格 JSON 檔案

bundletool 可以產生指定 JSON 檔案所指定的裝置設定的 APK 組合。如要先為已連結的裝置產生 JSON 檔案,請執行下列指令:

bundletool get-device-spec --output=/tmp/device-spec.json

bundletool 會在工具所在的目錄中建立裝置的 JSON 檔案。您可以將此檔案傳送至 bundletool 以產生一組指定該 JSON 檔案所描述設定的 APK,如下所示:

bundletool build-apks --device-spec=/MyApp/pixel2.json
--bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks

手動建立裝置規格 JSON

如果您無法存取要建構指定 APK 的裝置 (例如好友想要用您目前沒有的裝置試用應用程式),您可以按照下列格式手動建立 JSON 檔案:

{
  "supportedAbis": ["arm64-v8a", "armeabi-v7a"],
  "supportedLocales": ["en", "fr"],
  "screenDensity": 640,
  "sdkVersion": 27
}

接著,請按照上一節的說明,將這個 JSON 傳送至 bundle extract-apks 指令。

從現有的 APK 組合中擷取裝置專用的 APK

如果您已設定現有 APK,且想要從指定特定裝置設定的 APK 子集擷取,您可以使用 extract-apks 指令並指定裝置規格 JSON,如下所示:

bundletool extract-apks
--apks=/MyApp/my_existing_APK_set.apks
--output-dir=/MyApp/my_pixel2_APK_set.apks
--device-spec=/MyApp/bundletool/pixel2.json

評估 APK 組合中的 APK 下載大小

如要測量 APK 組合中透過 Wi-Fi 無線提供的預估 APK 下載大小,請使用 get-size total 指令:

bundletool get-size total --apks=/MyApp/my_app.apks

您可以使用下列標記修改 get-size total 指令的行為:

標記 說明
--apks=path (必要) 指定現有 APK 組合檔案的下載路徑大小。
--device-spec=path 指定裝置規格檔案的路徑 (來自 get-device-spec 或手動建構),以供比對。 您可以指定部分路徑來評估一組設定。
--dimensions=dimensions 指定在計算大小預估值時所採用的維度。可接受以逗號分隔的清單,包含 SDKABISCREEN_DENSITYLANGUAGE。如要測量所有維度,請指定 ALL
--instant 測量免安裝即用 APK 的下載大小,而非安裝專用的 APK。根據預設,bundletool 會測量可安裝的 APK 下載大小。
--modules=modules 指定在 APK 中設定要納入考量的模組清單,並以半形逗號分隔。bundletool 指令會自動包含指定組合的任何相依模組。根據預設,指令會計算在首次下載期間安裝的所有模組的下載大小。

使用 SDK 套件依附元件建構並測試應用程式套件 (實驗功能)

藉由使用 bundletool,您就能用 Android SDK 套件依附元件建構 Android App Bundle,並測試從這個套件產生的 APK。

使用 SDK 套件依附元件建構應用程式套件

藉由使用 Android SDK 套件依附元件,您可以透過指令列建構 Android App Bundle,然後再用 jarsigner 簽署。

每個應用程式套件模組內都有一個模組通訊協定緩衝區 (.pb) 檔案:runtime_enabled_sdk_config.pb。這個檔案內有 應用程式套件模組所依附的 SDK 清單。如果想瞭解這個檔案的完整定義,請參閱 runtime_enabled_sdk_config.proto 檔案。

若要用 SDK 套件依附元件建構應用程式套件,請參閱同一份指南瞭解如何使用 bundletool 建構應用程式套件,不過這次請為每個內有編譯程式碼和資源的模組 ZIP 檔案新增 runtime_enabled_sdk_config.pb 檔案。

runtime_enabled_sdk_config.pb 檔案內的重要欄位:

  • 憑證摘要:簽署 SDK APK 的金鑰憑證 SHA-256 摘要。這和 Android SDK 封存格式SdkMetadata.pb 檔案內憑證互相對應。

  • 資源套件 ID:當產生 APK 以便將 SDK 嵌入應用程式時,這個 SDK 內的所有資源都會重新對應到的套件 ID。這個項目可以啟用回溯相容性。

SDK 只能在一個模組內;如果有多個模組都需要依附同一個 SDK,您應該複製並移動這個依附元件到基本模組內。不同模組無法依附 SDK 的不同版本。

使用 SDK 套件依附元件從應用程式套件產生 APK

若要從應用程式套件產生 APK,請按照「透過應用程式套件產生一組 APK」或「產生裝置專用的一組 APK」的步驟進行操作,不過這次您應該以應用程式依附的 SDK 提供 bundletool build-apks 指令。提供這些 SDK 時,可以使用 SDK 套件格式或 SDK 封存格式。

加入 --sdk-bundles 標記即可將 SDK 提供為 SDK 套件,如下所示:

bundletool build-apks --bundle=app.aab --sdk-bundles=sdk1.asb,sdk2.asb \
    --output=app.apks

加入 --sdk-archives 標記即可將 SDK 提供為 SDK 封存,如下所示:

bundletool build-apks --bundle=app.aab --sdk-archives=sdk1.asar,sdk2.asar \
    --output=app.apks

建構並測試 SDK 套件 (實驗功能)

您可以使用 bundletool 建構 Android SDK 套件,並測試產生安裝和發布所需的檔案。

建構 SDK 套件

您可以透過指令列建構 Android SDK 套件 (ASB),然後再用 jarsigner 簽署。

若要建構 SDK 套件,請按以下步驟操作:

  1. 按照以下和應用程式套件相同的步驟操作,以便用 proto 格式產生 SDK 套件的資訊清單和資源

  2. 將 SDK 的編譯程式碼和資源封裝到基本 ZIP 檔案內,如同應用程式套件的使用方式。

  3. 產生符合 Android SDK 套件規格文件說明格式的 SdkModulesConfig.pb.json 檔案和 SdkBundleConfig.pb.json 檔案。

  4. 使用 bundletool build-sdk-bundle 指令建構 SDK 套件,如下所示:

bundletool build-sdk-bundle --sdk-bundle-config=SdkBundleConfig.pb.json \
    --sdk-modules-config=SdkModulesConfig.pb.json \
    --modules=base.zip --output=sdk.asb

下表詳細說明了在使用 bundletool build-sdk-bundle 指令時,您可以設定的各種標記和選項。

標記 說明
--modules (必要) 您想用來建構最終 Android SDK 套件的模組檔案。
--output (必要) 欲建構 Android SDK 套件的路徑。
--sdk-modules-config (必要) 說明 SDK 模組設定的 JSON 檔案路徑。如果想瞭解如何設定 JSON 檔案格式,請參閱 Android SDK 套件規格文件
--sdk-bundle-config 說明 SDK 套件設定的 JSON 檔案路徑。如果想瞭解如何設定 JSON 檔案格式,請參閱 Android SDK 套件規格文件
--metadata-file 在 Android SDK 套件內說明要納入並當做中繼資料使用的檔案。標記值使用的格式為 <bundle-path>:<physical-file>,其中 <bundle-path> 代表 SDK 套件中繼資料目錄內的檔案位置,而 <physical-file> 代表內含要儲存的原始資料的現有檔案。您可以重複使用這個標記。
--overwrite 設定後,便會覆寫所有之前就有的輸出內容。

從 SDK 套件產生 APK

建構 Android SDK 套件之後,您可以利用 bundletool build-sdk-apks 指令產生 APK,然後即可在本機測試 SDK 套件,如以下程式碼所示。

bundletool 從您的 SDK 套件產生 APK 時,系統會將 APK 包含在名為「APK 集的封存檔案」的容器中,而容器會使用 .apks 副檔名。bundletool 會從 SDK 套件產生一個獨立 APK,這個 APK 會指定所有裝置設定。

bundletool build-sdk-apks --sdk-bundle=sdk.asb --output=sdk.apks

如果想把 ASB 部署到裝置上,您需要加入應用程式的簽署資訊,如以下指令所示:如果未提供簽署資訊,bundletool 會嘗試為您用偵錯金鑰簽署 APK。

bundletool build-sdk-apks --sdk-bundle=sdk.asb --output=sdk.apks \
    --ks=keystore.jks \
    --ks-pass=file:/keystore.pwd \
    --ks-key-alias=KeyAlias \
    --key-pass=file:/key.pwd

下表詳細說明了在使用 bundletool build-sdk-apks 指令時,您可以設定的各種標記和選項。

標記 說明
--sdk-bundle (必要) SDK 套件路徑。必須使用 .asb 副檔名。
--output (必要) 應該建立 APK 集封存的預設路徑。另外,如果您使用 --output-format=DIRECTORY,這應該也是指向儲存系統所生 APK 的目錄路徑。
--ks 應該用來簽署系統所生 APK 的 KeyStore 所屬路徑。
--ks-key-alias 在 KeyStore 裡使用的金鑰別名,這會用來簽署系統產生的 APK。
--key-pass 在 KeyStore 裡的金鑰密碼,這會用來簽署系統產生的 APK。如果您要以明文傳遞密碼,必須在該值前面加上 pass:,例如 pass:qwerty。如果密碼位於檔案第一行,您必須在該值前面加上 file:,例如 file:/tmp/myPassword.txt。如果您未設定這個標記,系統會嘗試使用 KeyStore 密碼。如果失敗了,指令列終端機會要求您輸入密碼。
--ks-pass 用來簽署系統所生 APK 的 KeyStore 密碼。如果您要以明文傳遞密碼,必須在該值前面加上 pass:,例如 pass:qwerty。如果密碼位於檔案第一行,您必須在該值前面加上 file:,例如 file:/tmp/myPassword.txt。如果您未設定這個標記,指令列終端機會要求您輸入密碼。
--aapt2 要使用的 AAPT2 二進位檔路徑。
--output-format 指定系統產生的 APK 輸出格式。預設值為 APK_SET,會輸出 APK 到建立的 APK 集封存內。如果設為 DIRECTORY,則會輸出 APK 到 --output 指定的目錄內。
--verbose 設定之後,標準輸出內容會列印出執行指令的額外資訊。
--version-code SDK 版本代碼。這是 Android 平台用來安裝 APK 的版本代碼,「並非」SDK 版本。可設為任意值。如果未設定,則預設值為 0。
--overwrite 設定後,便會覆寫所有之前就有的輸出內容。

從 SDK 套件產生 SDK 封存

把 Android SDK 套件上傳道發布頻道 (例如 Google Play) 之後,Android SDK 套件便會轉換為 Android SDK 封存 (.asar),以便透過 Maven 發布給應用程式開發人員。如果想進一步瞭解格式詳情,請參閱 SDK 封存格式規格文件

建構 Android SDK 套件之後,您可以利用 bundletool build-sdk-asar 指令測試在本機產生 Android SDK 封存,如以下程式碼所示。

bundletool build-sdk-asar --sdk-bundle=sdk.asb --output=sdk.asar \
    --apk-signing-key-certificate=keycert.txt

下表詳細說明了在使用 bundletool build-sdk-asar 指令時,您可以設定的各種標記和選項。

標記 說明
--apk-signing-key-certificate (必要) 簽署憑證的 SDK APK 路徑。這個憑證和您用 build-sdk-apks 指令簽署 APK 時所用的金鑰相對應。
--output (必要) 應該建立 .asar 檔案的路徑。
--sdk-bundle (必要) SDK 套件路徑。必須使用 .asb 副檔名。
--overwrite 設定後,便會覆寫所有之前就有的輸出內容。

支援執行階段的 SDK 格式 (實驗功能)

支援執行階段的 SDK 帶來兩種 Android 檔案格式:用來將支援執行階段的 SDK 發布到應用程式商店的 Android SDK 套件 (.asb),以及用來在 Maven 發布支援執行階段的 SDK 的 Android SDK 封存 (.asar)。

Android SDK 套件格式

SDK 套件是支援執行階段的 SDK 的發布格式。其中含有所有 SDK 程式碼和資源,包括 SDK 依附的所有程式庫程式碼。其中並無其他 SDK 依附的支援執行階段的 SDK 的程式碼和資源。

Android SDK 套件是經過簽署的 ZIP 檔案,含有 .asb 副檔名。SDK 程式碼和資源的組織方式和 APK 類似。ASB 也有幾種設定檔,這些設定檔可以用來輔助產生可供安裝的 APK。

圖 1. Android SDK 套件內容。

以下清單會詳細說明部分 Android SDK 套件檔案:

  • SdkBundleConfig.pb:proto 格式的設定檔,其中含有 SDK 依附的所有支援執行階段的 SDK。完整定義請參見 sdk_bundle_config.proto 檔案。

  • modules.resm:內含所有用來從 SDK 產生 APK 所需資料的 ZIP 檔案。

  • SdkModulesConfig.pb:proto 格式的設定檔。這個檔案內含 SDK 名稱、版本,以及架構 SDK 進入點的類別名稱 (SandboxedSdkProvider)。完整定義請參見 sdk_modules_config.proto 檔案。

  • base/:含有 SDK 程式碼和資源的單一模組。

    • manifest/:proto 格式的 SDK 資訊清單。
    • dex/:DEX 格式的編譯程式碼。您可以提供多個 DEX 檔案。
    • res/lib/assets/:這些目錄與一般 APK 中的目錄相同。當系統為 SDK 產生 APK 時,會保留這些目錄的路徑。
    • root/:這個目錄會儲存之後要移到 SDK APK 根層級的檔案。舉例來說,這個目錄內可能會有 SDK 載入 Class.getResource() 方法時所使用的 Java 資源。這個目錄中的路徑也會保留下來。
    • BUNDLE-METADATA:這個目錄含有中繼資料檔案,其中包含工具或應用程式商店會用到的資訊。這類中繼資料檔案可能包括 ProGuard 對應,以及 SDK DEX 檔案的完整清單。這個目錄中的檔案不會封裝至 SDK 的 APK 中。

Android SDK 封存格式

Android SDK 封存是在 Maven 發布支援執行階段的 SDK 時所使用的格式。這個 ZIP 檔案,含有 .asar 副檔名。其中含有所有應用程式建構工具用來產生依附支援執行階段的 SDK 的 Android App Bundle 所需的資訊。

圖 2。 Android SDK 封存套件內容。

以下清單會詳細說明部分 Android SDK 套件檔案:

  • SdkMetadata.pb:這是 proto 格式的設定檔,內含 SDK 名稱、版本,以及金鑰憑證摘要;上述金鑰是用來簽署針對此 SDK 所產生的 APK。完整定義請參見 sdk_metadata.proto 檔案。

  • modules.resm:內含所有用來從 SDK 產生 APK 所需資料的 ZIP 檔案。這和 Android SDK 套件內的 .resm 檔案相同。

  • AndroidManifest.xml:文字 XML 格式的 SDK 資訊清單檔案。

其他資源

如要進一步瞭解如何使用 bundletool,請嘗試下列資源。

程式碼研究室

  • 第一個 Android App Bundle:這個程式碼研究室可探索 Android App Bundle 的基本原則,並說明如何透過 Android Studio 快速開始建構應用程式。這個程式碼研究室也會探索如何使用 bundletool 測試應用程式套件。