Android App Bundle
Android项目中会有针对不同设备的资源文件,比如根据分辨率不同,drawable会分为drawable-ldpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等文件夹;根据系统版本不同,layout会分为layout-v21、layout-v23等文件夹;根据设备ABI不同,libs分为armeabi-v7a、arm64-v8a等文件夹;根据支持的语言不同,values分为values-zh、values-en等文件夹。
以上的种种资源文件,会随着打包生成的apk,全部带入设备中,这就会导致很多设备用不到的资源文件也会进入设备中,造成包大小增大的后果。
Android提供的App Bundle解决了这个问题,利用Google Play的Dynamic Deliver服务,以及Android5.0开始支持的APK拆分功能,实现了APK的按需拆分和按需下载安装。
- 将原来单一的APK,根据功能模块拆分成base-apk以及dynamic feature module-apk,根据资源文件支持的设备类型生成不同的apk如xxhdpi-apk、armeabi_v7a-apk、zh-zpk等;在下载安装时,会根据设备的类型下载相应的apk,功能模块也只会下发base-apk,而feature-dynamic-module-apk动态模块,可以在需要时调用api进行下载。
AAB
在Android Studio工具栏的Build中,除了可选择Build Apk,也可以选择Build Bundle,编译打包完成后,产物是一个.aab文件,这个文件就是Android App Bundle的产物,是一个压缩类型的文件,我们可以解压缩来看。
- BundleConfig.pb是对整个项目bundle的一些描述和配置,比如打包用的工具的版本等
- BUNDLE-METADATA携带有一些项目信息,如proGuard的mapping等
- base/是装有主module内容的文件夹,包含应用基本功能和资源文件
- 其他的文件夹是dynamic feature module的文件夹,和base/类似,只不过是可以单独下发的功能模块
- 每一个module包括base和dynamic feature module的内部,都和我们的APK结构差不多,包含了assets、lib、dex、res等内容
- *.pb是对不同资源的描述配置文件,用来根据不同设备类型拆分apk使用
aab的整体结构如上图所示,每个功能模块(包括base)结构都一样,包含了对应模块的所有的资源文件和描述配置文件,其中蓝色的部分用来根据不同设备类型,拆分成不同的apk。
APKS
当我们生成签名的aab文件后,只需要和签名信息一起上传至Google Play上,Google Play会自动为我们将aab生成不同的apk文件并签名,然后当用户在Google Play下载时,会根据设备信息,下发对应的多个apk进行安装。
aab生成的文件类型是一个APKS类型的文件,从aab到apks文件的过程,我们可以使用bundletool工具进行测试。官方文档
APKS文件也是个压缩类型的文件,我们可以解压缩来看。
- splits/顾名思义,就是拆分出来的所有apk文件
- standalones/是为不支持拆分apk的设备(5.0以下)提供的独立apk,包含了所有功能,但是仍会对资源类型进行拆分
- base-开头的apk是主module的相关apk,dynamic feature module模块也有相应的apk
- 可以看到base-zh.apk这种就是对语言资源进行了拆分、base-xhdpi.apk就是对分辨率进行了拆分
也就是说,假如一个设备只支持中文,并且是xhdpi分辨率的设备,那么初次下载时,只会下载base-master.apk(基本功能的apk)、base-zh.apk和base-xhdpi.apk文件,而相应apk里只携带相应类型的资源。
通过bundletool工具,可以从.apks文件中,根据不同设备信息提取出不同的apk。
官方文档
Dynamic Feature Module
上面说到的对资源文件拆分,是aab自动实现的,而Android App Bundle还支持对功能模块的自定义拆分,我们可以像添加一个普通module一样简单的添加一个Dynamic Feature Module,这样在打包aab时也会和base一样拆分apk,并在初次下载安装应用时不会被下发,可以在后续通过api手动请求。
官方文档
Android 5.0以下设备
由于拆分APK是在Android 5.0及以上的系统版本才支持,所以在5.0以下的设备上,不能支持动态下载apk,这是会用到我们上面说的standalones/文件夹的apk。
这些apk是包含了所有功能代码和所有资源文件的单一apk,会一次性安装到设备上,虽然无法对一些模块如dynamic feature module、语言资源等进行按需下载,但也会对分辨率和ABI等信息,进行一次拆分,尽可能的保证携带资源少。
5.0以下的支持需要一些配置。官方文档
注意事项
- 如果一个资源id只有一个资源,不管其在哪个设备类型的资源文件夹下,都会带到base-master.apk中,保证所有设备都能访问到该资源。如果该资源有多个(如xhdpi、xxhdpi),那么只会选择最适合设备的那一个带入base-xxconfiguration.apk中
- 有些项目会通过自定义插件修改resource table(resource.arsc)的内容,这个可能会在AAB中产生一些问题
- 由于安装应用时会安装多个apk,所以在我们手动传入apk到设备上时需要注意
- Dynamic Feature Module会生成一些manifest配置项,需要注意配置项的设置官方文档
- 只有搭载 Android 5.0(API 级别 21)及更高版本的设备才支持按需下载和安装Dynamic Feature Module。要使其适用于更低版本的 Android,请确保在创建动态功能模块时启用 Fusing
- Dynamic Feature Module不得在其清单中指定 Activity 并将
android:exported设置为 true。这是因为当其他应用尝试启动相应 Activity 时,无法保证设备已下载相应的Dynamic Feature Module。此外,应用在尝试访问Dynamic Feature Module的代码和资源之前,应该先确认该功能已下载