Skip to content
Back to Blog
format-comparisons

APK 与 AAB 对比:安卓新分发格式全面解析

2026-05-17 9 min read

APK 到底是什么(以及它为何能称霸安卓 15 年)

在长达 15 年的时间里,安卓应用包(Android Package Kit,简称 APK)是唯一的选择。自 2008 年安卓平台诞生以来,它一直是安卓应用的标准格式。一个 APK 文件其实就是一个具有特定内部结构的 ZIP 压缩包:它包含了编译后的 AndroidManifest.xml、DEX 字节码(classes.dex)、一个 resources.arsc 资源表,以及存放 assets、原生库和其他原始资源的文件夹。当你从网站上下载应用,或者用蓝牙传给朋友时,你发送的就是一个 .apk 文件,这个文件包含了在任何安卓设备上运行所需的一切。 这种“一包通用”的方式既是 APK 最大的优点,也是它致命的缺陷。一个来自 Google Play 商店的 APK 必须支持所有设备,从搭载 64 位 ARM 芯片的三星 Galaxy S25 Ultra,到使用 32 位 ARM 芯片的低端 Tecno 手机,再到采用 x86 处理器的 Chromebook,以及各种你能想到的屏幕密度。为了做到这一点,开发者不得不把每个原生库、翻译字符串和屏幕密度图片的各种版本都打包进一个庞大的文件里。结果呢?像 Google Maps 这样的应用,其 APK 文件可能高达 100 MB,而你的设备实际需要的可能只有 40 MB。剩下的部分就纯属累赘——被下载、被存储,但永远不会被使用。

Android App Bundle:2018 年的变革以及谷歌为何强制推行

在 Google I/O 2018 大会上,谷歌终于着手解决 APK 的臃肿问题,推出了 Android App Bundle (AAB),并从 2021 年 8 月起强制要求 Play 商店的新应用使用该格式。虽然它的扩展名是 .aab,并且同样是一个 ZIP 压缩包,但它并不能直接安装。你可以把它想象成一份菜谱和一盒配料,而不是做好的蛋糕成品。一个 AAB 文件包含了模块化的编译代码和资源,但最终的组装工作由 Google Play 的服务器完成。 这个过程被称为动态分发 (Dynamic Delivery)。当用户在 Play 商店点击“安装”时,谷歌的服务器会分析用户的具体设备——CPU 架构 (ABI)、屏幕密度和语言设置。然后,服务器会构建并提供一套定制化的分割 APK (split APKs),其中只包含该设备所需的内容。一台运行安卓 15 的英文版 Pixel 9 手机可能只需要下载 38 MB,而过去那种大而全的 APK 文件则可能高达 95 MB。 体积的减小并非理论上的,而是显著且可衡量的。谷歌自家 2021 年的数据显示,改用 AAB 的应用平均体积减小了 15%,有些应用的体积甚至减少了 50% 以上。对于一款为不同 GPU 压缩格式(如 ETC2、ASTC 和 S3TC)设计了大量纹理图集的游戏来说,节省的空间更是天文数字,可以轻松地为用户的手机安装省下数百兆字节。

AAB 文件的内部结构

如果你用 ZIP 工具打开一个 AAB 文件,你会立刻发现它和 APK 不一样。顶层有一个定义应用包配置的 BundleConfig.pb 文件,一个 BUNDLE-METADATA 目录,以及至少一个模块目录。主模块通常被称为 `base/`,其内部看起来有点像 APK,也包含 `dex/`、`manifest/`、`res/`、`root/` 和 `lib/` 文件夹。但有一个关键区别:AAB 的资源以 `resources.pb` 这种 proto 格式存储,而不是 APK 那种扁平的二进制 `resources.arsc` 文件。这也是 AAB 不能被直接安装的一个核心原因。 其他功能模块会与 `base/` 模块并列存放,例如 `onboarding/` 或 `ar_features/`。每个模块都有自己的清单文件和资源,并且可以设置为在安装时下载、安装后立刻下载(fast-follow),或者仅在需要时下载。这种按需下载模式使得像 Google Earth 这样的应用可以避免让每个用户都背负 3D 城市数据的负担,只有当用户真正尝试查看有 3D 覆盖的城市时,应用才会通过 Play Core 库去获取数据。 每个模块内的 `lib/` 目录是实现体积缩减的真正魔法所在。一个跨平台游戏可能包含 `arm64-v8a`、`armeabi-v7a` 和 `x86_64` 等子目录,每个目录里都装满了编译好的 .so 库。一个传统的 APK 会把所有这些库都打包进去。而使用 AAB,动态分发能确保只有与设备匹配的那个 ABI 目录会被发送。对于一个每个 ABI 的原生代码都有 80 MB 的游戏来说,这意味着在现代 64 位手机上能立即节省 160 MB,因为这些手机根本用不到 32 位或 x86 的库。

