Starting in August 2021, new apps will need to use the Android App Bundle to be released on Google Play. Play Feature Delivery or Play Asset Delivery now supports new apps over 150 MB in size.

Due to Google Play’s policy requirements, more and more projects are investigating the problems of AppBundle recently.

What is an App Bundle

The Android App Bundle is a publishing format that contains all of the compiled code and resources of the App, leaving APK generation and signing to Google Play. Google mainly wants to optimize APK volume, dynamic distribution and other functions through App Bundle, by means of Split APKs.

As you can see from the figure below, resources are distributed among modules, and each module is organized in a similar way to APK because eventually each module can be generated as a separate APK.

The AppBundle in Figure 1 contains a base module, two function modules, and two resource bundles.

More detailed directory structure:

  • Base /, Feature1 /, and Feature2 / : Each of these top-level directories represents a different application module. The base modules of the App are always contained in the Base directory of the App Bundle. However, the name provided for the directory for each functional module is specified by the split attribute in the module manifest. For details, see the list of functional modules.

  • Asset_pack_1 / and ASset_pack_2 / : For large applications or games that require a lot of graphics, you can modularize assets as resource packs. Resource packs are ideal for games because of their high size caps. You can customize how and when individual resource packs are downloaded to the device in three distribution modes (i.e., install-time distribution, fast-follow distribution, and on-demand distribution). All resource packs are hosted on And provided from Google Play. Learn more about how to add resource bundles to your App Bundle.

  • Bundle-metadata / : This directory contains METADATA files that contain information useful to tools or the app store. Such metadata files may contain a complete list of DEX files for ProGuard mappings and applications. Files in this directory are not packaged into your application’s APK.

  • Module protocol Buffer (*.pb) files: These files provide metadata that helps explain the contents of each application module to various app stores, such as Google Play. For example, BundleConfig. Pb provides information about the bundle itself (such as the version of the build tool used to build app bundles), while Native. pb and resources.pb describe the code and resources in each module, This is useful when Google Play optimizes APK for different device configurations.

  • Manifest / : Unlike APK, app Bundle stores the Androidmanifest.xml file for each module in this separate directory.

  • Dex / : Unlike APK, App Bundle stores the dex files for each module in this separate directory.

  • Res /, lib/, and assets/ : These directories are exactly the same as those in a typical APK. When you upload your App Bundle, Google Play checks these directories and packages only files that meet the configuration requirements of the target device, while preserving the file path.

  • Root / : Files stored in this directory will then be relocated to the root of any APK containing the module in which this directory resides. For example, the Base /root/ directory of the App Bundle might contain Java-based resources that your application loads using class.getResource (). These files are then repositioned to the root of your application’s base APK and each multiple APK generated by Google Play. The paths in this directory are also retained. That is, the directory (and its subdirectories) is also repositioned to the root of APK.

Split APKs

After AppBundle organizes resources in this manner, it is easy to split APK. Splitting APK can be considered in two dimensions:

1. According to the resources required by the model, it is divided into different APKs

Since there are many types of Android phones, different resources need to be adapted: ABI (Armeabi Armeabi-V7A ARM64-V8A x86..) Screen density language. Eventually all resources are packaged into apK.

Take the res lib folder in the above APK as an example, we can see that in the past, the APK we packaged included all the above resources, and the volume of so library + image layout resources accounted for a large proportion in the whole APK.

But in fact, each mobile phone only needs one corresponding resource from all dimensions: for example, if the CPU is Armeabi-V7A, you only need to download the SO library of Armeabi-V7A; Screen PPI is 400 only need to download xxXHDPI picture layout resources; Chinese language users only need to download Chinese language resources. Refer to the following figure:

2. Divide into different APKs according to basic functions and additional functions

Only basic functions need to be downloaded for the first time, and additional functional modules can be downloaded when needed.

Based on the above two dimensions, Google Play packages AppBundles into three types of APKs

  • Basic APK:

This APK contains code and resources that are accessible to all other split APKs and provides the basic functionality of the application. When a user requests to download your application, the APK is downloaded and installed first. This is because only the listing of the basic APK contains complete declarations of the application’s services, content providers, permissions, platform version requirements, and dependencies on system functionality. Google Play generates a basic APK for an app based on the project’s application module (the base module). If you want to reduce the initial download size of your application, it is important to note that all the code and resources contained in this module are included in your application’s base APK.

  • Configure the APK

