本文会根据官网的介绍,结合自己的一些理解,来阐述Android App Bundles的相关概念和开发流程。

主要参考文章如下。

  1. https://developer.android.com/guide/app-bundle/
  2. https://developer.android.com/platform/technology/app-bundle/

什么是Android App Bundle

Android App Bundle是一种新的Android App开发,编译和发布机制,它也可以用来表示这种机制生成文件的格式。在文章https://developer.android.com/guide/app-bundle/中并没有明确的区分这两者,它有时表示这种机制,有时表示文件格式。此外,它的写法也很随意,有时用首字母大写的形式Android App Bundle,有时用全小写的android app bundle,有时又把Android或android省掉,变成App Bundle和app bundle,bundle和bundles的单复数使用也很随意。

bundle是一捆,一束的意思,正如这个词的字面意思,Android App Bundle会将整个App编译成一个bundle,在这个bundle里包含了若干个子的模块,每个模块都可以拆分成一个单独的apk。这一点会在后面介绍。

Android App Bundle和Android 9

有人可能认为Android App Bundle和Android 9是捆绑在一起的,但其实并不是,它们两除了都是今年发布的之外并无其他关系。

顺便吐槽下Android Pie的版本号,所有官方文档中都将Android Pie的版本号称为Android 9,而不是Android 9.0,但在这之前的其他版本一直都是有.0的小尾巴的。然后在Android Studio中很多地方选择版本号时,Android Pie的版本号又变成了9.0。

Android App Bundle和Android Studio 3.2

Android Studio 3.2中增加了Android App Bundle的支持,包括在Build中增加了Build Bundles和Generate Signed Bundle的选项,在new module时增加了Dynamic Feature Module的模板等,这些在以前版本中是没有的。所以如果要方便的使用Android App Bundle,需要使用Android Studio 3.2及以上版本。

在Android Studio中使用Android App Bundle来开发

如前所述,Android App Bundle是一种新的Android App开发,编译和发布机制。在Android App Bundle出现之前,开发者开发一个App一般都是在Android Studio中创建一个Phone Module,把App的框架和主要功能的代码写到Phone Module中,创建0到多个Library Module,把一些相对独立的子功能代码写到Library Module,然后将整个工程编译成一个apk文件。apk文件中包含了工程中的全部代码和资源,无论是Phone Module还是Library Module都被编译到了apk文件中。

Android App Bundle在原先的Phone Module和Library Module基础上增加了一个Dynamic Feature Module,可以在开发时创建0到多个Dynamic Feature Module,正如这三个英文单词所表示的,每个Dynamic Feature Module表示一个动态的功能模块,关于这个模块的用途需要结合后面的split APKs和Dynamic Delivery来理解。这里只是介绍它的创建过程。

Dynamic Feature Module的创建

在Android Studio 3.2中,选择File - New - New Module…,打开New Module窗口,选择第三个Dynamic Feature Module,然后选择一个Base application module,输入Module name和Package name,选择Mininum API Level即可创建一个Dynamic Feature Module。Module name,Package name和Mininum API Level的含义和创建其他Module是一样的,这里多出来一个Base application module,它表示这个要创建的Dynamic Feature Module所依附的Base module,它必须是一个application module即在build.gradle中第一行是apply plugin: 'com.android.application’的module,不能是apply plugin: ‘com.android.library’。这一般就是工程的主module。Base module和Dynamic Feature Module的关系同样要到后文介绍split APKs和Dynamic Delivery的时候才能够理解。


创建好后的Dynamic Feature Module后,会在base module的build.gradle中增加android.dynamicFeatures配置,表示依赖此module的所有Dynamic Feature Modules。

android {

// Specifies dynamic feature modules that have a dependency on
// this base module.
dynamicFeatures = [":my_dynamic_feature1", “:my_dynamic_feature2”]
}

在创建的Dynamic Feature Module的build.gradle中,第一行不再是apply plugin: ‘com.android.application’,也不是apply plugin: ‘com.android.library’,而是apply plugin: ‘com.android.dynamic-feature’。同时,在创建的Dynamic Feature Module的build.gradle中还会自动添加对base module的依赖。

dependencies {

// Declares a dependency on the base module, ‘:app’.
implementation project(’:app’)
}

