Save the date! Android Dev Summit is coming to Mountain View, CA on November 7-8, 2018.

Build, deploy, and upload Android App Bundles

The Android App Bundle is a new upload format that includes all your app’s compiled code and resources, but defers APK generation and signing to Google Play. And, after you upload your app bundle to Google Play, Dynamic Delivery uses the app bundle to generate and serve smaller, more optimized APKs for each device configuration your app supports. That way, users download only the code and resources they need to run your app.

This guide describes the Android App Bundle format, and shows you how to build an app bundle for upload or testing. If you haven’t already done so, make sure you configure your app project to support Dynamic Delivery.

The easiest way to build an app bundle to a connected device is using Android Studio. So, make sure to download the latest Canary version of Android Studio.

The Android App Bundle format

An Android App Bundle is a file (with the .aab file extension) that you upload to Google Play to support its new app serving model, called Dynamic Delivery. Each bundle includes the compiled code and resources for all of your app’s modules and supported device configurations.

To put it simply, app bundles are signed ZIP files that organize your app’s code and resources into modules, as illustrated in figure 1, from which Google Play generates the various APKs that are served to users: such as the base APK, dynamic feature APK(s), configuration APKs, and (for devices that do not support split APKs) multi-APKs. The directories that are colored in blue represent code and resources that Google Play uses to create configuration APKs for each module.

Figure 1. The contents of an Android App Bundle with one base module and two dynamic feature modules.

Code and resources for each module are organized similarly to what you would find in an APK—and that makes sense because each of these modules may be generated as separate APKs. The following list describes some of the app bundle’s files and directories in more detail:

  • base/, feature1/, and feature2/: Each of these directories at the root of the app bundle represent a different module of your app. The base module for your app is always contained in a base directory of the app bundle. However, the directory for each dynamic feature module is given the name specified by the split attribute in the module’s manifest. To learn more, read about the Dynamic feature module manifest.
  • BUNDLE-METADATA/: This directory includes metadata files that contain information useful for tools or app stores. Such metadata files may include ProGuard mappings, the complete list of your app's DEX files, and BundleConfig.pb—which provides information about the bundle itself (such as which version of the build tools were used to build the app bundle). Files in this directory are not packaged into your app's APKs.
  • Module Protocol Buffer (*.pb) files: These files provide metadata that helps describe the contents of each app module to app stores, such as Google Play. For example, Google Play uses native.pb and resources.pb to determine what code and resources in each module to use when optimizing APKs for different device configurations.
  • manifest/: Unlike APKs, app bundles store the AndroidManifest.xml file of each module in this separate directory.
  • dex/: Unlike APKs, app bundles store the DEX files for each module in this separate directory.
  • root/: This directory stores files that are later relocated to the root of any APK that includes the module that this directory is located in. For example, the base/root/ directory of an app bundle may include Java resources that your app loads using Class.getResource(). Those files are later relocated to the root directory of your app’s base APK and every multi-APK that Google Play generates. Paths within this directory are also preserved. That is, directories (and their subdirectories) are also relocated to the root of the APK.

  • res/, lib/, and assets/: These directories are identical to those in a typical APK. When you upload your app bundle, Google Play inspects these directories and packages only the files that satisfy the target device configuration, while preserving file paths.

Now that you understand the format of a simple app bundle, and how it represents an Android app project, you should build one from your app project. The easiest way to do so is by using Android Studio.

Deploy your app from an app bundle

When using an existing or default run/debug configuration, Android Studio doesn’t use bundles to deploy your app—it builds and deploys APKs that are targeted to your connected device. That’s because deploying from an app bundle has the following limitations you should consider:

  • Instant Run does not work when deploying from an app bundle.
  • The Android Studio build system must build an app bundle before using it to build APKs that it deploys to your app—this extends the total build time when deploying your app.

If you still want Android Studio to build and deploy your app from an app bundle, you can modify an existing run/debug configuration to do so as follows:

  1. Select Run > Edit Configurations from the menu bar.
  2. In the left pane of the Run/Debug Configurations dialog, select your desired configuration under the Android App node.
  3. In the dropdown menu next to Deploy, select APK from app bundle.
  4. Under Dynamic features to deploy, check the box next to each dynamic feature module you want to include when deploying your app.
  5. Click OK.

