bundletool 工具使用详解

一、前言

    bundletool 是 Android Studio、Android Gradle 插件和 Google Play 用于构建 Android App Bundle 并将 App Bundle 转换为部署到设备的各种 APK 的底层工具。 bundletool 也可用作命令行工具,因此您可以自己构建 App Bundle,并模拟 Google Play 服务端构建应用程序 APK。

二、下载与配置bundletool

2.1 下载bundletool

    可以从 Github 上面下载 bundletool,下载地址: bundletool Github 下载

2.2 bundletool 配置

    因为下载的 bundletool 工具是一个 .jar 格式文件,因此运行需要先配置 Java 环境(这里就不再详细讲解)。使用命令行命令 java -jar bundletool-xxx.jar 即可运行,但是为了方便,可以编写一个脚本并配置环境变量,方便全局调用(本示例基于 Windows 系统)。

  1. 新建一个目录 (本文示例为:D:\Android\bundletool\),将下载的 bundletool-xxx..jar 文件拷贝进去;
  2. 在目录下新建一个文件(本文示例为:bundletool.bat),并在文件中添加内容 java -jar D:\Android\bundletool\bundletool-all-1.7.1.jar %* 注意,因为需要全局调用,这里需要引用jar的绝对路径,最后面的 %* 表示接收任意数量的参数
  3. 将目录(本文示例为:D:\Android\bundletool\)添加到环境变量的 Path 变量中,并保存;
  4. 打开命令行窗口(如果已经打开,需要关闭后重新打开新的窗口),就可以使用命令 bundletool 调用 bundletool 工具了。

三、bundletool 使用详解

3.1 bundletool 命令详解

    bundletool 包含了常用的命令,每个命令有自己的参数和标记,下面列出 bundletool 可用的命令:

命令名称说明备注
build-bundle将 zip 格式的 Bundle 模块文件集合,构建成 Android App Bundle(.aab)文件参考:构建 Android App Bundle
build-apks生成一个 APK 集合压缩包。压缩包内包含所有可能的分解 APK 和单独 APK, 或者针对已连接设备优化的 APK。参考:为 Android App Bundle 生成 APK 集合
extract-apks根据给定设备配置,从 APK 集合中提取安装到该配置设备的 APK参考:从 APK 集合中提取特定设备的 APK
get-device-spec获取已连接设备的配置,并将其输出到一个 JSON 文件中。参考:设备配置 JSON 文件的生成与使用
install-apks从 APK 集合中提取 APK 并安装到连接的设备上。安装会替换已存在的包。参考:将 APK 集合部署到连接的设备
install-multi-apks以原子方式将多个 APK 集中的 APK 和 APEX 安装到连接的设备。-
validate校验给定的 Android App Bundle 文件是否有效,并且输出相关信息。输出详细的文件信息。
dump以人可读的形式从 App Bundle 中打印文件或者提取值。-
get-size计算 APK 集合针对不同设备配置生成的 APK 的最小和最大的下载大小完整命令为 get-size total,参考:估算 APK 集合中 APK 的下载大小
version查看当前 bundletool 版本号-

说明:可以使用 bundletool help 查看命令帮助,使用 bundletool hlep command 查看对应命令的帮助。

3.2 构建 Android App Bundle

    如果你使用Android Studio开发,强烈建议你使用Android Studio IDE 和 Android Gradle 插件生成 App Bundle,因为使用 bundletool 在命令行生成 App Bundle 是极其复杂的步骤(首先要生成 proto 格式的清单和资源(使用 aapt2 编译并链接应用的资源),然后将这些清单和资源打包成 ZIP 文件(文件目录结构与 Android App Bundle 类似),最后使用 bundletool build-bundle --modules=base.zip --output=mybundle.aab 命令生成最终的 Android App Bundle文件(.aab))。然而,如果不是使用 Android Studio,比如持续构建服务器,就可以使用 bundletool 在命令行构建 App Bundle,并使用 jarsigner 对其进行签名。

注意事项:不能使用 apksigner 对 App Bundle 进行签名,要对 App Bundle 进行签名,请使用 jarsigner。