上述过程都是在Android Studio中创建Dynamic Feature Module时自动完成的,无需手动添加。不过如果要修改一个已有的Dynamic Feature Module的名字,并不会自动修改base module中dynamicFeatures配置中的名字,需要手动修改一下,这可能是现阶段Android Studio的一个bug,应该不久就会被修复。

使用Android App Bundle方式来编译

在Android Studio 3.2中,选择Build - Build Bundle(s) / APK(s) - Build Bundle(s)即可使用Android App Bundle方式来编译。如果要生成带签名的Bundle,则选择Build - Generate Signed Bundle /APK…,在弹出的对话框中选中Android App Bundle即可。

使用Android App Bundle方式编译后不再生成apk文件,而是生成一种新的aab格式的文件。

aab文件

aab文件是Android App Bundle编译后生成的文件格式。不同于以往的apk文件,aab文件并不能直接在Android设备上安装和运行,aab格式的文件是专门用来提交到Google Play使用的。Google Play使用后文所说的split APKs机制将一个aab文件转换为若干个apk文件,用户在下载app的时候,再通过Dynamic Delivery将用户需要的apk文件提供给用户。

和apk文件一样,aab文件同样是一个zip格式的压缩文件,可以使用7-zip等工具解压查看。

一个典型的aab文件结构如下,它包含了一个base文件夹和若干个其他文件夹,还有一个BundleConfig.pg文件。base文件夹对应app的application module,也就是主module。其他文件夹每个都对应一个Dynamic Feature Module,文件夹名就是之前创建Dynamic Feature Module使用的module name,这里是my_dynamic_feature1和my_dynamic_feature2。进入到base文件夹或每个Dynamic Feature Module对应的文件夹里,可以看到它们的结构都是一样的,包含dex,manifest,res和root四个文件夹,和一个resources.pb文件,root文件夹又包含kotlin和META-INF两个子文件夹。

将这个结构和apk文件的结构做对比,可以很容易发现它们之间基本是可以对应上的,dex文件夹存放的是apk结构中的classes.dex,manifest文件夹中存放了AndroidManifest.xml,res还是以前的res,root则包含了以前的kotlin和META-INF。从这里可以看出一个app bundle文件包含了工程全部的module代码和资源,但是它将base module和Dynamic Feature Modules独立开来,base module和每个Dynamic Feature Module都包含各自的代码和资源,它们组成了原先apk文件的内容。从后面的介绍可以知道,Google Play确实是将aab文件又重新将base module和Dynamic Feature Modules拆分成单独的apk文件。

集成Play Core Library

如果要使用Dynamic Feature Module,就需要在base module中集成Play Core Library。在后文中会看到,用户在Google Play下载一个通过Android App Bundle 方式开发的应用时,只会下载base module对应的apk文件,Dynamic Feature Module对应的apk文件会在运行时按需下载。

Play Core Library用来在App运行时请求下载Dynamic Feature Module对应的apk,它的使用还是比较复杂的,可以参见官方文档 https://developer.android.com/guide/app-bundle/playcore,这里就不多做介绍了。

multiple APKs

multiple APKs是Google Play支持的一项服务,它允许开发者在为同一个版本的APP提供多个APK文件,这些APK必须使用相同的签名和包名,但version_code必须不同。这些APK在CPU architectures,screen sizes and densities,device feature,platform versions,OpenGL texture compression formats五个维度上存在一处或多处差异,用户在下载APP时会根据设备信息选择最匹配的那个APK来下载。multiple APKs最早似乎叫做Apk splits,后来才称作multiple APKs,不过这点已无法查证,如果读者有知道这段历史的可以说下。关于multiple APKs可以参见这个文章https://developer.android.com/google/play/publishing/multiple-apks。

