This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!

Since August, Google has required that all Google Play apps be in AAB’s new format. This isn’t news to me. It was officially announced back in December:

Android-developers.googleblog.com/2020/11/new…

To my surprise, this “old news” is getting a lot of buzz recently, but it turns out it’s because of the heat:

AAB made its debut on GoogleI/O in 2018, and that’s when Google was introduced.

But objectively speaking, although AAB has long appeared, it is rarely mentioned in China, so it is understandable that some media have misinterpreted it. So this article for you to do a popular science about AAB, to dispel the concerns of hongmeng supporters.

Android App Bundle

The Android App Bundle (OR AAB) is a dynamic packaging method that Google launched in 2018. When an application is uploaded to Google Play (or any other aAB-enabled app marketplace) in AAB format, on-demand distribution of features or resources can be implemented for different users. Google Play (GP for short) currently offers dynamic services based on AAB (many articles say that these services are AAB, this is not an accurate statement, it is GP).

  • Play Feature Delivery (PFD) : The on-demand dynamic loading of Feature is realized with the help of AAB, which is similar to the popular “plug-in” technology in China
  • Play Asset Delivery (PAD) : Use AAB to enable dynamic on-demand download of some game materials. This is especially suitable for some game apps. There is no need to keep all the game materials for all models

In addition to game resources, AAB can also deliver regular resources on demand. For example, there is no need to have multiple sets of pictures such as HDPI and XHDPI at the same time, so many apps have significantly improved in terms of package size:

Smaller package sizes mean higher load rates, which is crucial in today’s high cost of user promotion:

App Bundle file format

Let’s start by looking at how AAB’s file format differs from traditional APK

The contents of AAB are similar to those of APK, but there are a few differences:

aab fiels descriptions
base/feature1/feature2 Base is the basic function of the application, and feature carries the content of each DynamicFeature (described later).
manifest.xml APK has only one manifest and is in binary format. AAB will exist in each module e and use ProtoBuf (PB) format for easy processing
dex Unlike APK, AAB stores the dex file for each module in its own directory
res/assets/libs The directories are the same as those in APK. When AAB is uploaded, GP checks these directories and packages only the minimum files that meet the needs of the target device
resources.pb Similar to the resource-. arsc file, it is a resource index table that describes the details of the resources and targets that exist within the application and can be used by GP to configure APK for different devices.
assets.pb The resource table equivalent to application Assets can be used by GP to configure APK for different devices. For example, if the assets resources are placed under the assets/languages#lang_xx or assets/i18n#lang_xx path, the assets resources will be delivered according to the language configuration.
native.pb This is equivalent to a native library resource table that can be used by GP to configure APK for different devices

The last three. Bp files are important parts of the AAB format. They describe the different service targets of the APP and are dynamically delivered from different resources organized in drawable/ HDPI, lib/armeabi-v7a or VALUES/ES.

Split APKs

The Split APKs mechanism is the basis for dynamic delivery of AAB. It allows a large APK to be Split into separate APKs according to different dimensions. When users download applications in GP, the Android Framework communicates with GP through IPC. Matches and downloads the smallest APK for the current device. This is only available for devices with Android 5.0 and above.

After the AAB is uploaded, the GP analyzes the common resources of all devices and generates a Base APK. When users download applications, the Base APK is installed first.

The Configuration APKs that were generated by GP were based on the language, density and ABI, and the versionCode and packageName shared with the Base were also generated by GP. Exists as an application in the process manager.

When the application is downloaded from the market, the GP will issue different values based on the device type to minimize the sale.

The values of that field and that field were different, as shown in the figure below

When the user’s device has a Configuration change (e.g. a system language change), GP will send a new israel-border to the phone. If the phone is offline at this time, the phone will be automatically sent when the next connection is made.

This Split APKs dynamic release will only work on devices older than Android 5.0. For older devices, AAB will generate multiple Standalone APKs based on these mono-matrix, although the Split APKs lack the dynamic release ability and must be installed in place at one time. However, compared to traditional APK, the package size is still reduced by a certain amount.

As developers, we don’t have to worry about these specific delivery policies, we just need to upload an AAB to the market and let the FW and GP handle it from there.

To create the App Bundle

Packaging AAB

AAB can be easily packaged using Android Studio