APK vs AAB:对开发者真正重要的直接比较

那么,这些差异在实践中对开发者、测试人员和用户意味着什么?让我们从日常工作中真正重要的方面来逐一比较。 **分发渠道支持:** Google Play 要求新应用必须使用 AAB。就这么简单。然而,AAB 是谷歌独有的技术。像亚马逊应用商店、三星应用商店、华为应用市场和 F-Droid 这样的第三方安卓应用商店,都要求使用传统的老式 APK。如果你要在 Google Play 之外分发你的应用,那你还是离不开 APK。这一点不容忽视,尤其是在那些 Google Play 无法使用、只能通过 APK 分发的市场。 **直接安装:** 你无法侧载一个 AAB。尝试用 `adb install app.aab` 来安装只会得到一个错误。要在本地测试 AAB,你必须使用谷歌的 `bundletool` 工具来生成一个本地的 APK 集,或者在构建时使用 `--local-testing` 标志。任何一个曾试图让非技术人员测试构建版本的人都知道,增加额外的步骤简直是自找麻烦。这无疑给测试工作流程增加了阻力。 **构建工具:** 在 Android Studio 中,你可以通过“Build > Generate Signed Bundle/APK > Android App Bundle”或 `./gradlew bundleRelease` 任务来创建 AAB。而构建 APK 则是用 `./gradlew assembleRelease`。大多数团队两者都会用,构建 APK 用于内部测试,而 AAB 用于最终上传到 Play 商店。 **磁盘文件大小:** 这是一个常见的误解:你的 AAB 文件几乎总是比你的 APK 文件大。一个 60 MB 的 APK 可能会生成一个 80 MB 的 AAB,因为 AAB 包含了适配*所有*设备配置的资源。只有在 Google Play 施展魔法之后,节省体积的优势才会体现在用户的设备上。 **安全模型:** 两种格式都需要签名,但过程不同。使用 AAB,你必须启用 Play 应用签名 (Play App Signing)。这意味着你上传你的应用包,然后谷歌用它管理的密钥来重新签名最终生成的分割 APK。虽然这个密钥是你注册的,但最终由谷歌持有,这一事实让一些注重安全的团队感到不安。而使用 APK,你可以用自己的密钥来控制整个签名过程,完全无需谷歌的介入。

在 APK 和 AAB 之间转换:哪些可行,哪些不行

在这个问题上,诚实的回答比营销承诺更重要。坦白说:将一个现有的 APK 转回 AAB 根本行不通,你应该对任何声称能自动完成此事的工具持严重怀疑态度。 问题是根本性的。一个 AAB 需要原始的源码信息——那些按屏幕密度和语言整齐组织的资源文件、proto 格式的资源表、模块结构等。所有这些数据在创建 APK 时都被编译、扁平化和优化掉了。APK 中的 `resources.arsc` 文件是一个二进制数据块;原始的 `res/drawable-hdpi/` 文件夹结构已经不复存在。试图从一个编译好的 APK 重建这些信息不是转换,而是一个痛苦的逆向工程过程,其结果几乎总是不完整的。 CocoConvert 是为 APK 到 APK 的操作而构建的。你可以用它来重新打包、重命名,以及最有用的功能——提取 APK 文件的内容进行检查。上传一个 APK,你就可以拉出它的清单文件,查看它的资源表,或者抓取特定的资源。但 CocoConvert 无法从一个 APK 生成一个有效的、可用于 Play 商店的 AAB。老实说,如果你没有原始的源代码项目,没有任何工具能可靠地做到这一点。 如果你丢失了源代码,手上只有一个 APK,你最好的选择是像 `apktool` 这样的工具。它可以将包反编译成 smali 字节码,并为你提供一个近似的资源结构,但要把它变回一个可以构建成 AAB 的正式项目,需要大量的手动工作。 CocoConvert *真正*有用的地方在于处理移动端测试和安全研究中经常遇到的任务。你可以将 APK 转换为 ZIP 文件来浏览其内容,提取特定的图片或音频文件,甚至可以批量处理整个文件夹的 APK 来进行审计。这些才是我们能帮助你完成的、实际的、真实世界的工作。

