2018年,google推出了aab技术。在此之后google发布通知:从 2021 年 8 月起,新应用需要使用 Android App Bundle 才能在 Google Play 中发布。
这意味着以GP为主要平台的海外版本,都需要使用aab。那么什么是aab,和apk有什么不同呢?
aab官方介绍:https://developer.android.com/guide/app-bundle
简单地说aab就是一个带有很多分包数据的压缩包。它将一个apk拆分了多个小包,比如按CPU架构拆分,按语言拆分等等,最终移动设备安装时只需要下载需要的分包即可。
apk可以直接安装到用户的设备上,但是aab只是一种发布格式,所以不能直接安装。但是可以使用bundletool命令行连接设备进行模拟安装。
技术细节
aab的数据格式
上面提到,aab其实是一个压缩包,它包含了一系列的文件。下图显示了一个aab文件内部的组成:
aab |
aab存在的目的是为了拆分出一系列的apk文件。为了能够拆分出来,首先就需要收集数据文件,并对数据文件进行整理,标记每个文件的作用。另外还需要配置拆分的规则。
其中所有的pb文件,其数据结构都可以在以下地址找到:
https://github.com/google/bundletool/blob/master/src/main/proto
base目录
在base目录下,我们会发现很多文件和apk大部分是相同的,但是用途又有点不同。
数据文件
- manifest.xml:它和apk中的一样,都是一些配置项。但不同的是,apk中这个文件是二进制的格式,而aab中用的是pb格式。
- res目录/assets目录/libs目录/dex目录:和apk是相同的组织形式,唯一的区别是res目录下的配置文件,全部也是用的pb格式
标记数据
- assets.pb
- native.pb
- resources.pb
assets.pb,native.pb,resources.pb是base中核心的内容,它列举了整个base下所有文件的组成信息,比如某个文件用于某个ScreenDensity(HDPI,XHDPI,XXHDPI之类),或者某个so文件用于某个CPU架构等等。有了这些数据,在拆分apk的时候,就可以将不同的文件拆分到不同的apk中。
BundleConfig.pb
buildconfig用于配置拆分的规则,见https://github.com/google/bundletool/blob/master/src/main/proto/config.protoh
其中也包含了很多的优化项,部分采用gradle进行打包aab的时候会影响到buildconfig的数据,比如UncompressNativeLibraries
https://developer.android.com/studio/releases/gradle-plugin#4-0-0-issues
构建 Android App Bundle 时,由以 Android 6.0(API 级别 23)或更高版本为目标平台的 App Bundle 生成的 APK 现在默认包含原生库的未压缩版本。这项优化无需设备创建库的副本,因此减少了应用占用的存储空间。如果您想要停用此优化,请在 gradle.properties 文件中添加以下代码: android.bundle.enableUncompressedNativeLibs = false |
另一个在gradle工程里面影响拆分配置是的build.gradle文件下的bundle模块,如(unity2018默认生成)
bundle { language { enableSplit = false } density { enableSplit = false } abi { enableSplit = true } } |
这会影响最终的拆包,不会做语言的拆分和density的拆分。如果在unity中含有多国语言或者多个ScreenDensity,那么可以在PlayerSetting的Publishing Setting中勾选Custom Gradle Template,修改这个值
注意:如果使用的是bundltool打包aab,因为没有gradle相关的文件,所以需要修改buildconfig.json,新增UncompressNativeLibraries=false的配置。见用bundletool打包aab
2、拆分apk:aab到apks
在android lolopop以上,会有SplitApks的功能。它允许一个应用程序可以分散在多个apk中,但是运行起来仍然是一个程序。因此,aab利用这一机制,将aab文件拆分为多个apk,最终根据用户设备,按需安装必要的apk即可。
aab一般来说会根据ScreenDensity,CPU架构和本地化语言进行拆分。这样的会,用户将不会下载用不到的资源,从而大大减少下载的内容大小。提高下载效率。
在gp平台进行下载安装,或者使用bundletool安装apks的时候,过程如下。
平台或者bundletool首先会判断系统是否支持SplitApk功能,即设备的android版本高于或等于Android Lolipop
如果含有该功能,则根据设备的ScreenDensiny,CPU架构和本地化语言下载对应的分包
通过bundletool,可以将aab转为一个叫做apks的文件,它也是一个压缩包
在这个包里面文件结构如下(为了方便删除了一些本地化语言的apk),可以在splits下发现有很多的分包apk。
而对于Android lolipop之前,则会使用standlones里面的apk
apks │ toc.pb ├─splits │ base-af.apk │ base-am.apk │ base-ar.apk │ base-arm64_v8a.apk │ base-armeabi_v7a.apk │ base-as.apk │ base-az.apk │ base-hdpi.apk │ base-ldpi.apk │ base-lo.apk │ base-lt.apk │ base-lv.apk │ base-master.apk │ base-mdpi.apk │ base-mk.apk │ base-tr.apk │ base-tvdpi.apk │ base-uk.apk │ base-ur.apk │ base-uz.apk │ base-vi.apk │ base-xhdpi.apk │ base-xxhdpi.apk │ base-xxxhdpi.apk │ base-zh.apk │ base-zu.apk| └─standalones standalone-arm64_v8a_hdpi.apk standalone-arm64_v8a_ldpi.apk standalone-arm64_v8a_mdpi.apk standalone-arm64_v8a_tvdpi.apk standalone-arm64_v8a_xhdpi.apk standalone-arm64_v8a_xxhdpi.apk standalone-arm64_v8a_xxxhdpi.apk standalone-armeabi_v7a_hdpi.apk standalone-armeabi_v7a_ldpi.apk standalone-armeabi_v7a_mdpi.apk standalone-armeabi_v7a_tvdpi.apk standalone-armeabi_v7a_xhdpi.apk standalone-armeabi_v7a_xxhdpi.apk standalone-armeabi_v7a_xxxhdpi.apk |
3、bundltool
上面我们说了很多的bundltool,这里提一下这个工具,Github地址:https://github.com/google/bundletool
可以从releases下载最新的版本
它的作用主要是(其他功能请自行参考github):
- 打包aab
- 通过aab转apks
- 安装apks到设备
在这个文章中介绍了bundletool进行打包的内容:https://developer.android.com/studio/build/building-cmdline#bundletool-build
在这个文章中介绍了后2个内容:https://developer.android.com/studio/command-line/bundletool
要注意的是,aab转apks的时候需要进行签名,否则将无法安装
链接整理
官方介绍:https://developer.android.com/guide/app-bundle
官方博文:https://medium.com/google-developer-experts/exploring-the-android-app-bundle-ca16846fa3d7
BundleTool:https://github.com/google/bundletool
BundleTool的prop数据格式:https://github.com/google/bundletool/blob/master/src/main/proto
BundleTool打包aab:https://developer.android.com/studio/build/building-cmdline#bundletool-build
BundleTool安装测试:https://developer.android.com/studio/command-line/bundletool
UncompressNativeLibraries问题:https://developer.android.com/studio/releases/gradle-plugin#4-0-0-issues