multiple APK虽然已经存在很久了,但操作和管理起来太复杂。首先它有5个不同的维度,但只有CPU architectures和screen densities支持在gradle中配置,可以用同一个工程一次性编译出不同CPU architectures和screen densities的APK(参见https://developer.android.com/studio/build/configure-apk-splits),其他维度的拆分则需要手动修改manifest,或创建多个工程来分别编译。如果要支持多个维度下的拆分,意味着工作量会呈指数级增长,apk文件的数量也会十分庞大。以下是在Gradle中启用了abi和screen densities后编译得到的apk文件,足足有35个,如果还需要按其他维度拆分,apk的数量会更多。每次打包都要将这几十,甚至上百个不同的apk文件一一上传到Google Play上(Google Play还不支持一次上传多个APK文件),再加上需要使用的不同的版本号,管理起来十分困难。而实际能产生的收益又很小,对CPU architectures,screen sizes and densities来说,只是减少了部分用户下载APP的大小,所以这项特性并没有被广泛使用。

split APKs

Google开发文档中并没有专门关于split APKs的文章,只在介绍app bundle的文章中用了一节来介绍。

在前面介绍Android App Bundle编译时我们知道,Android App Bundle会将一个Android工程编译成一个aab文件,但是aab文件并不能直接在Android设备上使用,必须将其重新组织成apk文件。split APKs就是用来对aab文件进行拆分和重新组装apk文件的一项服务。如前所述,一个aab文件中包含了一个base module和若干个dynamic delivery modules。split APKs会据此将一个aab文件拆分为一个基础APK和若干个功能APK,此外它还允许继续按照屏幕密度,abi和语言对基础APK做进一步的拆分,基础APK会拆分为一个Base APK和若干个Configuration APKs,每个功能APK会拆分为一个Dynamic feature APK和若干个对应的Configuration APKs。也就是说一个aab会被拆分为一个Base APK,若干个Dynamic feature APKs和更多的Configuration APKs。官网文档中的这张图很好说明了一个aab文件经过拆分之后的多个APK之间的联系。

split APKs运行在Google Play服务端,它以aab文件作为输入,每当开发者通过Google Play Console上传一个aab文件,split APKs就会将其拆分成各种apk文件。不过要想支持这种拆分后的APK文件的安装和使用,必须要Android系统的支持,在Android 5.0及之后版本上才支持split APKs。

split APK和上面的multiple APKs完全不是一回事。虽然multiple APKs也可以按照屏幕密度,abi等拆分apk,但multiple APKs机制下每个APK文件都是一个完整的安装包,它在设备上安装后就可以使用应用全部的功能,它的安装和运行也不需要在Android系统上做额外的支持。multiple APKs的生成完全交由开发者实现,Google Play只是在用户下载的时候加了一层判断,根据用户设备选择合适的APK来下载。此外,split APKs和multiple APKs拆分apk的维度也是有所差异的,split APKs支持按照功能来拆分APK,multiple APKs并不支持这一点,反过来multiple APKs支持按照device feature,platform versions,OpenGL texture compression formats来拆分APK,而split APKs并不支持。

Dynamic Delivery

Dynamic Delivery是Google Play新的应用服务模型(Google Play’s new app serving model),这个名词一般用首字母大写的形式。Dynamic Delivery同样运行在Google Play的服务端。

当一个用户通过Google Play商店下载一个App的时候,如果这个App是用app bundle机制生成的(也就是说App开发者上传到Google Play的是app bundle生成的文件,而不是apk文件),Dynamic Delivery就开始工作。它会根据用户的设备信息,来决定要将哪些apk文件分发给用户。此外,当用户运行到某项Dynamic Feature Module的功能,而这个moudle对应的apk又没有安装时,会通过Play Core Library去下载对应的apk文件,这时同样Dynamic Delivery需要根据用户设备信息将需要的Dynamic Feature Module对应的apk及其configration apks分发给用户。

使用App Bundle的优势

  1. 不再需要管理multiple APKs了
  2. 用户要下载的apk体积更小
  3. 按需提供功能,而不是一次性在安装时就全部提供
  4. 允许不安装就直接使用某项功能,需要结合instant run一起使用

更多相关文章

  1. Android文件/文件夹批量蓝牙分享
  2. Android(Java):ndk开发
  3. Android安全卫士-检测升级(一)
  4. Android(安卓)当媒体变更后,通知其他应用重新扫描
  5. Android下使用GDB调试无符号ELF文件
  6. Android(安卓)Studio 配置应用自动签名
  7. mk文件中配置lib arm64 文件夹
  8. Android____View-->Bitmap
  9. Android(安卓)库文件的编译(静态和动态库 Android.mk)

随机推荐

  1. [Android开发实战]Android手势密码(支付宝
  2. android 自定义控件学习之三 控件布局常
  3. android 如何把apk放进系统------unyaffs
  4. Android(安卓)EditText remove focus 只
  5. ANDROID 应用退出
  6. Android中的跨进程通信方法实例及特点分
  7. 定制你自己的Andoird桌面Launcher
  8. android在EditText中插入表情图片
  9. Android中Uri的使用
  10. 8步教你打开Android之门 NDK入门教程