Each configuration APK contains native libraries and resources for a particular screen density, CPU architecture, or language. When a user downloads your application, their device will only download and install the configuration APK for that device. Each configuration APK is a dependency of the base APK or function module APK. That is, the configuration APK is downloaded and installed along with the APK for which they provide the code and resources. Unlike basic and functional modules, you do not need to create separate modules for configuring APK. If you follow standard practice in organizing and managing the provisioning of dedicated standby resources for basic and functional modules, Google Play will automatically generate the provisioning APK for you.

  • Function module APK:

Each function module APK contains the code and resources for an application function that you modularize using a function module. You can then customize how and when to download this functionality to the device. For example, with the Play core library, some functionality can be installed on demand after the basic APK is installed on the device to provide additional functionality to the user. Let’s say we have a chat application that downloads and installs the feature only when the user wants to take and send a photo. Because function modules may not be available at installation time, you should include all common code and resources in the base APK. That is, your feature modules should assume that only basic APK code and resources are available at installation time. Google Play generates a feature block APK for an app based on the project’s feature block.

An application that contains three functional modules and supports multiple device configurations has the following dependency tree between APKs:

Build, test, and configure the AppBundle

Build AppBundle

Similar to the previous packaging of APK, the assemble command replaces the bundle. Such as

./gradlew assembleProductionRelease
 ->  
./gradlew bundleProductionRelease
Copy the code

Test AppBundle

  • Deploying appBundles through Google Play’s test channel is cumbersome and requires formal configuration

  • This is recommended for testing by deploying the AppBundle through Google Play’s internal sharing channel and delivering it to testers. It can be uploaded directly to share downloads with.aab and has fewer restrictions than the testing channel: App signatures and versionCode are not restricted. Refer to the below

  • Use the command line toolbundletool
    1. Generate apks
    // The default debug signature bundletool build-apks --bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks // Or specify the signature bundletool build-apks --bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apksCopy the code

–ks=/MyApp/keystore.jks –ks-pass=file:/MyApp/keystore.pwd –ks-key-alias=MyKeyAlias –key-pass=file:/MyApp/key.pwd

