应用安装包体积一直是影响用户下载意愿的关键因素。当APK从几十MB增长到上百MB,每增加1MB都可能带来可观的流失。传统做法是优化代码、压缩图片、使用ProGuard,但这些本质上还是在同一个全量APK内做文章。Android App Bundle(AAB)走了一条不同的路线:它不再是单一的可安装文件,而是一种发布格式,把应用的代码、资源、原生库拆分成多个模块,交给应用商店去完成最终的APK组装。

Android App Bundle与APK的本质区别
AAB文件的后缀是.aab,它不能直接安装到设备上。它更像是一个“原料包”,里面包含了针对不同屏幕密度、CPU架构、语言的所有资源变体。当你把AAB上传到Google Play后,商店会根据每个用户设备的配置,动态生成一个只包含该设备所需资源的“定制APK”,这个过程称为“Dynamic Delivery”。例如,一台只支持armeabi-v7a架构的中文设备,拿到的APK里不会包含x86_64的so库,也不会包含英文、日文等无关的语言资源包。相比之下,传统APK必须包含所有可能的资源,否则就会在某些设备上出现兼容性问题。
这种差异带来两个直接好处:一是安装包体积显著减小,通常比全量APK小15%到35%;二是开发者不再需要手动维护多套APK(如按CPU架构拆分),也不需要为不同设备生成不同版本。所有优化都由Google Play自动完成。不过要注意,AAB目前只适用于通过Google Play发布的应用,国内应用商店若要求上传APK,仍需要单独构建传统APK或使用工具将AAB转换为APK。
如何构建和导出AAB文件
在Android Studio中,构建AAB非常简单。打开菜单栏的Build,选择“Generate Signed Bundle or APK”,然后勾选“Android App Bundle”并点击Next。接下来的签名流程和构建APK完全一样。如果更习惯命令行,可以使用Gradle任务:在项目根目录执行./gradlew bundleRelease,就会在app/build/outputs/bundle/release/目录下生成一个app-release.aab文件。对于CI环境,也可以配置signingConfig后在脚本中调用相同的task。
构建完成后,强烈建议先在本地验证AAB的内容。Google提供了一个名为bundletool的命令行工具,可以解析AAB并模拟生成针对特定设备的APK。例如执行bundletool build-apks --bundle=app.aab --output=app.apks --ks=keystore.jks --ks-pass=pass:password会生成一个.apks文件,里面包含了一组APK。接着用bundletool install-apks --apks=app.apks就可以安装到连接的设备上。这个工具还能检查AAB的结构是否符合规范,以及估算不同设备上的APK大小,对排查资源遗漏和体积优化都有帮助。
动态功能模块与按需分发
AAB不仅用于基础资源的按需拆分,还支持“动态功能模块”(Dynamic Feature Module)。开发者可以把某些不常用的功能(如扫码、视频编辑、高级设置)封装成独立模块,在用户需要时才从Google Play下载。这些模块在AAB中声明,并通过Play Core Library在运行时请求安装。模块的加载状态可以通过回调监听,用户几乎无感知地完成功能扩展。这种方式能把初始安装包压缩到极致,适合功能丰富但使用频率不均的应用。
要使用动态功能模块,首先在项目中新建一个module,其AndroidManifest.xml中需要声明android:isDynamicFeature="true",并指定dist:module属性。主应用模块则通过SplitInstallManager发起请求。代码示例如下:
// 创建SplitInstallManager实例
SplitInstallManager splitInstallManager = SplitInstallManagerFactory.create(context);
// 构建请求,指定要下载的模块名
SplitInstallRequest request = SplitInstallRequest.newBuilder()
.addModule("video_editor")
.build();
// 发起下载请求
splitInstallManager.startInstall(request)
.addOnSuccessListener(sessionId -> {
// 下载完成,可以启动模块中的Activity
})
.addOnFailureListener(exception -> {
// 处理下载失败
});
动态功能模块的下载进度、失败重试都可以通过SplitInstallStateUpdatedListener监听。需要注意的是,模块一旦下载安装,后续更新会随着应用更新自动完成,用户无需再次手动下载。这种按需分发的机制不仅减小了首次安装体积,还提高了应用商店的转化率。
迁移到AAB的注意事项与常见问题
对于已经发布APK的应用,迁移到AAB需要关注签名一致性。Google Play要求AAB和已有的APK使用相同的签名密钥,否则无法更新。另外,AAB发布的版本号必须高于现有版本,否则会被拒绝。如果应用使用了多个APK(比如按ABI拆分),迁移到AAB后这些手动拆分的APK需要全部移除,因为AAB已经自动处理了架构和屏幕密度拆分。
还有一个常见误区是关于“AAB更安全”的讨论。AAB本身不增加安全性,它只是改变了分发方式。真正的安全还是要依靠代码混淆、资源加密、证书保护等手段。另外,部分开发者担心AAB无法离线分发,这确实是个限制:如果你需要把应用分发给无法访问Google Play的设备,AAB就不适用了。此时可以使用bundletool把AAB转换为通用APK,或者继续维护一套传统APK构建流程。国内发行渠道通常要求上传APK,所以很多团队会同时维护AAB(用于Google Play)和APK(用于国内商店)两套构建产物。
从实践角度看,AAB带来的体积优化在海外市场尤其明显,而国内由于渠道复杂,其优势暂时无法完全发挥。但Google Play已经强制要求新应用使用AAB格式,因此了解并掌握AAB是Android开发者的必备技能。建议先在开发分支中尝试构建AAB,使用bundletool验证生成的APK体积,再逐步过渡到生产发布。

