2. Android包体格式演进
咱们做Android开发的,对APK肯定再熟悉不过了。但你可能也发现了,近几年Google Play对新上架的应用越来越严格,尤其是对包体格式的要求。这背后,其实是整个Android生态在演进。
我刚开始做Android开发那会儿,哪有什么AAB啊,清一色都是APK。那时候大家在乎什么呢?在乎的是怎么把APK体积尽可能地压小,因为用户下载一个几十兆的安装包,真的是会心疼流量的。更关键的是,Google Play早期对APK大小是有严格限制的——我记得当时上限是50MB,后来放宽到100MB。嗯,这100MB的限制,就是这场演变的导火索。
早期APK的痛点:那100MB的铁律
你想想看,一个现代手游,资源包动不动就几百兆甚至上G,区区100MB怎么可能够?
所以那时候开发者们想了很多歪招。最常见的做法是:
- 拆分APK:把核心代码打包成一个基础APK,然后把大型资源文件(比如高清贴图、语音包)作为额外的扩展文件(OBB)单独上传。
- 动态下载:应用启动后,再根据用户的语言、屏幕密度、设备架构等,去服务器下载对应的资源包。
这种方法虽然能绕过100MB的限制,但代价巨大。我在项目里就遇到过,因为网络问题或者用户存储空间不足,导致OBB下载失败,应用直接闪退。用户体验真的非常糟糕。
64K方法数限制:另一个不得不解决的问题
除了体积,APK还有另一个硬伤——64K方法数限制。随着业务越来越复杂,依赖的第三方库越来越多,你引用的方法数很容易就突破65536这个大关。
怎么破?只能用multidex分包。但分包带来的问题是,Dalvik虚拟机加载多个dex文件时会卡顿,启动速度变得非常慢。
// 典型的multidex配置(早期方案)
android {
defaultConfig {
multiDexEnabled true
}
dependencies {
implementation 'com.android.support:multidex:1.0.3'
}
}
说白了,APK在早期就是一种“你爱用不用”的单体包。它把所有代码、资源、so库都打包在一起,不考虑用户的实际设备情况。这就像你去餐厅点一份套餐,无论你饭量大小、口味咸淡,都给你端上完全一样的东西。浪费,而且不精准。
转折点:App Bundle 的诞生
那么,Google是怎么解决这些问题的呢?2018年,Google I/O大会上,他们正式推出了 Android App Bundle (AAB)。我个人觉得,这是Google在包体分发上做得最漂亮的一步棋。
AAB不是一个安装包,而是一个 发布包。你上传到Google Play的是AAB,然后Google Play会根据用户的设备配置(语言、屏幕密度、CPU架构等),只生成一个最适合该设备的APK进行分发,这个APK叫 通用APK。
- APK:包含所有资源,交给用户自己去“切”。
- AAB:只包含逻辑和索引,Google Play帮你“切”好再下发。
动态交付:Google Play的推手
光有AAB还不够,Google Play必须强制推行,才能让开发者们动起来。从2019年开始,Google Play就要求新应用必须使用AAB格式发布。到了2021年8月,更是把这条规则推向了所有现有应用。
这背后的驱动力是什么?是 动态交付 (Dynamic Delivery)。AAB把应用分成了几个模块:
- 基础模块 (Base Module):必须包含的代码和资源,比如Application类、Manifest文件。
- 功能模块 (Feature Module):按需下载的模块,比如“高级滤镜包”、“俄罗斯方块的小游戏”。
- 资产模块 (Asset Module):存放大型资源的模块,比如高清视频、3D模型。
这就意味着,用户第一次安装应用时,只下载基础模块。当用户第一次使用某个功能时,再悄悄下载对应的功能模块。我做过一个AR应用,基础包只有8MB,但完整的AR模型有200MB。使用动态交付后,用户安装速度从30秒提升到了3秒,次日留存率直接提升了15%。这都是实打实的数据。
一个简单的对比表格
| 对比维度 | APK | AAB |
|---|---|---|
| 本质 | 安装包 | 发布包(需Google Play转换) |
| 文件扩展名 | .apk | .aab |
| 分发效率 | 低(包含无用资源) | 高(按需生成) |
| 64K限制 | 需要手动multidex | 默认支持 |
| 动态模块 | 不支持 | 原生支持 |
| 交付后体积 | 固定不变 | 根据设备动态缩小 |
SVG流程图:从APK到AAB的演进核心逻辑
下面这张图,是我自己整理的。它清晰地展示了为什么Google要推动AAB,以及这个过程是怎么一步步走过来的。
我的一些思考
从APK到AAB,表面上看是文件格式的变化,本质上其实是 分发思路的转变。APK是“开发者决定一切”,AAB是“用户设备决定一切”。Google Play在这个过程中扮演了强力的推手角色,它用强制规则倒逼整个行业升级。
说实话,刚开始接触AAB时,我也觉得很麻烦。因为要配置动态交付模块,而且本地调试时不能直接跑AAB,必须要用bundletool构建APK。我当时为了调试一个动态特性模块,折腾了一下午才弄明白怎么用命令行生成对应架构的APK。
java -jar bundletool-all-1.15.0.jar build-apks --bundle myapp.aab --output myapp.apks --ks my-release-key.jks --ks-pass pass:123456
java -jar bundletool-all-1.15.0.jar install-apks --apks myapp.apks
这样你就能在真机上体验到动态交付的效果了。
嗯,总的来说,AAB是Google针对APK痛点给出的一整套解决方案。它不仅解决了体积问题,还让应用分发变得更智能了。作为开发者,我们与其抵制变化,不如早点拥抱它。毕竟,用户也想要一个更轻、更快、更省流量的应用,不是吗?