3.3 为 Android App Bundle 生成 APK 集合

    在构建 Android App Bundle 之后,可以使用 bundletool 工具在本地测试模拟 Google Play 是如何使用 App Bundle 生成 APK,以及这些 APK 在部署到设备时是怎样的一种行为方式。

    在 bundletool 从 App Bundle 中生成 APK 时,会将这些 APK 放在一个称之为 APK 集合的压缩包容器内,这个压缩包容器文件以 .apks 为后缀。从 App Bundle 中为应用支持的所有设备配置生成 APK 集合,使用 bundletool 的 build-apk 命令。如下示例所示:

bundletool build-apks --bundle=<your_app_bundle_path> --output=<output_apks_path>

    默认地,bundletool 工具在生成 apks 时,使用 Android 默认的调试签名文件(即 C:\Users\<用户名>\.android、debug.keystore)对生成的 APK 进行签名。当然,你可以指定自己的签名文件为生成的 APK 进行签名,执行如下格式命令(执行时确保命令及参数是单行):

bundletool build-apks --bundle=<your_app_bundle_path> --output=<output_apks_path> 
--ks=<keystore_file_path> 
--ks-pass=<pass:keystore_store_pass> | <file:keystore_store_pass_file_path> 
--ks-key-alias=<key_store_alias> 
--key-pass=<pass:keystore_key_pass> | <file:keystore_key_pass_file_path>

3.3.1 build-apks 命令使用参考

    bundletool build-apks
        --bundle=<bundle.aab>
        --output=<output.apks>
        [--aapt2=<path/to/aapt2>]
        [--adb=<path/to/adb>]
        [--connected-device]
        [--create-stamp]
        [--device-id=<device-serial-name>]
        [--device-spec=<device-spec.json>]
        [--device-tier=<low>]
        [--key-pass=<key-password>]
        [--ks=<path/to/keystore>]
        [--ks-key-alias=<key-alias>]
        [--ks-pass=<[pass|file]:value>]
        [--local-testing]
        [--max-threads=<num-threads>]
        [--min-v3-signing-api-version=<30>]
        [--mode=<default|universal|system|persistent|instant>]
        [--modules=<base,module1,module2>]
        [--optimize-for=<abi|screen_density|language|texture_compression_format|device_tier>]
        [--output-format=<apk_set|directory>]
        [--overwrite]
        [--stamp-key-alias=<stamp-key-alias>]
        [--stamp-key-pass=<stamp-key-password>]
        [--stamp-ks=<path/to/keystore>]
        [--stamp-ks-pass=<[pass|file]:value>]
        [--stamp-source=<stamp-source>]
        [--verbose]

3.3.2 build-apks 命令参数标记详解

    使用 bundletool 为 App Bundle 生成 APK 集合使用的是 build-apks 命令,下面将详细介绍该命令使用的参数:

参数标志必须参数说明
--bundle=path指定 App Bundle 文件的路径
--output=path指定输出 .apks 文件路径
--overwrite如果输出文件已经存在,覆盖旧文件。如果存在同名旧文件,没有此标记命令会执行失败。
--aapt2=path指定自定义的 aapt2 工具路径,不指定使用默认的 aapt2 版本
--ks=path指定签名文件路径,用于配置输出 APK 文件的签名文件,不指定使用 Android 默认调试签名,即 C:\Users\<用户名>\.android、debug.keystore
--ks-pass=pass:password
或者
--ks-pass=file:path_to_pwssword_file
指定签名文件的存储秘钥,指定了 --ks=path 时此项必须。如果使用字符串秘钥,使用 pass:password ,如果秘钥存储在文件中,使用 file:path_to_pwssword_file
--ks-key-alias=alias秘钥别名,指定了 --ks=path 时此项必须。
--key-pass=pass:password
或者
--key-pass=file:path_to_pwssword_file
指定签名别名秘钥,指定了 --ks=path 时此项必须。如果使用字符串秘钥,使用 pass:password ,如果秘钥存储在文件中,使用 file:path_to_pwssword_file
--connected-device指示 bundletool 工具根据已连接的设备的配置生成 APK 集合。如果不指定,bundletool 工具会根据应用支持的所有配置生成 APK 集合
--device-id=device_id指定已连接的设备。指定了 --connected-device 且有多个连接的设备时此项必须,可以使用 Android adb 工具 adb devices 查看已连接的设备的 ID
--device-spec=spec_json此参数用于指定目标设备的配置文件路径,配置文件是 JSON 格式文件,以 .json 为后缀。指定后只会生成配置文件对应的 APK 集合,关于设备配置文件的详细介绍参考:设备配置 JSON 文件的生成与使用
--mode=universal设置生成模式,如果您想要 bundletool 为 App Bundle 生成一个包含了所有应用代码和资源的单个 APK,请设置成 universal,生成的单个 APK 兼容应用支持的所有设备配置。生成模式默认值为 default