Using the run/debug configuration you just modified, deploy your app by selecting Run > Run from the menu bar (or by clicking Run in the toolbar). As an intermediate build step, Android Studio first converts your app project into an app bundle that includes all your app’s compiled code and resources. From that app bundle, the IDE then generates only the APKs that are required to deploy your app to the connected device.

Build an app bundle using Android Studio

Generating an Android App Bundle using Android Studio is very similar to generating an APK. If you already have your app project open in the IDE and you want to simply test building an app bundle, select Build > Build Bundle(s)/APK(s) > Build Bundle(s) from the menu bar. The IDE generates an app bundle for your selected build variant and places it in the project-name/module-name/build/outputs/bundle/ directory.

If you build an app bundle for a debug version of your app, Android Studio automatically signs your app bundle with a debug signing key, and you can use bundletool to deploy your app from the app bundle to a connected device. If you don’t select a version of your app that’s signed with a debug signing key, Android Studio builds an unsigned app bundle. To upload your app to the Play Console, you need to first generate a signed app bundle.

After Android Studio finishes building your signed app bundle, you can either locate or analyze it by clicking on the appropriate option in the pop-up notification. Analyzing your bundle allows you to inspect the contents of the app bundle and works similarly to the APK Analyzer.

To generate an app bundle from your app project, the IDE’s build system uses the same open-source tool, called bundletool, that Google Play uses to later convert your app bundle into signed APKs. To learn more about bundletool, read about how to Test Android App Bundles with bundletool.

Build a signed app bundle for upload

Before you can upload your app bundle to the Play console you need to generate a signed app bundle. To generate a signed app bundle, proceed as follows:

  1. Select Build > Generate Signed Bundle/APK from the menu bar.
  2. In the Generate Signed Bundle or APK dialog, select Android App Bundle and click Next.
  3. In the Module dropdown menu, select the base module of the app you want to generate an app bundle for.
  4. Provide information for an existing key and keystore, or create a new one. This is the same type of key and keystore information you provide when building a signed APK.
  5. If you want Android Studio to also save your signing key as an encrypted file, check the box next to Export encrypted key. To be able to upload your app bundle and take advantage of Dynamic Delivery, you need to upload this encrypted file to the Play Console and enroll in app signing by Google Play.
  6. Click Next.
  7. Provide a Destination Folder for your app bundle, and select the Build Type and Flavors that you want to generate app bundles for.
  8. Click Finish.

After Android Studio finishes building your signed app bundle, you can either locate or analyze the app bundle by clicking on the appropriate option in the pop-up notification. If you selected the option to export your signing key, you can quickly navigate to it by clicking the dropdown arrow in the bottom right corner of the popup to expand it and clicking Show Exported Key File, as shown in figure 2.

Figure 2. After the IDE finishes generating your signed app bundle, click the links in the popup to analyze or locate your app bundle, or locate your exported signing key.

Now that you’ve generated a signed APK, you can either use bundletool to locally test how Google Play will generate APKs from your app bundle, or upload your app bundle to the Play Console.

Build an app bundle from the command line

If you’d rather generate an app bundle from the command line, run the bundleVariant Gradle task on your app’s base module. For example, the following command builds an app bundle for the debug version of the base module:

./gradlew :base:bundleDebug

If you want to build a signed bundle for upload to the Play Console, you need to first configure the base module’s build.gradle file with your app’s signing information, similar to how you would when building a signed APK from the command line. To learn more, read Configure Gradle to sign your APK. You can then, for example, build the release version of your app, and Gradle automatically generates an app bundle and signs it with the signing information you provide in the build.gradle file.

If you instead want to sign an app bundle as a separate step, you can use jarsigner to sign your app bundle from the command line.

Build an app bundle using bundletool

bundletool is a command line tool that Android Studio, the Android Gradle plugin, and Google Play use to convert your app's compiled code and resources into app bundles, and generate deployable APKs from those bundles.

