Android 应用包格式

Android 应用包是一个文件(文件扩展名为 .aab),您将其上传到 Google Play。

应用包是已签名的二进制文件,将您应用的代码和资源组织到模块中,如图 1 所示。每个模块的代码和资源的组织方式类似于您在 APK 中找到的内容——这很有道理,因为这些模块中的每一个都可能生成独立的 APK。然后,Google Play 使用应用包生成提供给用户的各种 APK,例如基本 APK、功能 APK、配置 APK 以及(对于不支持拆分 APK 的设备)多 APK。用蓝色着色的目录(例如 drawable/values/lib/ 目录)表示 Google Play 用于创建每个模块的配置 APK 的代码和资源。

App bundles organize your app into directories that each represent a
        module. Within each module directory, code and resources are organized
        similar to that of a typical APK.

图 1. 一个 Android 应用包的内容,包含一个基本模块、两个功能模块和两个资产包。

以下列表更详细地描述了应用包中的一些文件和目录

  • base/、feature1/ 和 feature2/: 这些顶层目录中的每一个都代表应用的不同模块。应用的基本模块始终包含在应用包的 base 目录中。但是,每个功能模块的目录都使用模块清单中指定的 split 属性来命名。要了解更多信息,请阅读有关 功能模块清单 的内容。
  • asset_pack_1/ 和 asset_pack_2/: 对于大型的、图形需求高的应用或游戏,您可以将资产模块化到资产包中。资产包非常适合游戏,因为它们有较大的大小限制。您可以根据三种交付模式定制每个资产包如何以及何时下载到设备上:安装时、快速跟进和按需。所有资产包都托管在 Google Play 上并从 Google Play 上提供服务。要了解有关如何将资产包添加到应用包的更多信息,请参阅 Play 资产交付概述
  • BUNDLE-METADATA/: 此目录包含元数据文件,其中包含对工具或应用商店有用的信息。 这些元数据文件可能包括 ProGuard 映射和应用所有 DEX 文件的完整列表。 此目录中的文件不会打包到应用的 APK 中。
  • 模块协议缓冲区 (*.pb) 文件: 这些文件提供元数据,有助于描述每个应用模块的内容以供应用商店使用,例如 Google Play。 例如,BundleConfig.pb 提供有关捆绑包本身的信息,例如用于构建应用捆绑包的构建工具版本,以及 native.pbresources.pb 描述每个模块中的代码和资源,这在 Google Play 为不同的设备配置优化 APK 时很有用。
  • manifest/: 与 APK 不同,应用捆绑包将每个模块的 AndroidManifest.xml 文件存储在此单独的目录中。
  • dex/: 与 APK 不同,应用捆绑包将每个模块的 DEX 文件存储在此单独的目录中。
  • res/, lib/, and assets/: 这些目录与典型 APK 中的目录相同。 当您上传应用捆绑包时,Google Play 会检查这些目录并仅打包满足目标设备配置的文件,同时保留文件路径。
  • root/: 此目录存储的文件稍后将被重新定位到包含此目录所在模块的任何 APK 的根目录。 例如,应用捆绑包的 base/root/ 目录可能包含应用使用 Class.getResource() 加载的基于 Java 的资源。 这些文件稍后将被重新定位到应用基本 APK 和 Google Play 生成的每个多 APK 的根目录。 此目录内的路径也保留。 也就是说,目录(及其子目录)也会被重新定位到 APK 的根目录。

拆分 APK 概述

提供优化应用程序的基本组成部分是 Android 5.0(API 级别 21)及更高版本上提供的 *拆分 APK* 机制。 拆分 APK 与常规 APK 非常相似——它们包含已编译的 DEX 字节码、资源和 Android 清单。 但是,Android 平台能够将多个已安装的拆分 APK 视为单个应用。 也就是说,您可以安装多个拆分 APK,这些 APK 可以访问公共代码和资源,并在设备上显示为一个已安装的应用。

拆分 APK 的好处是能够将单片 APK(即包含应用支持的所有功能和设备配置的代码和资源的 APK)分解成更小的离散包,这些包根据*需要*安装在用户的设备上。

例如,一个拆分 APK 可能包含仅少数用户需要的附加功能的代码和资源,而另一个拆分 APK 包含仅针对特定语言或屏幕密度的资源。 这些拆分 APK 中的每一个都在用户请求时或设备需要时下载和安装。

