第2章 App Bundle原理:打包拆分、模块化、签名分发
2.1 什么是Android App Bundle
Android App Bundle(.aab)是Google于2018年推出的官方发布格式,它取代了传统APK成为Google Play商店的默认上传格式。AAB本身不是可安装包,而是包含所有编译后代码和资源的容器,由Google Play商店根据用户设备配置(屏幕密度、CPU架构、语言等)动态生成并分发优化的APK分片(Split APK)。
核心优势:减小初始安装包体40%以上,按需下载模块,实现动态交付。
2.2 APK vs AAB:关键差异对比
| 对比维度 | APK | AAB |
|---|---|---|
| 交付格式 | 单一可安装包 | 发布容器,需平台转换 |
| 包含内容 | 所有资源配置无条件打包 | 仅保留原始代码和资源,不冗余 |
| 设备适配 | 由开发者手动分包(多APK) | 由商店自动分发最优分片 |
| 动态模块 | 不支持运行时按需安装 | 通过SplitInstall API原生支持 |
| 签名方式 | 直接对APK签名 | 对AAB签名,分片继承签名 |
| 文件后缀 | .apk | .aab |
2.3 App Bundle构建与分发流程
下图展示了从源代码到最终设备安装的完整链路:
2.4 打包拆分原理
Android Gradle Plugin(AGP)在构建AAB时,会将应用划分为多个逻辑模块,每个模块最终输出独立的Split APK。拆分粒度包括:
- Base模块:所有设备都需要的核心代码和资源(如Application类、通用资源)。
- Config模块:按屏幕密度(mdpi/hdpi/xhdpi等)、CPU架构(armeabi-v7a/arm64-v8a/x86)、OpenGL ES纹理等拆分。
- Language模块:按系统语言分离字符串资源。
- Feature模块:开发者通过
com.android.dynamic-feature插件声明的按需功能。
提效技巧:使用
bundletool的extract-apks命令可本地验证拆分结果,无需上传商店。java -jar bundletool.jar build-apks \
--bundle=app.aab \
--output=app.apks \
--ks=my-release-key.jks \
--ks-pass=pass:123456 \
--ks-key-alias=myalias \
--key-pass=pass:123456
2.5 模块化结构配置
在项目根目录的settings.gradle中声明所有模块:
include ':app'
include ':feature_camera'
include ':feature_ar'
include ':feature_payments'
在基础模块(app)的build.gradle中引用动态特性模块:
// app/build.gradle
android {
dynamicFeatures = [':feature_camera', ':feature_ar']
}
dependencies {
implementation project(':feature_camera') // 作为动态特性,运行时安装
implementation project(':feature_ar')
}
动态特性模块自身需声明为动态特性插件:
// feature_camera/build.gradle
plugins {
id 'com.android.dynamic-feature'
}
android {
compileSdk 33
defaultConfig {
minSdk 21
}
}
dependencies {
implementation project(':app')
// 其他依赖
}
2.6 签名与分发
AAB的签名流程与APK类似,使用JKS签名文件。关键步骤:
- 生成签名密钥(
keytool) - 配置
build.gradle签名信息或使用-ks参数通过jarsigner手动签名 - 通过
bundletool构建APKS集并签名
手动签名示例(使用jarsigner):
jarsigner -keystore my-release-key.jks \
-storepass 123456 \
-keypass 123456 \
-signedjar app_signed.aab \
app.aab myalias
自动签名(推荐用于本地测试):
// 使用bundletool一次性签名
bundletool build-apks \
--bundle=app.aab \
--output=app.apks \
--ks=my-release-key.jks \
--ks-pass=pass:123456 \
--ks-key-alias=myalias \
--key-pass=pass:123456
关键注意:Play商店要求AAB使用应用签名密钥(App Signing Key)进行签名。上传至Play控制台时,建议启用Google Play App Signing,让Google托管应用签名密钥,防止密钥丢失导致无法更新。
2.7 常见错误与优化
- Error: No matching variant of …:动态特性模块与基础模块的
minSdkVersion、targetSdkVersion不一致。确保所有模块版本对齐。 - Duplicate resources:动态特性模块不应包含与base模块重复的资源。使用
dist标签筛选或重命名。 - Split APK安装超时:特性模块体积过大。建议单模块不超过150MB,使用
On-Demand模式分块下载。
性能优化建议:
• 将大型资源(3D模型、高清贴图)单独抽离为按需特性模块。
• 使用
• 对语言资源启用
• 将大型资源(3D模型、高清贴图)单独抽离为按需特性模块。
• 使用
SplitInstallManager的deferredInstall在后台静默下载非关键模块。• 对语言资源启用
android.bundle.language.enableSplit = false避免过多小APK。