In addition, you can also use the Gradle command to package, which is more suitable for some CI processes.

Here’s how to package a debug version of AAB using Gradle

. /gradlew :base:bundleDebug
Copy the code

If you want to generate AAB for release you need to configure the signature in the same way as you do for APK.

That list will be generated for that of your Configurations.

bundle {
        language {
            enableSplit = false
        }
        density {
            enableSplit = true
        }
        abi {
            enableSplit = true}}Copy the code

Upload app Marketplace

After the AAB is generated, you can upload the app market. The entry for AAB and APK in GP is together. Of course, there is no entry for APK after August.

After the AAB is uploaded, you can view its details in the background

For example, you can view the screen density supported by AAB, as well as the reduction in packet size

Bundle Tool

AAB cannot be directly installed on mobile phones. If you want to test AAB locally, you need to convert AAB to APK, which requires the Bundletool tool provided by Google

Bundletool can obtain the current device information

bundletool get-device-spec --output=/tmp/device-spec.json
Copy the code

Configurations Output the device Configurations information to the specified JSON

{
  "supportedAbis": ["arm64-v8a"."armeabi-v7a"."armeabi"]."supportedLocales": ["zh-CN"]."deviceFeatures" : // ...
  "screenDensity": 480."sdkVersion": 28
}
Copy the code

Bundletool generates.apks intermediate files from json

bundletool build-apks 
--bundle=/MyApp/my_app.aab 
--output=/MyApp/my_app.apks 
--ks=/MyApp/keystore.jks
--ks-pass=file:/MyApp/keystore.pwd
--ks-key-alias=MyKeyAlias
--key-pass=file:/MyApp/key.pwd
--device-spec=file:device-spec.json

Copy the code

Our products will be separated from that directory and our standalones directory. That directory is Split and must be installed on that directory. Standalone must be installed independently in order to be compatible with Android versions below 5.0.

Toc. pb is an archived listing of APKs, a description file containing APK collection information

Then extract apK from APKS according to json file:

bundletool extract-apks 
--apks=${apksPath} 
--device-spec={deviceSpecJsonPath} 
--output-dir={outputDirPath}

Copy the code

Finally, the APK is installed on the phone via Bundletool. Note The apK command is not apKS

bundletool install-apks --apks=/MyApp/my_app.apks

Copy the code

To summarize the overall process of Bundletool APK generation:

Create a Dynamic Feature

In addition to delivering Configuration APKs, service modules can also be dynamically delivered “plug-in”, which is called Dynamic Features (DF for short).

Select New DF Module from IDE:

Click Next and select when to install DF, such as once in place or on demand

Create a DynamicFeature Module with a directory similar to a normal Gadle Module

However, plugin in build.gradle is different: com.android.dynamic-feature

plugins {
    id 'com.android.dynamic-feature'
    id 'kotlin-android'
}
Copy the code

In build.gradle, there is no need to configure versionCode, versionName, signConfig, etc. DF is essentially Split APKs, so the information of Base APK is shared.

At this point, open app/ build.gradle again, you will find the following configuration

dynamicFeatures = [':dynamicfeature']
Copy the code

This is a statement for all DFS currently supported by the APP

Finally, DF’s Manifeset has also changed:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:dist="http://schemas.android.com/apk/distribution"
    package="com.github.dynamicfeature">

    <dist:module
        dist:instant="false"
        dist:title="@string/title_dynamicfeature">
        <dist:delivery>
            <dist:on-demand />
        </dist:delivery>
        <dist:fusing dist:include="true" />
    </dist:module>
</manifest>
Copy the code
  • Dist :delivery: delivery mode selected when creating the Module of the Dynmaic Feature. OnDemand indicates delivery onDemand
  • Title: Identifies the associated name when the user confirms to download the Module
  • Fusing Include: set to true, which means that devices below 5.0 can install this Feature in multi-APK mode. This Feature must be set to onDemand mode.

Install the Dynamic Feature

Once the application supports DF, I can request and install the Features on demand, which requires integration with the Play Core SDK

implementation 'com.google.android.play:core:$latest_version'
Copy the code

Play Core allows users to interactively request DF downloads and installs and listen for download status

Initiate a download request

DF download requires SplitInstallManager

SplitInstallManager splitInstallManager =
    SplitInstallManagerFactory.create(context);