“`

2. Deploy apK from APKS to device bundletool install-apks --apks=/MyApp/my_app.apksCopy the code
Some configuration when generating APKS

When apKS is generated by default, all related configuration sets are packaged into APK. Generally, only the APK of a specific model is required for testing. There are several configuration methods:

  • Only APKs connected to adb models are generated
bundletool build-apks --connected-device
--bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks
Copy the code
  • Generate a JSON file describing the model configuration
bundletool get-device-spec --output=/tmp/device-spec.json
Copy the code

Then configure this when generating APKs

bundletool build-apks --device-spec=/MyApp/pixel2.json
--bundle=/MyApp/my_app.aab --output=/MyApp/my_app.apks
Copy the code

You can also manually generate or adjust the JSON file for the model configuration

{ "supportedAbis": ["arm64-v8a", "armeabi-v7a"], "supportedLocales": ["en", "fr"], "screenDensity": 640, "sdkVersion": 27}Copy the code

Reference documents for configuring other parameters

Extracts the specified APK from APKs

In addition to APKs that only generate APKs for a specific model, you can also extract specific APKs from APKs for easy installation and estimation of APK size, etc.

Extract the specified APK:

bundletool extract-apks
--apks=/MyApp/my_existing_APK_set.apks
--output-dir=/MyApp/my_pixel2_APK_set.apks
--device-spec=/MyApp/bundletool/pixel2.json
Copy the code

Estimate the size range of APK after it is installed on the device (you can also specify the configuration reference document manually)

bundletool get-size total --apks=/MyApp/my_app.apks
Copy the code

Principles and practical effects of AppBundle

The biggest difference of AppBundle technology is that it used to be installed directly with an APK. Now it is packaged as an AppBundle and then packaged as APKs and installed according to device configuration. The following is a practical test of the difference.

Android developers should be aware that installed APK is actually placed in an APP’s private directory (/data/ APP). Take the Demo project as an example, package apK directly and install it into the emulator:

You can see that there is only one base.apk in the installation directory, which is 23.5MB. Then I pack an AppBundle and use Bundletool to generate APKs and view the contents

You can see that there are many APKs generated according to different dimensions in the. APKs are actually the set containing all split APKs.

Next, after installing from APKs to emulator with the command, look at the installation directory.

As you can see, the contents of the installation directory are different and have been split into multiple APKs for installation. There are base.apk split_config.en.apk split_config.x86.apk split_config.xxhdpi.apk and some other files such as so library and dex.

  • Base. apK: base APK
  • Split_config.en. apk Resources in the English language
  • Split_config.x86. apk Configuration of the x86 architecture
  • Split_config.xxhdpi. apk Specifies the xxhdPI required by the device
  • Lib /x86 So library used under x86 architecture
  • Oat /x86/base.art base.odex base. Vdex corresponds to the previous dex file

Compare the total size difference between apK installed directly and the split installed by AppBundle

It can be seen that the difference between the two is 16.5MB and (7.5MB-14.8MB) (which means the apK size range installed according to different models). For the APP that does not use much SO library and image resources, the volume can be reduced by up to 50%+, and the gap of other apps may be larger, so the effect is still obvious. And the volume can be optimized after downloading and installing to the device.

Play Feature Delivery:

In addition, split APK can also realize the function of dynamic delivery, the first installation only download the basic APK, non-essential module dynamic download. (dependent on Google Play store) I have not actually used this, please refer to the document Play Feature Delivery

The limitation of AppBundle
  • The Android 5.0

Android does not support the installation of split APK until later than 5.0, so the following features are not fully available, but developers should not be too concerned, Google Play will generate the appropriate APK to use.

  • Oob format

    The common ooB format for games is no longer supported, and asset_pack is recommended instead

AppBundle signature replacement

The signing process of some projects is that after we sign APK, the client will sign again and upload it to Google Play: AppBundle format cannot be signed with Apksinger, but can be changed to Jarsigner. Another approach is to refer to the Play signature scheme, which will be mentioned later

Play App signature plan

Google Play has always had a Play app signature program, which used to be ignored but is mandatory if you use AppBundle. One reason is that after we upload the AppBundle, Google Play needs to package it into APKs, so we need to give the signature to Google Play.

The Play App Signature plan uses two keys: the App signature key and the upload key. The upload key is used to verify the identity of the.aab/.apk we uploaded to Google, and the App signature key can be signed to the App as before.

Principle reference:

There are two options for applying the signature key:

  1. Upload the encrypted key to Google Play, and Google Play signs with the key.

  2. Upload the encrypted key to Google Play, but Google Play will generate another set of key to sign APK. The key we uploaded is only used to verify AppBundle.

    • Bonus: In case our key is lost or stolen, we just need to prove our identity and then we can continue to use the signature generated by Google Play or, in the first case, change the signature.
    • Disadvantages: 1. If we want to publish APK with our own key signature in other stores or official websites, we cannot overwrite the installation because the signature is different from Google Play. 2. Some SDKS, such as the Rakuten IDSDK we used, need to authenticate the identity according to the certificate fingerprint, which needs to be replaced with the fingerprint of the real signature.

The key must be encrypted with PEPK and uploaded:

In addition, the requirement of replacing the signature mentioned above can also be realized by distinguishing the upload key from the signature. The key of our packaged AppBundle is set to the upload key in the Play signature plan, and the key actually packaged by the customer is set to the application signature key, so the original requirement of re-signing can be realized.

conclusion

In general, if our APP engineering structure is standard and does not use too much black tech (special cases may fail to package, etc., need special check), it is very easy to get a large APK volume compression optimization at a low cost, which is still cost-effective. And Google Play mandates it, so don’t worry about using it. The project has been using the AppBundle format for a while without major problems. In addition, through AppBundle, I think we can have some ideas to split modules when developing apps in the future. In this way, you can try features like Play Feature Delivery and Instant App (App installation is not required).

Reference: developer.android.com/guide/app-b… Developer.android.com/studio/comm… Developer.android.com/guide/app-b… Developer.android.com/guide/app-b… Support.google.com/googleplay/…