bundletool

bundletool 是 Android Gradle 外掛程式 Android Studio 和 Google Play 用於建構 Android App Bundle 的基礎工具。bundletool 可以將應用程式套件轉換為部署至裝置的各種 APK。

Android SDK 套件 (ASB) 和套件的 APK 都使用 bundletool 建構而成。您也可以把它當做一種指令列工具,用來自行建構應用程式套件和 SDK 套件,並可重新建立下列兩者的 Google Play 伺服器端版本:應用程式 APK 或支援執行階段的 SDK APK。

下載 bundletool

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

建構並測試應用程式套件

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

建構應用程式套件

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

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

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

建構 Android App Bundle 後,測試 Google Play 用以產生 APK 的結果,以及這些 APK 部署到裝置後的表現。

測試應用程式套件的方式有兩種:

本節說明如何使用 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 指令時,您可以設定的各種標記和選項:

表 1. 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 將模式設為 universal。如果希望 bundletool 僅建構一個 APK,包含您應用程式的所有程式碼及資源,並與應用程式支援的所有裝置相容,請使用此選項。

附註: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 選項指定僅針對連結裝置,如下列指令所示。如果您連接多部裝置,請加入 --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 指令的行為:

表 2. 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 套件依附元件建構應用程式套件

藉由使用 Android SDK 套件 (ASB) 依附元件,您可以透過指令列建構 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 套件依附元件,針對不支援 SDK 程式庫的裝置產生 APK

Android 13 以下版本的裝置不支援安裝 SDK 程式庫,也無法在 SDK 執行階段中執行這些程式庫。Bundletool 會隱藏回溯相容性的複雜性,當您透過 --sdk-bundles--sdk-archives 選項執行 bundletool build-apks 時,從同一個應用程式套件產生多個 APK 變化版本。多個變化版本會指定具備不同功能的裝置:

  • 系統會為較新的裝置提供變化版本,其中 SDK 是以應用程式獨立的套件安裝,且應用程式 APK 不包含任何 SDK 內容。
  • 舊型裝置會有多個變化版本,其中 SDK APK 會新增至應用程式 APK,並以額外 APK 分割的形式加入。SDK APK 屬於應用程式套件。在這種情況下,系統會在裝置的應用程式執行階段中模擬 SDK 執行階段。

與沒有 SDK 依附元件的應用程式套件產生 APK 的方式類似,bundletool extract-apksbundletool install-apks 會針對已連結的裝置,或提供的裝置設定,從最佳變化版本傳回經過篩選的 APK。

針對進階用途,只想從適用於舊版裝置的特定應用程式 SDK 封存產生 APK 分割,請使用 bundletool build-sdk-apks-for-app 指令,如下所示:

bundletool build-sdk-apks-for-app --app-properties=app-properties.json \
    --sdk-archive=sdk.asar --output=sdk.apks

app-properties 檔案應包含 runtime_enabled_sdk_config.proto 檔案中所述的欄位。app-properties 檔案看起來會像這樣:

{
  "package_name": "com.my.app",
  "version_code": 1234,
  "min_sdk_version": 21,
  "resources_package_id": 0x7e
}

bundletool build-sdk-apks-for-app 指令會產生應用程式 APK 子集,對應應用程式套件名稱下的 SDK 內容。您可以將這些 APK 與包含該應用程式內容的其他 APK 結合。舉例來說,假設您以個別且逐步的方式建構這些元件,然後同時安裝在不支援 SDK 執行階段的裝置上。

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

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

建構 SDK 套件

您可以透過指令列建構 ASB,然後再用 jarsigner 簽署。

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

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

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

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

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

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 指令時,您可以設定的各種標記和選項。

表 3. bundletool build-sdk-bundle 指令的選項

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

從 SDK 套件產生 APK

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

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

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

如果想把 ASB 部署到裝置上,您需要加入應用程式的簽署資訊,如以下指令所示:

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 指令時,您可以設定的各種標記和選項。

表 4. 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 APK 的大小

這部分您可以按照以下章節所述步驟操作:將 APK 部署到連結裝置從現有的 APK 套組擷取裝置專用的 APK測量 APK 套組的 APK 下載大小

從 SDK 套件產生 SDK 封存

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

建構 ASB 之後,您可以利用 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 指令時,您可以設定的各種標記和選項。

表 5. 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 套件 (ASB) 是經過簽署的 ZIP 檔案,含有 .asb 副檔名。SDK 程式碼和資源的組織方式和 APK 類似。ASB 也有幾種設定檔,這些設定檔可以用來輔助產生可供安裝的 APK。

圖 1. Android SDK 套件內容。

以下清單會詳細說明部分 ASB 檔案:

  • 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,請觀看應用程式套件:使用 bundletool 和 Play 管理中心測試套件