Copy the code

Create SplitInstallRequest and request to download the Module

// Dynamic request module
SplitInstallRequest request =
    SplitInstallRequest
        .newBuilder()
        .addModule("someDynamicModule")
        .build();
Copy the code

AddModule () can be called multiple times, adding DF for multiple requests

Use SplitInstallManager to start Request and set the callback listener to download

splitInstallManager
        .startInstall(request)
        .addOnSuccessListener {  }
        .addOnFailureListener {  }
        .addOnCompleteListener {  }
Copy the code

The startInstall() call initiates the request immediately. You can also use deferredInstall to delay requests until the application is switched to background startup.

splitInstallManager
      .deferredInstall(Arrays.asList("someDynamicModule"));
Copy the code

In addition to requesting a specified DF, you can also request a specified resource, such as an installation language resource

SplitInstallRequest request =
    SplitInstallRequest.newBuilder()
        .addLanguage(Locale.forLanguageTag(sharedPrefs.getString(LANGUAGE_SELECTION)))
        .build();
Copy the code

CancelInstall (Int) cancelInstall(Int) cancelInstall(Int) cancelInstall(Int) cancelInstall(Int)

After the request is initiated, the link may not be established. In this case, the following error message is displayed

Error Descriptions
ACCESS_DENIED Unable to download due to some reason on the current device
ACTIVE_SESSIONS_LIMIT_EXCEEDED The current application requests too many sessions
API_NOT_AVAILABLE The request API is currently unavailable
INCOMPATIBLE_WITH_EXISTING_SESSION The requested session contains the requested DF
INTERNAL_ERROR Internal error
INVALID_REQUEST Invalid request
MODULE_UNAVAILABLE The requested DF does not exist
NETWORK_ERROR Network error
NO_ERROR Unable to get error message
SERVICE_DIED Service not responding
SESSION_NOT_FOUND Failed to obtain the requested session

Download and install

After the connection is successfully established, the download and installation stage will be entered. Using SplitInstallStateUpdatedListener can download and install the state monitoring, can according to the status to prompt to download progress of users

val stateListener = SplitInstallStateUpdatedListener { state ->
    when (state.status()) {
        PENDING -> { }
        DOWNLOADING -> { }
        DOWNLOADED -> { }
        INSTALLED -> { }
        INSTALLING -> { }
        REQUIRES_USER_CONFIRMATION -> { }
        FAILED -> { }
        CANCELING -> { }
        CANCELED -> { }
    }
}
splitInstallManager.registerListener(stateListener)
Copy the code
State Description
CANCELED Download cancelled
CANCELING Download cancelled
DOWNLOADED Download completed, but not yet installed
DOWNLOADING The download is almost complete
FAILED Download or installation failed
INSTALLED Successful installation
INSTALLING In the installation
PENDING Download waiting
REQUIRES_USER_CONFIRMATION Waiting for user confirmation
UNKNOWN The unknown

Uninstall the module

After successful installation, you can get all the installed Modules through getInstalledModules

val installedModules = splitInstallManager.installedModules
Copy the code

In addition, DF can be explicitly uninstalled with Deferring Install

splitInstallManager
        .deferredUninstall(listOf("someDynamicModule"))
        .addOnSuccessListener {  }
        .addOnFailureListener {  }
        .addOnCompleteListener {  }

Copy the code

AAB effect

According to Google, AAB’s average packet size is 20% smaller than APK’s, which means 20% less download traffic. Take Twitter, for example, after adopting AAB

  • Save 95% of language related resources
  • Our values will save 45% on that field
  • 20% savings on ABI-related resources

In addition to the package size advantage, there’s also the efficiency benefit of using AAB. Instead of configuring multiple flavors and generating multiple APKs for different target devices, you can upload only one AAB and let the marketplace do the rest.

Domestic AAB use

Qigsaw is a dynamic solution based on Android App Bundle provided by iQiyi. You can experience the Android App Bundle development tool in China without Google Play Service. It supports dynamic delivery of plug-in APK, using a single class loader, so that applications can dynamically install plug-ins without reinstallation.

In addition, Huawei application market has long supported AAB upload and dynamic delivery, so don’t say that AAB is a product of huawei to suppress 😅

Developer.huawei.com/consumer/cn…