注意事项:
1. 如果指定了 --connected-device 或者 --device-spec=spec_json,只能使用默认值 default
2. bundletool 在 universal 模式下生成的单个 APK,只会包含在清单文件中使用 <dist:fusing dist:include="true"/> 指定的功能模块。


生成的单个 APK 包体会比针对指定设备配置生成的 APK 要大,但是单个 APK 更易于在测试者之间共享,因为他可以兼容多个设备,方便在不同的设备上安装测试。
--local-testing使用这个标志启用 App Bundle 用户本地测试, 本地测试支持在无需上传 Google Play 服务端的情况下实现快速、迭代的测试周期。

说明:在命令行中使用 bundletool help build-apks 可以查看相关的帮助信息。

3.4 将 APK 集合部署到连接的设备

    在生成 APK 集合(.apks 文件)之后,可以使用 bundletool 将 APK 集合部署到链接的设备上,bundletool 会根据连接设备对应配置选择需要安装 APK 文件并安装到设备上(使用 --mode=universal 生成的单个 APK 会将所有代码和资源安装到设备)。使用 install-apks 命令将 APK 集合部署到链接的设备上:

bundletool install-apks --apks=<your_apks_path>

注意事项:如果在使用 build-apks 命令生成 APK 集合时使用了 --local-testing 标志,为了确保本地测试能够正确进行,请使用 install-apks 安装的 APK。

3.4.1 install-apks 命令使用详解

 bundletool install-apks
        --apks=<archive.apks>
        [--adb=<path/to/adb>]
        [--additional-local-testing-files]
        [--allow-downgrade]
        [--allow-test-only]
        [--device-groups=<highRam,googlePixel>]
        [--device-id=<device-serial-name>]
        [--device-tier=<high>]
        [--modules=<base,module1,module2>]
        [--timeout-millis=<60000>]

3.4.2 install-apks 命令参数标记详解

参数标志必须参数说明
--apks=path指定 APK 集合(.apks)文件路径,改文件使用 build-apks 命令生成
--adb=path_to_adbadb 工具的路径,不指定时使用 ANDROID_HOME 或者 PATH 环境变量配置的,如果未在环境变量配置,必须在此标记指定 adb 工具路径。
--additional-local-testing-files需要额外放到本地测试目录的文件列表,这个标记仅在使用了 --local-testing 标记生成的 APK 集合有效
--allow-downgrade允许降级安装。如果指定,即使将要安装的 APK 集合版本号比已安装的版本号低,也能进行安装。
--allow-test-only如果指定,允许安装在清单文件中制定了 android:testOnly=true 的 APK 集合
--device-groups=device_groups指定设备所属的设备组。 该值用于将设备与正确的设备组模块相匹配,这个标记仅用于 App Bundle 按设备组条件分发功能模块的情况。多个设备组使用半角逗号隔开。
--device-id=device_id指定已连接的设备。指定了 --connected-device 且有多个连接的设备时此项必须,可以使用 Android adb 工具 adb devices 查看已连接的设备的 ID
--device-tier=<high>指定设备的层次,该值用于将设备与正确的设备层次模块相匹配,这个标记仅用于 App Bundle 按设备层次条件分发功能模的情况
--modules=modules_names指定需要安装的模块列表,使用 _ALL_ 指定安装所有模块。默认安装第一次安装是需要的模块(即非按需安装),需要注意的是依赖模块也会被提取,如果安装使用 --mode=universal 指定生成的 APK 集合,此标志无效
--timeout-millis=time-milli-seconds传入到 adb 工具的超时时长,单位:毫秒,默认值为 10 分钟(60000毫秒)

说明:在命令行中使用 bundletool help install-apks 可以查看相关的帮助信息。

