3. AAB与APK的区别及优势
说实话,我刚接触 Android App Bundle 那会儿,第一反应是:“这不就是换了个壳的 APK 吗?”
真干了几个项目之后才发现,这俩玩意儿的底层逻辑完全不同。咱们今天就把它们掰开揉碎,看看 AAB 到底比 APK 强在哪,以及为什么灰度发布这件事儿,用 AAB 简直是天生一对。
3.1 打包方式的根本差异
APK 的打包,说白了就是把所有资源一股脑塞进一个 Zip 包里。你想想,一个 100MB 的 APK,里头可能包含 10 种语言的字符串、5 种分辨率的高清图、3 种架构的 so 库。用户下载的时候,哪怕他只用中文 + 1080p + arm64,也得把整个包拖下来。
我早期维护过一个海外社交 App,包体 80MB,每次发版都在想“用户流量不要钱吗?”后来改成 AAB,看数据惊了——平均下载量降了 40%。原因很简单:AAB 打包的时候,它把资源按“配置维度”拆开了。
核心区别一览
| 对比项 | APK(传统方式) | AAB(Android App Bundle) |
|---|---|---|
| 打包产物 | 单个 APK 文件 | .aab 文件(包含所有模块 + 分块资源) |
| 资源处理 | 不做拆分,全部包含 | 按语言、屏幕密度、CPU 架构拆分为“模块分片” |
| 签名时间 | 构建时签名 | 上传至 Google Play,由 Play 签名并生成“带签名的 APK” |
| 最终交付 | 用户直接下载 APK 安装 | Google Play 根据用户设备生成“专用 APK”再下发 |
嗯,这里要注意:AAB 本身不能直接安装到手机上。它是个上传格式,Google Play 拿到后,会按设备配置生成一个“裁剪过的 APK”给用户。这个过程叫做“动态交付”(Dynamic Delivery)。
3.2 体积优化:AAB 凭什么更小?
你可能会问:“AAB 拆开之后,单个用户的下载体积能小多少?”
来,看个真实数据。我去年做过一个工具类 App,原始 APK 65MB。改成 AAB 并配置了拆分后,用户平均下载包只有 38MB。节省了近 42%。
为什么会这样?
- 语言资源:你一个中文 App,没必要让用户下载日文、法文、阿拉伯文的字符串。APK 强迫你“买一送十”,AAB 只给用户“买一送一”。
- 图片资源:屏幕密度从 mdpi 到 xxxhdpi,像素差好几倍。AAB 只下发对应密度及可回退的密度,不会塞那些永远用不上的巨图。
- 原生库:arm64-v8a、armeabi-v7a、x86……APK 得全放。AAB 挑出用户设备对应的架构,其他直接砍掉。
个人经验:我在做灰度方案时,曾经把包含 4 套 so 库的 APK 直接切换成 AAB,单渠道包体积从 120MB 降到 35MB。当时测试同事以为我写错了脚本……其实这就是 AAB 的正常表现。
3.3 动态分发能力:按需加载的魅力
APK 是“一次下载,全部安装”。AAB 允许你把功能模块做成“按需安装”的组件。比如你的 App 里有个 AR 拍照功能,可能 80% 的用户从来不用。那这个功能模块就可以做成“按需分发”。用户第一次点 AR 相机时,后台默默下个几 MB 的模块,装好再用。
这对于灰度发布来说,简直是神器。为什么?
- 你可以只把新功能模块推给灰度组,其他用户看不到也下载不到。
- 如果灰度发现 BUG,直接撤回模块,不需要用户更新整个 App。
- 灰度结束后,把模块状态改为“默认安装”,所有后续增量用户自动带上。
还记得我前面提到的“按需模块”吗?它不仅仅是体积优化,更是发布策略上的一个分身术。我负责过一个电商项目,想在双十一前灰度测试“直播购物”功能。如果用 APK 传统方式,得打两个包(有直播版 + 无直播版),然后分别配置渠道。维护两个版本号,想想就头大。
换成 AAB + 按需模块后,只维护一份 AAB,直播模块是“on-demand”。灰度组在 Play Console 里配置 5% 用户可下载该模块,剩下的用户压根感知不到有这个功能存在。出了问题,一键关掉分发即可。回滚速度从“发版 + 审核”变成“秒级配置生效”。
避坑指南:我曾经在灰度某功能时,没注意“按需模块”的下载时机。结果灰度用户进入页面后,先弹出一个“正在加载模块”的 Toast,然后才下载安装,体验很糟糕。后来我改用“条件延迟下载”——用户空闲时 WiFi 下预加载,体验才正常。
3.4 为什么灰度发布更适合同步 App Bundle?
咱们把灰度发布的目标再明确一下:
- 控制暴露范围:只让一小部分用户看到新功能。
- 快速迭代:发现问题能立刻停止推送。
- 数据对比:灰度组和对照组之间需要有明确的版本分界。
传统 APK 做灰度,要么用多渠道包(一个 APK 对应一个灰度组),要么用服务端开关(同一个 APK 里内置功能开关)。多渠道包管理成本高,而且维护多个 APK 的版本号容易出错。服务端开关倒是方便,但开关控制的代码始终在用户手机里,容易被逆向破解或抓包篡改。
AAB 给了一个更优雅的方案:细分版本 + 按需模块。
- 细分版本:AAB 可以选择只给灰度用户下发“带新功能的新版模块”,其他人继续用旧版。这相当于天然将用户分成了两组。
- 按需模块:新功能以模块打包,只有灰度用户才会下载该模块。未下载的用户根本不包含任何新功能代码,安全性和隔离性都更好。
- 包体积优势:因为进行了资源拆分,灰度用户的下载量更小,灰度测试的成本(流量、存储)也降低了。
我个人的建议:如果你的灰度发布频率大于每月一次,或者灰度功能涉及大量资源(图片、布局、so库),那么用 AAB 替换 APK 几乎是零坑升级。否则,继续用老路也能凑合。
知识结构总览
3.5 总结:一张表看透 AAB vs APK
| 维度 | APK | AAB |
|---|---|---|
| 打包粒度 | 单体胖包 | 模块化 + 资源分片 |
| 用户下载体积 | 打包时的全量数据 | 仅下载当前设备所需 |
| 灰度灵活性 | 多渠道包 / 代码开关 | 按需模块 + Play Console 配置 |
| 回滚效率 | 需重新发版 | 关闭模块分发,秒级生效 |
| 安全隔离性 | 代码均在安装包内 | 未授权用户不包含模块代码 |
| 适用场景 | 简单功能、小团队 | 复杂模块、频繁灰度、大团队 |
说到底,AAB 不是为了取代 APK 而生的,它是为了响应动态分发和包体积优化这个时代需求而生的。你只要做过一次灰度切 AAB 的迁移,就再也不想回到以前那个“打五个不同渠道号 APK”的日子了。