bundletool 构建学习笔记

64 阅读7分钟

要在本地调试 .aab(Android App Bundle)文件,由于 .aab 不能直接安装到设备上,你需要使用 Google 官方提供的命令行工具 bundletool 将其转换为可安装的 APK 文件(如针对特定设备的 APK 集合或通用 APK),然后安装到手机进行测试。

下面是完整的 本地调试流程


✅ 一、准备工作

1. 安装 bundletool

  • 下载地址:github.com/google/bund…
  • 下载最新版的 bundletool-all-*.jar(例如 bundletool-all-1.17.1.jar
  • 建议重命名为 bundletool.jar,并放到项目目录或加入系统 PATH

2. 准备 .aab 文件

通过以下任一方式生成:

# Debug 版本(用于开发测试)
./gradlew bundleDebug

# Release 版本(需签名)
./gradlew bundleRelease

输出路径通常为:

app/build/outputs/bundle/debug/app-debug.aab

⚠️ 注意:如果你使用了 Play App Signing,本地调试建议用 debug 签名自签名 release,避免签名不匹配。


🧪 二、本地调试方法(三种常用方式)


方法 1️⃣:生成 设备专用 APK 集合(推荐,最真实)

适用于连接了真机或模拟器的情况,bundletool 会根据设备配置(ABI、屏幕密度、语言等)生成最优 APK。

步骤:

  1. 确保设备已连接并启用 USB 调试

    adb devices
    
  2. 生成并安装 APK 到设备

    java -jar bundletool.jar install-apks \
      --apks=app.apks \
      --bundle=app-debug.aab
    

    💡 bundletool 会自动:

    • 生成 app.apks(内部包含 base + config-specific APKs)
    • 根据当前连接设备的配置选择合适 APK
    • 自动安装到设备
  3. 启动应用测试

    • 在设备上手动打开 App

    • 或通过 ADB 启动:

      adb shell am start -n com.example.myapp/.MainActivity
      

✅ 优点:完全模拟 Google Play 的分发行为,体积最小,最接近线上体验。


方法 2️⃣:生成 通用 APK(universal.apk)

适用于快速安装、多设备共享或无法连接设备时(如给 QA 发包)。

步骤:

  1. 生成 universal APK

    java -jar bundletool.jar build-apks \
      --bundle=app-debug.aab \
      --output=app.apks \
      --mode=universal
    
  2. 提取 universal.apk

    unzip app.apks -d apks/
    

    得到文件:apks/universal.apk

  3. 安装到设备

    adb install apks/universal.apk
    

⚠️ 缺点:

  • 包含所有资源(语言、ABI、dpi),体积大
  • 不支持动态功能模块的按需加载(所有模块都会打包进去)
  • 仅用于简单测试,不能验证动态模块的下载行为

方法 3️⃣:生成 APK Set 并手动安装(高级调试)

如果你想查看具体生成了哪些 APK(如 base.apk、xxhdpi.apk、arm64-v8a.apk 等):

# 生成完整 APK 集(未指定设备)
java -jar bundletool.jar build-apks \
  --bundle=app-debug.aab \
  --output=app.apks \
  --ks=your-debug.keystore \          # 如果 aab 未签名,需提供 keystore
  --ks-key-alias=androiddebugkey \
  --ks-pass=pass:android \
  --key-pass=pass:android

--connected-device //为已连接的设备生成 apk(根据已连接设备的分辨率、abi 和语言)

🔐 注意:如果 .aab 是用 debug key 签名的(默认 bundleDebug 会自动签),通常不需要额外指定 keystore。但如果报签名错误,请加上。

然后你可以:

  • 解压 app.apks 查看结构
  • 使用 adb install-multiple 手动安装多个 APK(适用于 split APK 场景)
unzip app.apks -d my_apks
adb install-multiple my_apks/*.apk

🛠️ 三、调试 Dynamic Feature Modules(动态模块)

如果你的 App 使用了 Dynamic Feature Modules,注意:

  • 方法 1(install-apks) :默认不会预装动态模块!它们仍需通过代码调用 SplitInstallManager 下载。
  • 若想强制包含动态模块用于本地测试,可在生成时指定:
java -jar bundletool.jar build-apks \
  --bundle=app-debug.aab \
  --output=app.apks \
  --modules=base,dynamic_feature1,dynamic_feature2

或使用 --local-testing(仅限较新版本 bundletool):

java -jar bundletool.jar build-apks \
  --bundle=app-debug.aab \
  --output=app.apks \
  --local-testing

启用 --local-testing 后,动态模块会被打包进 APK Set,并可通过 SplitInstallManager 模拟“已安装”状态,方便离线调试。

然后安装:

java -jar bundletool.jar install-apks --apks=app.apks

🧹 四、常见问题

❓ Q1:提示 “The APKs don’t contain a valid AndroidManifest.xml”

A:你可能直接对 .aab 使用了 adb install。记住:必须先用 bundletool 转成 APK

❓ Q2:安装时报签名冲突?

A:确保 .aab 和已有安装的 App 签名一致。卸载旧 App 再试:

adb uninstall com.example.myapp

❓ Q3:如何查看设备支持的配置?

A:运行:

adb shell getprop ro.product.cpu.abi    # ABI
adb shell getprop ro.sf.lcd_density     # 屏幕密度

✅ 总结:推荐调试流程

场景推荐命令
日常开发 + 真机调试bundletool install-apks --bundle=app-debug.aab
快速发包给他人测试生成 universal.apk
调试动态模块行为使用 --local-testing + install-apks
分析 APK 结构build-apks + unzip

使用 bundletool.aab 文件进行签名并打包为可安装的 APK,通常发生在以下场景:

  • 你有一个未签名或仅用 debug key 签名的 .aab
  • 你需要生成一个 release 签名的 APK 集(.apks) 用于本地测试、分发到非 Google Play 商店(如华为、小米应用市场);
  • 或者你需要生成 universal.apk 并确保其使用正确的 release 签名。

✅ 核心命令:bundletool build-apks + 签名参数

java -jar bundletool.jar build-apks \
  --bundle=app-release.aab \
  --output=app-release.apks \
  --ks=your-release-key.jks \
  --ks-key-alias=your-key-alias \
  --ks-pass=pass:your-keystore-password \
  --key-pass=pass:your-key-password

🔐 这个命令会:

  • 读取 .aab
  • 使用你提供的 keystore 对生成的 APK 进行 v1 + v2 签名
  • 输出一个 .apks 文件(内部是 ZIP 格式,包含多个 split APK 或 universal APK)

📌 参数详解

参数说明
--bundle输入的 .aab 文件路径
--output输出的 .apks 文件路径(注意是 .apks,不是 .apk
--ksKeystore 文件路径(如 my-release-key.jks
--ks-key-alias密钥别名(key alias)
--ks-passKeystore 密码,格式: pass:xxx(明文)或 file:/path/to/pwd.txt
--key-pass私钥密码(通常和 keystore 密码相同)

💡 如果你的 keystore 和 key 密码相同,且别名为 key0,典型命令如下:

java -jar bundletool.jar build-apks \
  --bundle=app-release.aab \
  --output=app.apks \
  --ks=my-release-key.jks \
  --ks-key-alias=key0 \
  --ks-pass=pass:123456 \
  --key-pass=pass:123456

🧪 示例:生成带 release 签名的 universal.apk

如果你要给第三方应用商店提供 单个 APK,可以结合 --mode=universal

java -jar bundletool.jar build-apks \
  --bundle=app-release.aab \
  --output=app-universal.apks \
  --mode=universal \
  --ks=my-release-key.jks \
  --ks-key-alias=key0 \
  --ks-pass=pass:123456 \
  --key-pass=pass:123456

然后提取 universal.apk

unzip app-universal.apks -d output/
# 得到 output/universal.apk

验证签名是否正确:

# 查看 APK 签名信息
apksigner verify --verbose output/universal.apk

# 或查看证书指纹
keytool -printcert -jarfile output/universal.apk

⚠️ 注意事项

1. .aab 是否已签名?

  • 如果你通过 ./gradlew bundleRelease 生成 .aab它本身不包含签名(签名由 Google Play 在分发时处理)。
  • 因此,必须通过 bundletool 指定 keystore 才能生成可安装的签名 APK

2. 不要混淆“上传密钥”和“应用签名密钥”

  • 如果你启用了 Google Play App Signing

    • 上传的是 upload key(用于签 .aab
    • Google Play 用 app signing key 签最终 APK
  • 但如果你要本地生成 release APK 给其他商店,必须使用 与 Google Play 不同的签名方案(即你自己保管的 release keystore),否则会因签名不一致无法覆盖安装。

3. 动态功能模块也会被签名

  • 所有 split APK(base、config、dynamic feature)都会使用你提供的 keystore 签名,确保完整性。

🔁 完整流程示例(从代码到 signed universal APK)

# 1. 构建 .aab(不签名,或用 upload key 签)
./gradlew bundleRelease

# 2. 使用 bundletool 生成 signed universal APK
java -jar bundletool.jar build-apks \
  --bundle=app/build/outputs/bundle/release/app-release.aab \
  --output=signed-app.apks \
  --mode=universal \
  --ks=../keys/release.jks \
  --ks-key-alias=my_app_key \
  --ks-pass=pass:MyKeystorePass \
  --key-pass=pass:MyKeyPass

# 3. 提取 APK
unzip signed-app.apks -d signed-apk/

# 4. 安装测试
adb install signed-apk/universal.apk

❓ 常见问题

Q:能否跳过签名?

A:不能。Android 要求所有 APK 必须签名才能安装。bundletool 若未提供 keystore,会尝试使用 debug key(仅限 debug aab),但 release 场景必须显式签名。

Q:如何知道我的 keystore 信息?

A:使用以下命令列出 keystore 内容:

keytool -list -v -keystore my-release-key.jks

Q:能否用 apksigner 后签?

A:不推荐。bundletool build-apks 已内置签名流程,手动拆包再签容易出错(尤其 split APK 场景)。


✅ 总结

目标命令关键点
生成设备专用 signed APK 集build-apks + keystore 参数(默认 mode)
生成 universal signed APK加上 --mode=universal
用于非 Google Play 分发必须使用你自己的 release keystore 签名
调试动态模块可加 --local-testing(需较新 bundletool)

appbundle split

分包策略,可以通过android.bundle的dsl定义进行配置,主要有三个维度,abi,density和language

    android{
        abi{
            enableSplit = true
        }
        density{
            enableSplit = true
        }
        
        language{
            enalbeSplit = true
        }
    }

install-apks 部署安装

java -jar bundletool.jar install-apks --apks=out.apks

adb shell pm path 包名 // 查看设备上已经安装应用的apk路径

导出已安装的apk

adb pull (上面查看的已经安装的apk路径) base.apk

生成全量apk

java -jar bundletool.jar build-apks --bundle=app.aab --output=all.apks --mode=universal