Header graphic by Virginia Poltrack

Local development and testing with on-demand modules

Wojtek Kaliciński
Android Developers


Over the past few months I’ve been working on addressing some of the feedback I got from developers who were using dynamic feature modules in their apps. A common theme was the lack of good testing support and their speed of development being affected by having to upload an artifact to the Play Store to be able to try the module download and installation flows.

Last year, at Android Dev Summit, I gave a talk with some colleagues working on Play’s Dynamic Delivery, in which we teased a new feature in the Play Core library called the FakeSplitInstallManager that makes it possible to perform some of the operations, such as installing on-demand modules, locally.

While the FakeSplitInstallManager class has been available for a while now (since Play Core 1.6.4), it took a bit of time to get the developer experience right and land the final changes to bundletool that were required to automate the process.

Today you can check out how it works in one of our new samples:

Previously, whenever we released samples that showcased the use of downloadable dynamic feature modules, we had to include instructions for developers to
1) change the package name of the sample app,
2) create an app entry on your Play Console account,
3) upload the bundle to internal app sharing or the internal testing track… Very cumbersome if you just want to experience using the API!

All of the above is not needed anymore if you just want to quickly play with the sample and see how it works locally.

This is thanks to a new --local-testing flag added in bundletool version 0.13.0.

When applied to the bundletool build-apks command, the flag instructs bundletool to add a small piece of meta-data to the generated APK’s manifest. You can then use this in two simple steps:

The returned instance now automatically detects the presence of the local testing meta-data and uses FakeSplitInstallManager under the hood, installing requested modules from local files rather than by downloading from Play. You must use Play Core 1.6.5 or newer for this to happen automatically.

To make it even simpler, I’ve added a new Gradle task in the sample to streamline running the bundletool commands that I mentioned:

./gradlew installApkSplitsForTestDebug

Unfortunately this functionality is still not available from Android Studio GUI or from the Android plugin for Gradle directly. The task you see here is just a quick hack, equivalent to running the following commands on your project:

./gradlew bundleDebugbundletool build-apks --overwrite --local-testing --bundle path/to/bundle.aab --output path/to/apkset.apksbundletool install-apks --apks path/to/apkset.apks

If you want to know how I added these tasks, take a look at the build script source. UPDATE: Take a look at our newer PlayCoreKTX sample to see how it’s done using the new Android Gradle plugin APIs.

Please note: not all SplitInstallManager functions are implemented in local testing mode or when calling FakeSplitInstallManager directly (e.g. when writing tests).

You can:

What’s not supported due to technical limitations (i.e. we have no current plans to add this):

  • Uninstalling modules.
  • Requesting deferred installs/uninstalls.
  • Starting a confirmation dialog for large modules.
  • More than one installation session running.

For further reading, please refer to the updated documentation.

By the way, the sample that I linked in this article showcases another library that I’ve worked on together with Ben Weiss, which makes it easier to integrate on-demand modules in your app when using the Navigation architecture component.

The dynamic feature navigator is an extension on top of the base navigation library that lets you define navigation destinations (such as Fragments, Activities) that come from dynamic feature modules.

If the module is installable on-demand the library takes care of downloading and installing it using the Play Core API, and even provides a default progress UI. At the same time, it is as customizable as you need it to be. You can read more in the new documentation page.

The library is currently in alpha and we welcome your feedback.