下面介绍了可能一起安装在设备上以形成完整应用体验的不同类型的 APK。 您将在本页后面的部分中了解如何在应用项目中配置以支持这些 APK。

  • 基本 APK: 此 APK 包含所有其他拆分 APK 可以访问的代码和资源,并提供应用的基本功能。 当用户请求下载应用时,此 APK 会首先下载和安装。 这是因为只有基本 APK 的清单包含对应用服务、内容提供程序、权限、平台版本要求以及对系统功能的依赖关系的完整声明。 Google Play 从项目的应用(或基本)模块生成应用的基本 APK。 如果您担心减少应用的初始下载大小,请务必牢记,此模块中包含的所有代码和资源都包含在应用的基本 APK 中。
  • 配置 APK: 每个 APK 包含针对特定屏幕密度、CPU 架构或语言的原生库和资源。 当用户下载应用时,他们的设备只下载和安装针对其设备的配置 APK。 每个配置 APK 都是基本 APK 或功能模块 APK 的依赖项。 也就是说,它们会与提供代码和资源的 APK 一起下载和安装。 与基本模块和功能模块不同,您无需为配置 APK 创建单独的模块。 如果您使用标准做法来 组织基本模块和功能模块的备用、特定于配置的资源Google Play 会自动为您生成配置 APK
  • 功能模块 APK: 每个 APK 包含应用功能的代码和资源,您可以使用功能模块对其进行模块化。 然后,您可以自定义该功能如何在设备上下载以及何时下载。 例如,使用 Play Core 库,可以在将基本 APK 安装到设备后按需安装功能,以便为用户提供其他功能。 考虑一个聊天应用,它只在用户请求使用该功能时才下载和安装捕获和发送照片的功能。 由于功能模块可能在安装时不可用,因此您应该在基本 APK 中包含任何常用代码和资源。 也就是说,您的功能模块应该假设只有基本 APK 的代码和资源在安装时可用。 Google Play 从项目的特性模块生成应用的特性模块 APK。

考虑一个具有三个功能模块并支持多种设备配置的应用。 下面的图 1 说明了应用各种 APK 的依赖关系树可能是什么样子。 请注意,基本 APK 构成了树的头部,所有其他 APK 都依赖于基本 APK。(如果您好奇这些 APK 的模块如何在 Android 应用捆绑包中表示,请参阅 Android 应用捆绑包格式。)

The base APK is at the head of the tree with feature module APKs having
        a dependency on it. Configuration APKs, which include device
        configuration-specific code and resources for the base and each
        feature module APK, form the leaf nodes of the dependency tree.

图 1. 使用拆分 APK 提供服务的应用的依赖关系树

请记住,您无需自己构建这些 APK——Google Play 会使用您使用 Android Studio 构建的单个签名应用捆绑包为您完成此操作。 要详细了解应用捆绑包格式以及如何构建应用捆绑包,请访问 构建、部署和上传 Android 应用捆绑包

运行 Android 4.4(API 级别 19)及更低版本的设备

由于运行 Android 4.4(API 级别 19)及更低版本的设备不支持下载和安装拆分 APK,因此 Google Play 反而会为这些设备提供一个名为 *多 APK* 的单个 APK,该 APK 已针对设备的配置进行了优化。 也就是说,多 APK 代表您的完整应用体验,但不包含不必要的代码和资源(例如针对其他屏幕密度和 CPU 架构的代码和资源)。

但是,它们确实包含应用支持的所有语言的资源。 这允许用户(例如)更改应用的首选语言设置,而无需下载不同的多 APK。

多 APK 没有能力在以后按需下载功能模块。 要在此 APK 中包含功能模块,您必须在 创建功能模块 时禁用 **按需** 或启用 **融合**。

请记住,使用应用捆绑包,您无需为应用支持的每种设备配置构建、签名、上传和管理 APK。 您仍然只需要为整个应用构建和上传一个应用捆绑包,Google Play 会为您处理其余工作。 因此,无论您是否计划支持运行 Android 4.4 或更低版本的设备,Google Play 都为您和您的用户提供了灵活的服务机制。

用户语言更改

使用应用捆绑包,设备仅下载运行应用所需的代码和资源。 因此,对于语言资源,用户的设备仅下载与设备设置中当前选择的语言匹配的应用语言资源。

当用户在设备设置中切换语言时,Google Play 可能需要下载和安装一些额外的拆分 APK,应用才能以新语言显示。

Google Play 会尝试在切换后立即下载其他语言。 如果用户设备处于脱机状态、下载失败或资源太大,Google Play 会在设备条件更适合时尝试在后台再次下载。 在运行 Android 9.0(API 级别 28)或更低版本的设备上,如果应用在安装新语言拆分 APK 时处于前台,则应用会被杀死。

如果您的应用需要所有语言始终在设备上可用,您可以 在构建配置中禁用语言拆分

如果您的应用需要独立于设备设置中选择的用户语言下载其他语言(例如,为了实现应用内语言选择器),您可以使用 Play Core 库 按需下载它们