AAB vs APK:为什么 Google 强制 AAB
2021年8月起,Google Play 要求所有新提交的应用必须使用 Android App Bundle(AAB)格式,不再接受传统的 APK 文件。这个决定在开发者社区引起了不小的讨论,但回头看,这确实是 Android 生态演进的必然方向。
先说清楚两者的本质区别。APK 是一个"大包",里面塞满了所有屏幕密度、CPU架构、语言资源,不管用户设备用不用得上,全部打包在一起。一个简单的工具类应用,APK 动辄 30-50MB,其中一大半资源对特定用户来说完全是浪费。
AAB 的思路完全不同——它不是最终的分发格式,而是一个"发布格式"。Google Play 收到你的 AAB 后,会根据每个用户的设备配置,自动生成一个最小化的 APK(叫做 Split APK),只包含该设备需要的资源。官方数据显示,AAB 平均能让应用体积缩小 15%-65%,对用户下载转化率的提升是实打实的。
根据 Google 在 Android Developers Blog 上公布的数据,自 AAB 强制执行以来,Google Play 上应用的平均安装体积下降了约 35%,节省了超过 10PB 的带宽1。
如果你还在犹豫要不要迁移,别纠结了——新应用必须用 AAB,这是硬性要求。与其被动适应,不如主动搞懂它。搞懂格式后,下一步就是走完整个上架流程——参考《Google Play 上架教程 2026》从注册到上线一步步操作。
AAB 格式技术原理
理解 AAB 的工作机制,有助于你在构建时做出正确的配置决策。
按需分发(Split APKs)
AAB 的核心机制是按需分发。当你上传一个 AAB 到 Google Play Console 后,Google 会根据以下维度拆分资源:
- 屏幕密度(ldpi、mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi)
- CPU 架构(armeabi-v7a、arm64-v8a、x86、x86_64)
- 语言资源(values-zh、values-en、values-ja 等)
用户在 Google Play 下载应用时,只会拿到跟自己设备匹配的那一组 Split APK,而不是完整的大包。举个例子,一个中国用户用骁龙处理器的手机下载你的应用,他拿到的是 arm64-v8a + xxhdpi + values-zh 的组合,完全不需要的 x86 资源和阿拉伯语翻译都不会被安装。
资源压缩与代码缩减
AAB 还支持更激进的资源优化。Google Play 会自动移除未使用的资源文件,配合 R8/ProGuard 的代码缩减功能,效果更加明显。如果你在 Google Play 上架全流程 中做过包体优化,应该对 shrinkResources 和 minifyEnabled 这两个配置不陌生,在 AAB 中它们的逻辑是一致的。
Asset Delivery
对于超过 150MB 的应用,AAB 提供了 Play Asset Delivery 机制,允许将大型资源文件(游戏贴图、视频等)按需下载或作为快速跟进包分发,不再需要单独的 OBB 文件。
从 APK 迁移到 AAB:完整步骤
迁移过程其实没有想象中复杂,大部分工作在 Gradle 配置层面就能完成。
步骤一:检查项目配置
首先确认你的项目使用 Android Gradle Plugin 4.0 或更高版本(建议 7.0+)。在项目根目录的 build.gradle 中检查:
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
}
}
如果你还在用很老的 Gradle 版本,建议先升级。AGP 4.0 之前的版本对 AAB 的支持有限。
步骤二:配置 build.gradle
在 app 模块的 build.gradle 中,确保以下配置正确:
android {
// 必须明确指定 bundle 配置
bundle {
density {
enableSplit = true // 按屏幕密度拆分
}
abi {
enableSplit = true // 按CPU架构拆分
}
language {
enableSplit = true // 按语言拆分
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
这三个 enableSplit 默认就是 true,但显式写出来更清晰。如果你不想某个维度被拆分(比如某些国产 SDK 对多架构支持不好),可以手动关掉对应的 split。
步骤三:配置签名
AAB 的签名跟 APK 有所不同。Google Play 现在使用 App Signing by Google Play(Google Play 应用签名),你需要区分两个概念:
- 上传密钥(Upload Key):你本地用来签名 AAB 的密钥
- 应用签名密钥(App Signing Key):Google Play 用来签最终分发给用户的 APK 的密钥
如果你是第一次发布应用,在 Google Play 开发者账号注册 完成后,创建应用时 Google 会引导你加入应用签名计划。建议直接让 Google 自动生成应用签名密钥,省心且安全。
在 build.gradle 中配置签名信息:
android {
signingConfigs {
release {
storeFile file('your-keystore.jks')
storePassword 'your_store_password'
keyAlias 'your_key_alias'
keyPassword 'your_key_password'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
更好的做法是把密码放到环境变量或 keystore.properties 文件中,避免密钥信息泄露到代码仓库。
步骤四:构建 AAB
使用命令行构建:
./gradlew bundleRelease
注意命令是 bundleRelease,不是 assembleRelease。前者生成 .aab 文件,后者生成 .apk。生成的 AAB 文件位于 app/build/outputs/bundle/release/app-release.aab。
AAB 构建与签名最佳实践
做了几十个项目之后,这里总结几条实战经验:
1. 统一使用一个上传密钥
如果你有多个应用,可以用同一个上传密钥。这样管理简单,密钥丢失的风险也小。但如果每个应用的应用签名密钥不同(Google Play 默认会为每个应用生成不同的密钥),替换上传密钥需要联系 Google 支持,比较麻烦。
2. 版本号管理要规范
每次上传 AAB,versionCode 必须比之前的高。建议在 build.gradle 中使用递增的版本号策略。上线后发现 bug 要紧急修复时,版本号搞错是很常见的问题。
3. 不要把签名文件放进 Git
这看起来是常识,但每年都有开发者踩这个坑。.jks 文件和密码信息应该放在 CI/CD 环境变量或者安全的密钥管理服务中。
4. Debug 和 Release 使用不同签名
开发阶段用 debug 签名(Android Studio 默认的 debug keystore),只在构建发布包时使用正式签名。这样团队成员之间不会因为签名不一致导致覆盖安装的问题。
常见构建错误及解决方案
迁移过程中踩坑是正常的,这里列几个最常见的:
错误一:JNI 库打包问题
现象:构建 AAB 时报错,提示 native library 包含不支持的架构。
解决:在 build.gradle 中过滤不需要的架构:
android {
defaultConfig {
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
}
}
现代 Android 设备几乎都是 arm64-v8a,保留 x86 主要为了模拟器测试。上架时可以只保留 ARM 架构来减小包体。
错误二:资源引用导致 Split 失败
现象:代码中通过字符串拼接方式引用资源(如 getIdentifier("img_" + id, "drawable", packageName)),导致资源无法被正确压缩。
解决:尽量避免动态资源引用。如果必须使用,需要在 bundleconfig.json 中保留相关资源:
{
"optimizations": {
"splitsConfig": {
"stripDots": false
}
}
}
错误三:签名不匹配
现象:上传 AAB 到 Google Play Console 时提示签名跟之前的应用不一致。
解决:如果你之前已经用某个密钥发布过应用,之后更换了上传密钥,需要通过 Google Play Console 的"请求更新上传密钥"功能来重置。这个流程需要身份验证,通常几个工作日能完成。
错误四:AAB 文件超过 150MB
现象:Google Play 对 AAB 文件有 150MB 的限制。
解决:使用 Play Asset Delivery 将大型资源文件分离出去。游戏类应用几乎都会超过这个限制,建议在项目初期就规划好资源加载策略。
如何测试 AAB 包:bundletool 使用指南
构建出 AAB 后,直接安装到设备上是不行的——AAB 不是可安装格式。你需要使用 Google 提供的 bundletool 工具来生成本地测试用的 APK。
安装 bundletool
从 GitHub 下载最新版本:
wget https://github.com/google/bundletool/releases/download/1.15.6/bundletool-all-1.15.6.jar
生成并安装测试 APK
# 生成 connected 设备的 APK 集合
java -jar bundletool-all-1.15.6.jar build-apks \
--bundle=app-release.aab \
--output=app.apks \
--connected-device
# 安装到设备
java -jar bundletool-all-1.15.6.jar install-apks \
--apks=app.apks
--connected-device 参数会根据你当前连接的测试设备生成最匹配的 APK 组合。如果不加这个参数,bundletool 会生成包含所有 Split 的完整包,体积会很大。
提取特定设备的 APK
如果需要在特定设备上测试,可以使用设备配置 JSON:
# 生成设备配置
java -jar bundletool-all-1.15.6.jar get-device-spec \
--output=device-spec.json
# 根据配置生成 APK
java -jar bundletool-all-1.15.6.jar build-apks \
--bundle=app-release.aab \
--output=app.apks \
--device-spec=device-spec.json
测试 AAB 包这一步千万别跳过。很多问题只在 Split APK 环境下才会出现,比如缺少某个密度的资源导致崩溃。直接用 Android Studio 的 Run 按钮测试的是完整 APK,覆盖不到这些边界情况。
FAQ
Q1:AAB 格式是否影响应用的更新?
不影响。Google Play 会自动处理从 APK 到 AAB 的过渡。老用户已经安装的 APK 会正常接收更新,Google Play 会根据设备配置推送合适的 Split APK 作为更新包。用户端完全无感知,不需要卸载重装。
Q2:我已经用 APK 发布了应用,现在想切换到 AAB,需要重新创建应用吗?
不需要。在 Google Play Console 中,你只需要从下一次更新开始上传 AAB 文件即可。前提是你已经加入了 Google Play 应用签名计划。如果之前发布时没有加入,需要先在 Console 中完成应用签名的 opt-in 流程。具体可以参考我们整理的 Google Play 上架费用 一文中关于签名服务费用的部分。
Q3:AAB 格式对应用内购(IAP)有影响吗?
完全没有影响。AAB 是打包和分发层面的改变,不影响应用内的业务逻辑。BillingClient 的接入方式、SKU 配置、支付流程都跟使用 APK 时一模一样。唯一需要注意的是,如果你的 IAP 测试依赖本地安装的 APK,切换到 AAB 后需要用 bundletool 生成的 APK 来做测试。
总结
从 APK 迁移到 AAB,表面上看是换了个打包格式,实际上涉及构建配置、签名策略、测试流程多个环节的调整。核心要点回顾:
- AAB 通过按需分发大幅减小用户下载体积
- 迁移主要改动在 Gradle 配置和签名设置
- 必须使用 bundletool 来测试 AAB 包
- 注意 JNI 库、动态资源引用等容易踩坑的地方
对于准备上架 Google Play 的开发者来说,AAB 已经不是"选择题"而是"必答题"。如果你的团队在上架过程中遇到任何问题,星辰出海 提供从开发者账号注册到应用审核通过的一站式服务,7年出海经验,2000+ 成功案例,帮你少走弯路。
Footnotes
-
Android Developers Blog, "Announcing Android App Bundle publishing format", https://android-developers.googleblog.com/2018/05/announcing-new-android-app-bundle.html ↩