bundletool 工具使用

一、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 系统

    1. 新建一个目录(示例:D:\Android\bundletool\),将下载的 bundletool-xxx..jar 文件复制进去;
    2. 在目录下新建一个文件(示例:bundletool.bat),并在文件中添加内容 java -jar D:\Android\bundletool\bundletool-all-1.7.1.jar %*,最后面的 %*表示接收任意数量的参数;
    3. 将目录(示例:D:\Android\bundletool\)添加到环境变量的 Path 变量中,并保存
    4. 打开命令行窗口(如果已经打开,需要关闭后重新打开新的窗口),就可以使用命令 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

  • 使用 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 集合,使用 bundletoolbuild-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 可以查看相关的帮助信息

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容