侧载问题以及为何 APK 不会消失

尽管谷歌大力推广 AAB,但不起眼的 APK 并不会消失。它的生命力来自于那些完全不受谷歌控制的用例。侧载——即从 Play 商店之外安装 APK——是安卓的一个核心功能,只需在手机设置中简单操作即可启用(通常路径是“设置 > 应用 > 特殊应用权限 > 安装未知应用”,但具体路径可能不同)。 而侧载的生态系统是巨大的。APKMirror 网站托管着经过验证的 Play 商店应用的 APK,让用户可以在分阶段发布触及他们之前抢先获得更新,或者安装旧版本。来自 VMware 和微软的企业移动设备管理 (MDM) 工具会向成千上万的公司设备推送 APK,而无需经过 Play 商店。游戏模组社区则完全依赖于修改版的 APK。对于那些 Play 商店访问受限地区的开发者来说,分享 APK 是最主要的分发方式。 对于所有这些用户来说,AAB 根本无关紧要。它是一种只存在于谷歌围墙花园内的格式。一旦一个应用需要在这个生态系统之外被分享、部署或安装,它就必须是 APK 格式。 随着新法规的出台,这一点变得愈发重要。欧盟的《数字市场法案》正迫使苹果和谷歌向第三方应用商店开放。随着第三方安卓市场在欧洲获得发展,它们将需要一个通用的提交格式。由于它们无法接入谷歌专有的动态分发基础设施,这个通用格式就只能是 APK。这可能讽刺地导致 APK 在一些全球最大的市场中重新变得重要起来,即便谷歌在自己的商店里加倍押注 AAB。

根据你的情况给出的实用建议

好了,我们直奔主题。选择哪种格式完全取决于你想做什么。这是一份根据你的角色制定的简单直接的指南。 **如果你要向 Google Play 发布新应用:** 你别无选择。自 2021 年 8 月起,任何新应用都必须提交 AAB。在 Play 管理中心配置好 Play 应用签名(路径:设置 > 应用完整性),设置你的 Gradle 签名配置,然后运行 `./gradlew bundleRelease`。务必使用 `bundletool build-apks --bundle=app.aab --output=app.apks --local-testing` seguido de `bundletool install-apks --apks=app.apks` 在本地进行测试。 **如果你要通过 MDM 向企业设备分发应用:** 坚持使用 APK。用 `./gradlew assembleRelease` 构建一个。你的 MDM 解决方案会直接将 APK 推送到设备上。在这里使用 AAB 毫无益处,只会自寻烦恼。 **如果你要向第三方应用商店分发应用:** 构建 APK。例如,亚马逊应用商店有自己的开发者门户用于上传 APK,也有自己的设备定位逻辑。他们不使用谷歌的系统。 **如果你是测试工程师,正在测试一个构建版本:** 日常的冒烟测试和回归测试请使用 APK;它们速度快,可以直接用 `adb install` 安装。对于发布前的最终验证,你应该构建一个 AAB 并使用 `bundletool` 来确保你测试的是用户最终会从 Play 商店获得的东西。 **如果你需要检查收到的一个 APK:** 你可以把它上传到 CocoConvert 来快速提取其内容,或者使用 Android Studio 自带的 APK 分析器(Build > Analyze APK)。这个分析器能以很好的可视化方式展示文件大小构成,非常适合用来比较两个不同构建版本之间的差异。 归根结底,APK 与 AAB 之争并非要脱离实际地看哪个格式在技术上更优越,而是一个关乎后勤的问题。正确的选择取决于你的分发渠道和你的工具链。这两种格式都将继续存在,服务于庞大的安卓生态系统中不同的路径。