So, while it's useful to test app bundles with bundletool and locally recreate how Google Play generates APKs, you typically won't need to invoke bundletool to build the app bundle itself—you should instead use Android Studio or Gradle tasks, as described in previous sections.

However, if you don't want to use Android Studio or Gradle tasks to build bundles—for example, if you use a custom build toolchain—you can use bundletool from the command line to build an app bundle from pre-compiled code and resources. If you haven't already done so, download bundletool from the GitHub repository.

This section describes how to package your app's compiled code and resources, and how to use bundletool from the command line to convert them into an Android app bundle.

Generate the manifest and resources in proto format

bundletool requires certain information about your app project, such as the app's manifest and resources, to be in Google's Protocol Buffer format—which is also known as "protobuf" and uses the *.pb file extension. Protobufs provide a language-neutral, platform-neutral, and extensible mechanism for serializing structured data—it's similar to XML, but smaller, faster, and simpler.

You can generate your app's manifest file and resource table in protobuf format using the latest version of AAPT2 from the Google Maven repository.

To download AAPT2 from Google's Maven repository, proceed as follows:

  1. Navigate to com.android.tools.build > aapt2 in the repository index.
  2. Copy the name of the latest version of AAPT2.
  3. Insert the version name you copied into the following URL and specify your target operating system: https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/aapt2-version/aapt2-aapt2-version-[windows | linux | osx].jar

    For example, to download version 3.2.0-alpha18-4804415 for Windows, you would use: https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/3.2.0-alpha18-4804415/aapt2-3.2.0-alpha18-4804415-windows.jar

  4. Navigate to the URL in a browser—AAPT2 should begin downloading shortly.

  5. Unpackage the JAR file you just downloaded.

Use AAPT2 to compile your app's resources with the following command:

aapt2 compile
project_root/module_root/src/main/res/drawable/Image1.png
project_root/module_root/src/main/res/drawable/Image2.png
-o compiled_resources/

During the link phase, where AAPT2 links your various compiled resources into a single APK, instruct AAPT2 to convert your app's manifest and compiled resources into the protobuf format by including the --proto-format flag, as shown below:

