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:
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.
Top comments (0)