3.5 为指定设备生成 APK 集合

    前面介绍到使用 bundletool 工具的 build-apks 生成 APK 集合,默认地是根据应用所支持的所有设备的配置生成 APK 集合,如果您不想生成包含支持所有设备配置的 APK 集合,可以仅针对已连接的设备配置生成 APK 集合。在 build-apks 命令中使用 --connected-device 选项标记即可(如果有多台已连接的设备,请使用 --device-id=device_id 指定设备,关于 build-apks 命令的参数标记请参考:build-apks 命令参数标记详解),如下示例所示:

bundletool build-apks --bundle=<your_app_bundle_path> --output=<output_apks_path> --connected-device

注意事项: 默认地,bundletool 工具在生成 apks 时,使用 Android 默认的调试签名文件对生成的 APK 进行签名,也可以使用 --ks=<keystore_file_path> --ks-pass=<pass:keystore_store_pass> | <file:keystore_store_pass_file_path> --ks-key-alias=<key_store_alias> --key-pass=<pass:keystore_key_pass> | <file:keystore_key_pass_file_path> 参数标记配置自己的签名。

3.5.1 设备配置 JSON 文件的生成与使用

    bundletool 可以为使用 JSON 文件声明的设备配置生成 APK 集合,使用 l 使用 get-device-spec 命令可获取已连接的设备的配置 JSON 文件,如下示例所示:

bundletool get-device-spec --output=output_file_path.json

获取到的配置文件内容如下示例所示:

{
  "supportedAbis": [
    "arm64-v8a",
    "armeabi-v7a",
    "armeabi"
  ],
  "supportedLocales": [
    "zh-TW",
    "zh-CN",
    "zh-HK",
    "en-US",
    "ja-JP",
    "ko-KR"
  ],
  "deviceFeatures": [
    "reqGlEsVersion=0x30002",
    "android.hardware.audio.low_latency"
  ],
  "screenDensity": 480,
  "sdkVersion": 29
}
3.5.1.1 get-device-spec 命令使用详解
bundletool get-device-spec
        --output=<device-spec.json>
        [--adb=<path/to/adb>]
        [--device-groups=<highRam,googlePixel>]
        [--device-id=<device-serial-name>]
        [--device-tier=<low>]
        [--overwrite]
3.5.1.1 get-device-spec 命令参数标记详解
参数标志必须参数说明
--output=output_file_path.json配置输出文件,JSON 格式文件
--adb=path_to_adbadb 工具的路径,不指定是使用 ANDROID_HOME 或者 PATH 环境变量配置的,如果未在环境变量配置,必须在此标记指定 adb 工具路径。
--device-groups=device_groups指定设备所属的设备组。 该值用于将设备与正确的设备组模块相匹配,这个标记仅用于 App Bundle 按设备组条件分发功能模块的情况。多个设备组使用半角逗号隔开。
--device-id=device_id指定已连接的设备。有多个连接的设备时此项必须,可以使用 Android adb 工具 adb devices 查看已连接的设备的 ID
--device-tier指定设备的层次,该值用于将设备与正确的设备层次模块相匹配,这个标记仅用于 App Bundle 按设备层次条件分发功能模的情况
--overwrite如果输出文件已经存在,覆盖旧文件。如果存在同名旧文件,没有此标记命令会执行失败。

3.5.2 手动创建设备配置 JSON 文件

    前面介绍了如何获取已连接设备的配置,从中我们可以了解到设备配置文件包含的信息,主要包含了以下几点:

  • supportedAbis:设备支持的 Abi(so 库)架构,字符串数组。
  • supportedLocales:设备当前添加支持的地区语言(设备中有可能继续添加支持的地区语言,也就是说此字段并不代表设备支持的所有地区语言),字符串数组。
  • deviceFeatures:设备支持的特性,字符串数组。
  • glExtensions:设备支持的OpenGL扩展,字符串数组。
  • screenDensity:屏幕密度,int 类型。
  • sdkVersion:设备系统版本(versionCode), int 类型。

    那么,设备配置 JSON 文件也可以手动创建,包含必要的信息即可,如下示例所示:

{
  "supportedAbis": ["arm64-v8a", "armeabi-v7a", "armeabi"],
  "supportedLocales": ["zh-CN", "en-US"],
  "screenDensity": 480,
  "sdkVersion": 28
}

