一、bundletoo 介绍
bundletool
是一种底层工具,可供 Android Studio、Android Gradle 插件和 Google Play 用于构建 Android App Bundle 文件并将 app bundle 转换为部署到设备的各种 APK。您也可以将 bundletool
作为一种命令行工具,用于自行构建 app bundle 和重新创建应用 APK 的 Google Play 服务器端 build。
二、下载与配置
命令别名配置
mac 使用alias(别名) : https://www.jianshu.com/p/a3b5da56e5ba
因为下载的 bundletool
工具是一个 .jar
格式文件,因此运行需要先配置 Java 环境
。使用命令java -jar bundletool-xxx.jar
即可运行,
为了方便,可以编写一个脚本并配置环境变量,方便全局调用
-
Windows 系统
- 新建一个目录(示例:
D:\Android\bundletool\
),将下载的bundletool-xxx..jar
文件复制进去; - 在目录下新建一个文件(示例:
bundletool.bat
),并在文件中添加内容java -jar D:\Android\bundletool\bundletool-all-1.7.1.jar %*
,最后面的%*
表示接收任意数量的参数; - 将目录(示例:
D:\Android\bundletool\
)添加到环境变量的Path
变量中,并保存 - 打开命令行窗口(如果已经打开,需要关闭后重新打开新的窗口),就可以使用命令
bundletool
调用bundletool
工具了
- 新建一个目录(示例:
Mac
设置 alias 别名
alias bundleTool="java -jar /Users/**/Android/Tools/bundletool-all-1.8.2.jar"
三、bundletool 使用详解
3.1 bundletool 命令详解
bundletool
包含了常用的命令,每个命令有自己的参数和标记,下面列出 bundletool
可用的命令:
命令名称 | 说明 | 备注 |
---|---|---|
build-bundle |
将 zip 格式的 Bundle 模块文件集合,构建成 Android App Bundle(.aab )文件 |
参考:构建Android App Bundle |
build-apks |
生成一个 APK 集合压缩包。压缩包内包含所有可能的分解 APK 和单独 APK, 或者针对已连接设备优化的 APK | 参考: 生成一组 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 total |
计算 APK 集合针对不同设备配置生成的 APK 的最小和最大的下载大小 | 参考:估算 APK 集中的 APK 的下载大小 |
version |
查看当前 bundletool 版本号 | - |
说明:可以使用
bundletool help
查看命令帮助,使用bundletool hlep command
查看对应命令的帮助。
3.2 构建Android 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开发,可以使用Android Studio IDE 和 Android Gradle 插件生成 App Bundle
3.3 生成 APK 集合
可参考官网:从 app bundle 生成一组 APK
在 bundletool
从 App Bundle 中生成 APK 时,会将这些 APK 放在一个称之为 APK 集合的压缩包容器内,这个压缩包容器文件以 .apks
为后缀。从 App Bundle 中为应用支持的所有设备配置生成 APK 集合,使用 bundletool
的 build-apk
命令
bundletool build-apks --bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks
默认bundletool 工具在生成 apks
时,使用 Android 默认的调试签名文件(即 .android/debug.keystore
)对生成的 APK 进行签名。当然,你可以指定自己的签名文件为生成的 APK 进行签名,执行如下格式命令(执行时确保命令及参数是单行):
bundletool build-apks --bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks
--ks=/MyApp/keystore.jks
--ks-pass=<file:/MyApp/keystore.pwd> 或者<pass:keystore的pwd>
--ks-key-alias=MyKeyAlias
--key-pass=file:/MyApp/key.pwd 或者<pass:keystore alias的pwd>
注意: 输入密码时要以
pass:
开头
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]
命令参数标记详解
参数标志 | 必须参数 | 说明 |
---|---|---|
--bundle=path |
是 | App Bundle 文件的路径 |
--output=path |
是 | 输出 .apks 文件路径 |
--overwrite |
否 | 如果输出文件已经存在,覆盖旧文件 如果存在同名旧文件,没有此标记命令会执行失败 |
--aapt2=path |
否 | 指定自定义的 aapt2 工具路径,不指定使用默认的 aapt2 版本 |
--ks=path |
否 | 指定签名文件路径,用于配置输出 APK 文件的签名文件,不指定使用 Android 默认调试签名,即 .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 部署到连接的设备
生成 APK 集合(.apks
文件)之后,可以使用 bundletool 将 APK 集合部署到链接的设备上,bundletool 会根据连接设备对应配置选择需要安装 APK 文件并安装到设备上(使用 --mode=universal
生成的单个 APK 会将所有代码和资源安装到设备)。使用install-apks
命令将 APK 集合部署到链接的设备上:
bundletool install-apks --apks=/MyApp/my_app.apks
如果在使用
build-apks
命令生成 APK 集合时使用了--local-testing
标志,为了确保本地测试能够正确进行,请使用install-apks
安装的 APK
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>]
install-apks
命令参数详解
参数标志 | 必须参数 | 说明 |
---|---|---|
--apks=path |
是 | 指定 APK 集合(.apks )文件路径,该文件使用 build-apks 命令生成 |
--adb=path_to_adb |
否 |
adb 工具的路径,不指定时使用 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 集合
参考官网链接:生成设备专用 APK 集
使用 bundletool 工具的 build-apks
生成 APK 集合,默认地是根据应用所支持的所有设备的配置生成 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 文件
参考官网链接:生成并使用设备规范 JSON 文件
bundletool
可以为使用 JSON 文件声明的设备配置生成 APK 集合, 使用 get-device-spec
命令可获取已连接的设备的配置 JSON 文件
bundletool get-device-spec --output=/tmp/device-spec.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
}
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]
get-device-spec
命令参数详解
参数标志 | 必须参数 | 说明 |
---|---|---|
--output=output_device_spec.json |
是 | 配置输出文件,JSON 格式文件 |
--adb=path_to_adb |
否 |
adb 工具的路径,不指定是使用 ANDROID_HOME 或者 PATH 环境变量配置的,如果未在环境变量配置,必须在此标记指定 adb 工具路径 |
--device-groups=device_groups |
否 | 指定设备所属的设备组。 该值用于将设备与正确的设备组模块相匹配,这个标记仅用于 App Bundle 按设备组条件分发功能模块的情况。多个设备组使用半角逗号 隔开 |
--device-id=device_id |
否 | 指定已连接的设备。有多个连接的设备时此项必须,可以使用 Android adb 工具 adb devices 查看已连接的设备的 ID |
--device-tier |
否 | 指定设备的层次,该值用于将设备与正确的设备层次模块相匹配,这个标记仅用于 App Bundle 按设备层次条件分发功能模的情况 |
--overwrite |
否 | 如果输出文件已经存在,覆盖旧文件。如果存在同名旧文件,没有此标记命令会执行失败 |
手动创建设备规范 JSON
参考官网链接:手动创建设备规范 JSON
如果无法访问要针对其构建目标 APK 集的设备(例如,朋友想通过您手头没有的设备试用您的应用),则可以使用以下格式手动创建 JSON 文件:
{
"supportedAbis": ["arm64-v8a", "armeabi-v7a"],
"supportedLocales": ["en", "fr"],
"screenDensity": 640,
"sdkVersion": 27
}
设备配置文件包含的信息主要包含了以下几点:
-
supportedAbis
:设备支持的 Abi(so 库)架构,字符串数组。 -
supportedLocales
:设备当前添加支持的地区语言(设备中有可能继续添加支持的地区语言,也就是说此字段并不代表设备支持的所有地区语言),字符串数组。 -
deviceFeatures
:设备支持的特性,字符串数组。 -
glExtensions
:设备支持的OpenGL扩展,字符串数组。 -
screenDensity
:屏幕密度,int
类型。 -
sdkVersion
:设备系统版本(versionCode),int
类型。
注意事项: 手动创建设备配置 JSON 文件的时候,只需要针对需要的信息进行配置即可,并不要求每一项都必须有,没有配置的项目会进行兼容处理 .
然后,您可以将此 JSON 传递给 bundle extract-apks
命令
从现有的 APK 集中提取设备专用 APK
参考官网链接:从现有的 APK 集中提取设备专用 APK
bundletool 可以使用 extract-apks
命令从现有的 APK 集合中提取指定设备配置的 APK 子集
bundletool extract-apks
--apks=/MyApp/my_existing_APK_set.apks
--output-dir=/MyApp/my_pixel2_APK_set.apks
--device-spec=/MyApp/bundletool/pixel2.json
extract-apks
命令输出的是 APK 文件(多个.apk
文件),而不是 APK 集合文件(.apks
压缩文件),所以--output-dir
是一个目录
extract-apks
命令使用详解
bundletool extract-apks
--apks=<archive.apks>
--device-spec=<device-spec.json>
[--include-metadata]
[--instant]
[--modules=<base,module1,module2>]
[--output-dir=<output-dir>]
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 集内的 APK 将在压缩后通过网络传送。如需估算这些 APK 的下载大小,可使用 get-size total
命令
bundletool get-size total --apks=/MyApp/my_app.apks
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>]
get-size total
参数标记详解
参数标志 | 必须参数 | 说明 |
---|---|---|
--apks=<archive.apks> |
是 | 由 build-apks 命令生成的 APK 集合压缩包路径 |
--human-readable-sizes |
否 | 添加此标记,输出可读性的大小(没有添加时单位为 Bit ),比如:10MB |
--device-spec |
否 | 指定设备配置,如果制定了此项,将获取针对该设备配置生成的 APK 下载大小,可通过 get-device-spec 命令获取设备信息 |
--dimensions |
否 | 定要扩展输出 APK 大小的维度,指定输出维度之后,将会以维度(或者维度组合)扩展输出 APK 大小信息,可使用的维度有:SDK (目标SDK版本)、ABI (ABI架构)、SCREEN_DENSITY (屏幕密度)、LANGUAGE (语种)、TEXTURE_COMPRESSION_FORMAT (纹理压缩格式)、DEVICE_TIER (设备层)、ALL (全部维度),可同时指定多个维度 |
--instant |
否 | 指定该标记,将会输出免安装模块的大小(而不是可安装 APK 的大小),默认不指定 |
--modules |
否 | 指定运行此命令获取的报告包含的模块列表(默认是首次安装需要下载的所有模块),需要注意的是,依赖模块也将会被计算在内。设置此标志时,我们会忽略独立 APK 进行大小计算 |
在命令行中使用
bundletool help get-size
可以查看相关的帮助信息