Bundletool and how to utilize Android App Bundle

Reading Time: 6 minutes

The App Bundle is the new official publishing format that app developers use to publish their apps on Google Play as opposed to APK, the traditional way that was done for over 10 years of android’s history.

Splitting the Publishing from the Serving format

In the past, app developers uploaded monolithic APKs to Google Play, and the channel acted like a dumb pipe that did the distribution to the users.

But with the App Bundle, a conscious decision was made to split the publishing format and the serving format. Developers now put everything in this publishing format, and then Google Play processes it and generates optimised APKs to serve the best possible APK to the end device.

The contents of an Android App Bundle with one base module, two dynamic feature modules, and two asset packs.
(source android-developers)

Testing Android App Bundle

This is where the bundletool comes in. It is actually the underlying tool that Google Play and the Android Gradle plugin use to build .aab files. This tool is also available as a command-line tool so that developers can test their app locally and emulate Play server-side build and test out Play App Delivery or Asset Delivery flows, before uploading the artefact.

The tool has a few different responsibilities that help developers manipulate Android App Bundles:

  • Build an Android App Bundle from pre-compiled modules of a project.
  • Generate an APK Set archive containing APKs for all possible devices.
  • Extract APK(s) from the APK Set compatible with a given device.
  • Install APK(s) from the APK Set compatible with a connected device.
  • Extract device spec from a device as a JSON file.
  • Add code transparency to an Android App Bundle. Code transparency is an optional code signing mechanism.
  • Verify code transparency inside an Android App Bundle, APK files or an application installed on a connected device.

How to build APK sets from App Bundle

The command build-apks is used to build an APK set for the bundle. It will contain all the APKs for all the modules in the project.

bundletool build-apks 
--bundle=/ExampleApp/example_app.aab 
--output=/ExampleApp/example_app.apks

If the APKs were installed on a device, they would need to be signed with a private key, all the APKs contained in the APK set will be signed and installable. Note, if signing information is not specified, bundletool will attempt to sign the APK with a debug key.

bundletool build-apks 
--bundle=/ExampleApp/example_app.aab 
--output=/ExampleApp/example_app.apks
--ks=/ExampleApp/keystore.jks
--ks-pass=file:/ExampleApp/keystore.pwd
--ks-key-alias=ExampleKeyAlias
--key-pass=file:/ExampleApp/key.pwd

Generating APK sets for devices

You can target a device by specifying its configuration in a JSON file. This file can be created manually with specifying information about supported Application Binary Interfaces (ABIs), Locales, Device Features, OpenGL Implementations, Device Screen Density and the SDK version. Or just simply delegate this work to the useful command of bundletool, get-device-spec.

{
  "supportedAbis": ["arm64-v8a", "armeabi-v7a", "armeabi"],
  "supportedLocales": ["en-US", "de-DE", "mk-MK"],
  "deviceFeatures": ["android.hardware.bluetooth","android.hardware.camera",    "android.hardware.microphone","android.hardware.nfc"...],
  "glExtensions": ["GL_OES_EGL_image","GL_OES_EGL_image_external","GL_OES_EGL_sync"...],
  "screenDensity": 440,
  "sdkVersion": 30
}                                                                      pixel4a.json
bundletool build-apks 
--bundle=/ExampleApp/example_app.aab 
--output=/ExampleApp/example_app.apks
--device-spec=pixel4a.json

When passing the flag connected-device, bundletool will create APKs just for the device currently connected to, or serial ids can be specified with the command device-id when multiple devices are connected.

bundletool build-apks 
--bundle=/ExampleApp/example_app.aab 
--output=/ExampleApp/example_app.apks
--connected-device

If device flag attributes are omitted when building the APKs, the bundletool will generate an APK set that will contain APKs for all possible devices.

Universal APK

The bundletool can also create a universal APK by passing the universal flag. This APK will contain all the files for all the device configurations. Because of that, it can be installed on any device. This will not by any means represent what the user will get when the app is installed from Play Store, however, this is a convenient way to pass an APK to users when you don’t know what device they are using.

bundletool build-apks 
--bundle=/ExampleApp/example_app.aab 
--output=/ExampleApp/example_app.apks
--ks=/ExampleApp/keystore.jks
--ks-pass=file:/ExampleApp/keystore.pwd
--ks-key-alias=ExampleKeyAlias
--key-pass=file:/ExampleApp/key.pwd
--universal

Testing Dynamic Feature Modules installation

When testing feature modules while building a universal APK, bundletool will include only the modules that specify <dist:fusing dist:include="true"/> in their manifest. If an attribute is set to false the definition of the activities will still be merged in the AndroidManifest.xml of the base module, however, the DEX files, Resources, Assets and Native libraries will not be.

A more convenient way of trying out the dynamic feature modules is by adding a local-testing argument to the build-apks command, which adds special metadata that will let us test feature module installation locally.

bundletool build-apks
--local-testing
--bundle=/ExampleApp/example_app.aab 
--output=/ExampleApp/example_app.apks

Deploying APKs to a connected device or an emulator

After a set of APKs are created, bundletool has the ability to extract the right combination of APKs from that set to a connected device or an emulator, by using the command install-apks.

Note, when using the local testing flag, bundletool will read the metadata from the previous step and push all optional modules into the device’s local storage.

bundletool install-apks 
--apks example_app.apks

Get APK size from an APK set

By providing the path of the APKs and adding the command get-size total, bundletool can measure the estimated download sizes as they would be server compressed over-the-wire. Adding the modules flag would provide the exact size of the base module plus the specified module or modules.

bundletool get-size total 
--apks=/ExampleApp/example_app.apks
--modules=module1

Support for Code Transparency for App Bundles

As of version 1.7.0 bundletool has added support for adding and checking transparency, which ensures the app’s integrity. To be precise SHA256 hashes are created for each DEX file and each .so file that is part of the App Bundle. Along with a singed code transparency file, the developer can verify the matching hashes using a singing key that is private to the developer. About how code transparency works and in-depth analysis on how to use bundletool while adding, verifying an App Bundle or APK set, you can read more here.

Android App Bundle is Open Sourced through bundletool

With APK sizes going as light as possible, and functionalities like on-demand feature installations, the future of the bundle format is looking bright in the Android Ecosystem.

With open-sourcing bundletool Google has indirectly open-sourced the App Bundle, meaning if any other distribution channels want to get in the action and implement support for bundles, they could with the help of bundletool.


This tool has given app developers the means to manipulate the App Bundle. If you have not tried it yet, download this command-line tool from the Github repository and give it a go. Cheers.