注意事项: 手动创建设备配置 JSON 文件的时候,只需要针对需要的信息进行配置即可,并不要求每一项都必须有,没有配置的项目会进行兼容处理。

    手动创建的设备配置文件,可以在 build-apks 命令(参考:为 Android App Bundle 生成 APK 集合)或者 extract-apks 命令(参考:从 APK 集合中提取特定设备的 APK)中传入,获取对应设备配置的 APK。如下图所示:

设备配置对应的 APK 集合

3.5.3 从 APK 集合中提取特定设备的 APK

    bundletool 可以使用 extract-apks 命令从现有的 APK 集合中提取指定设备配置的 APK 子集。

bundletool extract-apks --apks=archive.apks --device-spec=device_config.json --output-dir=output_dir
  • 抽取结果示例:
    提取出来的 APK

注意事项: extract-apks 命令输出的是 APK 文件(多个 .apk 文件),而不是 APK 集合文件(.apks 压缩文件),所以 --output-dir 是一个目录。

3.5.3.1 extract-apks 命令使用详解
bundletool extract-apks
    --apks=<archive.apks>
    --device-spec=<device-spec.json>
    [--include-metadata]
    [--instant]
    [--modules=<base,module1,module2>]
    [--output-dir=<output-dir>]
3.5.3.2 extract-apks 命令参数标记详解
参数标志必须参数说明
--apks=<archive.apks>build-apks 命令生成的 APK 集合压缩包路径
--device-spec=<device-spec.json>设备配置 JSON 文件路径
--include-metadata如果添加此标记,将会在输出目录中多了一个 metadata.json 文件,这个文件包含抽取的 APK 相关信息
--instant如果添加此标记,只提取免安装模块的 APK,而不会提取可安装模块的 APK。
注意事项:如果不包含兼容 APK,无法提取免安装的 APK,命令执行失败。
--modules=<base,module1,module2>需要提取的模块列表,或者使用 _ALL_ 提取所有模块。默认情况下只会提取首次安装需要的模块。
--output-dir=<output-dir>输出文件存放目录。
注意事项:extract-apks 命令输出的是 APK 文件(多个 .apk 文件),而不是 APK 集合文件(.apks 压缩文件)。

3.6 估算 APK 集合中 APK 的下载大小

    APK 集合中的 APK 将经过压缩后通过网络传送。如需估算这些 APK 的下载大小,可使用 get-size total 命令:

3.6.1 get-size total 命令使用详解

    bundletool get-size total
        --apks=<archive.apks>
        --human-readable-sizes
        [--device-spec=<device-spec.json>]
        [--dimensions=<SDK,ABI,SCREEN_DENSITY,LANGUAGE,
            TEXTURE_COMPRESSION_FORMAT,DEVICE_TIER,ALL>]
        [--instant]
        [--modules=<base,module1,module2>]

3.6.2 get-size total 参数标记详解

参数标志必须参数说明
--apks=<archive.apks>build-apks 命令生成的 APK 集合压缩包路径
--human-readable-sizes如果添加此标记,输出人可读性的大小(没有添加时单位为 Bit),比如:10MB。
--device-spec指定设备配置,如果制定了此项,将获取针对该设备配置生成的 APK 下载大小,可通过 get-device-spec 命令获取设备信息,参考:设备配置 JSON 文件的生成与使用
--dimensions指定要扩展输出 APK 大小的维度,指定输出维度之后,将会以维度(或者维度组合)扩展输出 APK 大小信息,可使用的维度有:SDK(目标SDK版本)、ABI(ABI架构)、SCREEN_DENSITY(屏幕密度)、LANGUAGE(语种)、TEXTURE_COMPRESSION_FORMAT(纹理压缩格式)、DEVICE_TIER(设备层)、ALL(全部维度),可同时指定多个维度。
--instant如果指定该标记,将会输出免安装模块的大小(而不是可安装 APK 的大小),默认不指定
--modules指定运行此命令获取的报告包含的模块列表(默认是首次安装需要下载的所有模块),需要注意的是,依赖模块也将会被计算在内。设置此标志时,我们会忽略独立 APK 进行大小计算。

说明:在命令行中使用 bundletool help get-size 可以查看相关的帮助信息。

  • 示例
bundletool get-size total --apks=F:\demo-hk-release.apks --human-readable-sizes --dimensions=SDK
  • 结果输出
SDK,MIN,MAX
19-20,7.76 MB,7.81 MB
21-,7.64 MB,7.72 MB
  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值