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