DEV Community

Attilio Carotenuto
Attilio Carotenuto

Posted on

Local Testing with Android App Bundles

App Bundle is an intermediate publishing format for Android, that includes all compiled code and resources, while deferring APK generation and signing to Google Play (commonly referred to as app thinning or slicing).

Google Play then generates optimized APKs based on the requesting user device, so only the code and resources that are needed for that device are downloaded and installed. This reduces download and install size for the user, and avoids having to manually manage multiple APKs for different device configurations.

During development, it’s convenient to be able to test your builds locally without having to upload to Google Play and creating a new release every time. To do so, we can use bundletool.

If you’re on Mac, you can install it through brew:

brew install bundletool

You can also find it on GitHub.

While bundletool also allows you to create App Bundles, in this guide I’ll assume you already created your AAB from Unity, Android Studio, or another authoring tool.

Generating APK set archives and installing on device

In order to install the App bundle on device, you first need to generate a related APKs file, which stands for APK set archive. To do so, you can use the build-apks command.

When running the command, you need to sign the APKs with the right key, otherwise it will use a default debug key, as shown below:

bundletool build-apks --bundle=/build/game.aab --output=/output/game.apks
--ks=/secrets/gamekey.keystore
--ks-pass=file:/secrets/keystore.pwd
--ks-key-alias=game_key_alias
--key-pass=file:/secrets/key.pwd

In this example I’m passing the ks-pass and the key-pass using a file. If you’d rather pass the actual password in clear text, replace file: with pass:

bundletool build-apks --bundle=/build/game.aab --output=/output/game.apks
--ks=/secrets/gamekey.keystore
--ks-pass=pass:mysecretpassword
--ks-key-alias=game_key_alias
--key-pass=pass:mysecretpassword

If you are using Play Asset Delivery, make sure to include the --local-testing flag. This will include metadata in your APKs manifest that allows the Play Feature Delivery Library to install modules and packs without connecting to Google Play.

If you expand the APKs file, or load it through Android Studio, you’ll be able to inspect the individual files contained, including PAD modules and base modules:

Image description

You can then install the game on a connected device by using:

bundletool install-apks --apks=/output/game.apks

Managing Device Specifications

If you include --connected-device in your build-apks command, bundletool will generate an APKs that matches the specs of the connected device. Otherwise it will generate APKs for any device configurations supported by your game.

Alternatively, passing --mode=universal will build a single APKs that includes all code and resources, supporting all device configurations your app supports.

You can generate a spec file for your connected device by using:

bundletool get-device-spec --output=/output/device_spec.json

This will include a list of deviceFeatures, screen density, SDK version, device brand and model, locales, supported ABIs, glExtensions and so on.

You can use this file to generate APKs that target that specific device, by using this command:

bundletool build-apks --device-spec=/output/device_spec.json
--bundle=/build/game.aab --output=/output/game.apks

You can integrate this as part of your testing deployment process to generate APKs for a list of specific devices, by storing their related device specs without needing the actual device at hand. You can also edit that file or create your own, following the existing format, to test your game in specific conditions.

Given an existing APKs file, you can generate a new archive containing a subset of configurations by passing a device spec file, as shown here:

bundletool extract-apks --apks=/output/universal_game.apks
--output-dir=/output/targeted_.apks
--device-spec=/output/device_spec.json

Determining Install size

As App bundles, and APK set archives, contain a variety of specifications for multiple devices, their install size will vary depending on the actual device it’s being installed on.

You can determine the range of install sizes by using the get-size command:

bundletool get-size total --apks=/output/game.apks

The output looks like this:

MIN,MAX
2264966236,2265953472

By default this indicates the download size of the base and Install time modules.

If you want to take into account specific modules, and their dependencies, you can pass those as a comma-separated list using the -- modules flag.

Checking App Bundle signature

Given a built App Bundle, you can check its signature using keytool:

keytool -printcert -jarfile /build/game.aab

This will print the certificate info, including Issuer, fingerprints, validity, algorithm used, and version.

If the build is unsigned, you’ll get this message:
Not a signed jar file

If you’re using Unity and you already supplied your keystore in the Publishing Settings, make sure you’re not making a Development Build, as they will be unsigned by default.

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs