05
2021
06

关于AAB的知识点整理

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
│ BundleConfig.pb
├─base
│ │ assets.pb
│ │ native.pb
│ │ resources.pb
│ ├─assets
│ ├─dex
│ │ classes.dex
│ ├─lib
│ │ └─armeabi-v7a
│ │ libmain.so
│ │ libmonobdwgc-2.0.so
│ │ libMonoPosixHelper.so
│ │ libunity.so
│ ├─manifest
│ │ AndroidManifest.xml
│ └─res
├─BUNDLE-METADATA
│ └─com.android.tools.build.libraries
│ dependencies.pb
└─META-INF
ANDROIDD.RSA
ANDROIDD.SF
MANIFEST.MF

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架构和本地化语言进行拆分。这样的会,用户将不会下载用不到的资源,从而大大减少下载的内容大小。提高下载效率。

clip_image002

在gp平台进行下载安装,或者使用bundletool安装apks的时候,过程如下。

平台或者bundletool首先会判断系统是否支持SplitApk功能,即设备的android版本高于或等于Android Lolipop

如果含有该功能,则根据设备的ScreenDensiny,CPU架构和本地化语言下载对应的分包

clip_image004

通过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

« 上一篇