aapt2 link --proto-format -o output.apk
-I android_sdk/platforms/android_version/android.jar
--manifest project_root/module_root/src/main/AndroidManifest.xml
-R compiled_resources/*.flat
--auto-add-overlay

You can then extract content from the output APK, such as your app's AndroidManifest.xml, resources.pb, and other resource files—now in the protobuf format. You need these files when preparing the input bundletool requires to build your app bundle, as described in the following section.

Package pre-compiled code and resources

Before you use bundletool to generate an app bundle for your app, you must first provide ZIP files that each contain the compiled code and resources for a given app module. The content and organization of each module's ZIP file is very similar to what's described in the section about the Android App Bundle format. For example, you should create a base.zip file for your app's base module and organize its contents as follows:

File or directory Description
manifest/AndroidManifest.xml The module's manifest in protobuf format.
dex/... A directory with one or more of your app's compiled DEX files. These files should be named as follows: classes.dex, classes2.dex, classes3.dex, etc.
res/... Contains the module's resources in protobuf format for all device configurations. Subdirectories and files should be organized similar to that of a typical APK.
root/..., assets/..., and lib/... These directories are identical to those described in the section about the Android app bundle format.
resources.pb Your app's resource table in protobuf format.

After you prepare the ZIP file for each module of your app, you can pass them to bundletool to build your app bundle, as described in the following section.

Build your app bundle using bundletool

To build your app bundle, you use the bundletool build-bundle command, as shown below:

bundletool build-bundle --modules=base.zip --output=mybundle.aab

The following table describes flags for the build-bundle command in more detail.

Flag Description
--modules=path-to-base.zip, path-to-module2.zip,path-to-module3.zip Specifies the list of module ZIP files bundletool should use to build your app bundle.
--output=path-to-output.aab Specifies the path and filename for the output *.aab file.
--config=path-to-BundleConfig.json Specifies the path to an optional configuration file you can use to customize the build process. To learn more, see the section about customizing downstream APK generation.
--metadata-file=target-bundle-path:local-file-path Instructs bundletool to package an optional metadata file inside your app bundle. You can use this file to include data useful to other steps in your toolchain or an app store.

target-bundle-path specifies a path relative to the root of the app bundle where you would like the metadata file to be packaged, and local-file-path specifies the path to the local metadata file itself.

Customize downstream APK generation

App bundles include a BundleConfig.pb file that provides metadata that app stores, such as Google Play, require when generating APKs from the bundle. Although bundletool creates this file for you, you can configure some aspects of the metadata in a BundleConfig.json file and pass it to the bundletool build-bundle command—bundletool later converts and merges this file with the protobuf version included in each app bundle.

For example, you can control which categories of configuration APKs to enable or disable. The following example of an BundleConfig.json file disables configuration APKs that each target a different screen density (that is, resources for all screen densities will be included in their respective base or dynamic feature APKs):

{
  "optimizations": {
    "splitsConfig": {
      "splitDimension": [{
        "value": "SCREEN_DENSITY",
        "negate": true
      }]
    }
  }
}

You can also use BundleConfig.json to control which file types to leave uncompressed when packaging APKs. By default, all files except the following are compressed:

  • Your app's resource table (resources.arsc).
  • Files with the following extensions: 3g2, 3gp, 3gpp, 3gpp2, aac, amr, awb, gif, imy, jet, jpeg, jpg, m4a, m4v, mid, midi, mkv, mp2, mp3, mp4, mpeg, mpg, ogg, png, rtttl, smf, wav, webm, wma, wmv, and xmf.
  • On Android 6.0 (API level 23) and higher: native libraries for apps that specify extractNativeLibraries=false in their manifest.

If you want any other files to remain uncompressed, specify them in your custom BundleConfig.json using glob patterns, as follows:

{
  "compression": {
    "uncompressedGlob": ["res/raw/**", "assets/**.uncompressed"]
  }
}

For a full description of what you can configure in your BundleConfig.json, inspect the bundletool config.proto file, which is written using Proto3 syntax.

Upload your app bundle to the Play Console

After you build your Android App Bundle, you can upload your app bundle to the Play Console to inspect, test, and publish your app. Before you get started, be aware of the following prerequisites:

  1. Before you upload your app bundle, you must enroll into app signing by Google Play.
  2. If your app includes dynamic feature modules, you can upload and test your app through the Play Console's internal test track. However, to publish your app to production, you must apply for the Dynamic Features Beta Program. To learn more, go to the Play Console help topic about the Beta program for publishing apps with dynamic feature modules.
  3. Note that Google Play supports only app downloads of 100MB or less. So, for example, when first installing your app, the total size of your base APK and its configuration APKs must equal 100 MB or less. The same applies to downloading dynamic features, where the total size of any dynamic feature APK and its configuration APKs must be 100 MB or less. After uploading your app bundle, the Play Console warns you if your app bundle results in APKs that violate this restriction.

Inspect APKs using bundle explorer

When you upload your app bundle, the Play Console automatically generates split APKs and multi-APKs for all device configurations your app supports. In the Play Console, you can use the App Bundle Explorer to see all APK artifacts that Google Play generates; inspect data such as supported devices and APK size savings; and download generated APKs to deploy and test locally.

To learn more, read the Play Console help topic about Reviewing your app bundle details.

Test Dynamic Delivery using the internal test track

The easiest and fastest way to test your app after you upload your app bundle is by using Play Console’s new internal test track. This new test track is aimed towards quickly sharing your app via Dynamic Delivery to a limited amount of internal testers. And, because the only way to test downloading installing dynamic feature modules on demand is through Google Play, the internal test track is where you’ll want to upload your app bundle to fine-tune this type of user experience.

To learn more, read Set up an open, closed, or internal test.

Update your app

After you upload your app to the Play Console, updating your app requires you to increase the version code you include in the base module, and build and upload a new app bundle. Google Play then generates updated APKs with new version codes and serves them to users as needed. For more information, read Manage app updates.