What is Android Dynamic Delivery Module?

Android Dynamic Delivery Feature Modules is the Future now

In Google I/O 2018, a new publishing format was introduced by Google is known as Android App Bundle(.aab). A few out of many benefits of using app bundle are dynamic delivery, automatic multi-APK distribution, smaller APK size, and dynamic feature modules.

What is Dynamic Delivery?

Google Play uses your app bundle to generate and serve optimized APKs for each user’s device configuration, so they download only the code and resources they need to run your app. For example, a user should not get x86libs if the device architecture is armeabi. Also, users should not get other resources like strings and drawables they are not using.

See More:
Text Path Animation for Android
Text Path Animation is to enter text, then set some animation...

You can also convert your independent modules/features (without these modules your app is functional) into dynamic feature modules which can be downloaded later. Through Dynamic Delivery, users can then download and install app’s dynamic features on demand after they’ve already installed the base APK of your app. As a result, the initial download size of your app is less and users don’t need to have unused code/feature in their devices.

Dependency tree for an app server using Dynamic Delivery (Split APKs).
Dependency tree for an app server using Dynamic Delivery (Split APKs).

Dynamic Delivery with split APKs

Split APKs are very similar to regular APKs — they include compiled DEX bytecode, resources, and an Android manifest. However, the Android platform is able to treat multiple installed split APKs as a single app. The benefit of split APKs is the ability to break up a monolithic APK into smaller, discrete packages that are installed on a user’s device as required.

  • Base APK: This APK contains code and resources that all other split APKs can access and provides the basic functionality for your app. When a user requests to download your app, this APK is downloaded and installed first. That’s because only the base APK’s manifest contains a full declaration of your app’s services, content-providers, permissions, platform version requirements, and dependencies on system features.
  • Configuration APKs: Each of these APKs includes native libraries and resources for a specific screen density, CPU architecture, or language. When a user downloads your app, their device downloads and installs only the configuration APKs that target their device. Each configuration APK is a dependency of either a base APK or dynamic feature APK. That is, they are downloaded and installed along with the APK they provide code and resources for.
  • Dynamic Feature APKs: Each of these APKs contains code and resources for a feature of your app that is not required when your app is first installed. That is, using the Play Core Library, dynamic APKs may be installed on demand after the base APK is installed on the device to provide additional functionality to the user.
See More:
Comparison of All Android Dependency Injection
There are a number of choices out there when it...

Note: Because devices running Android 4.4 (API level 19) and lower don’t support downloading and installing split APKs, Google Play instead serves those devices a single APK, called a multi-APK, that’s optimized for the device’s configuration.

What are Dynamic Feature Modules?

Dynamic feature modules allow you to separate certain features and resources from the base module of your app and include them in your app bundle. Users can download and install these modules later on demand after they’ve already installed the base APK of the app using Dynamic Delivery. For example, if your app has a custom camera feature you can make it a dynamic module and users can download and install the custom camera on demand.

Creating a dynamic feature module

Dynamic feature modules are organized just like regular app modules. They provide their own code, resources, and assets in the directories you would expect. To add a dynamic feature module to your app project using Android Studio(3.2 Canary 14+), proceed as follows:

Note: Before creating a dynamic module, you have to create your app bundle.

See More:
Direct Select Dropdown Android Library
Direct Select Dropdown is a selection widget with an ethereal,...
  1. Select File > New > New Module from the menu bar. In the Create New Module dialog, select Dynamic Feature Module and click Next.

2. On the Configure your new module screen, give your module a name.

3. On the Configure your new module screen, specify the module title.

  • Check the Enable on-demand box if you want the module to be available for on-demand downloads.
  • Check the Fusing box if you want this module to be available to devices running Android 4.4 (API level 20) and lower and include it in multi-APKs.

4. Hit Finish and wait for the project to sync.

Dynamic feature module: build.gradle

  • IDE applies the following Gradle plugin to the module’s build.gradle file: apply plugin: 'com.android.dynamic-feature'
  • What not to include: 
    Signing configurations: App bundles are signed using signing configurations of the base module.
    The minifyEnabled property: You can enable code shrinking for your entire app project from only the base module’s build configuration.
    versionCode and versionName: Gradle uses app version information that the base module provides.
  • When your dynamic module is created, it is added to the android.dynamicFeatures property of the base module’s build.gradle file android { android.dynamicFeatures = [":dynamic-feature-test"] }
  • Additionally, the base module’s dependency is added to the dynamic module. implementation project(':app')

Dynamic feature module: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:dist="http://schemas.android.com/apk/distribution"
    package="com.test.dynamic"
    split="dynamic-feature-test">

    <dist:module
        dist:onDemand="true"
        dist:title="@string/title_test">
        <dist:fusing include="true" />
    </dist:module>

</manifest>
  • split="split_name" : Defines the name of the module, which your app specifies when requesting an on-demand module using the Play Core Library.
  • <dist:module : This new XML element defines attributes that determine how the module is packaged and distributed as APKs.
  • dist:onDemand="true|false" : Specifies whether the module should be available as an on-demand download.
  • dist:title="@string/feature_name" : Specifies a user-facing title for the module.
  • <dist:fusing include="true|false" /> : Specifies whether to include the module in multi-APKs that target devices running Android 4.4 (API level 20) and lower.

Note: If the dynamic feature module generates no DEX files — that is, it contains no code that is later compiled into the DEX file format — you must set this property to false. Otherwise, you may get runtime errors.

<application
  android:hasCode="true"
  tools:replace="android:hasCode">
  ...
</application>

Downloading dynamic feature modules

With Google Play Core Library, your app can download dynamic feature modules on demand to devices running Android 5.0 (API level 21) and higher. You can also use this API to download on demand modules for your Android Instant Apps.

Note: Downloading modules on demand is in beta. If you experience any issues, please report a bug here.

Include the Play Core Library in your app’s build.gradle

dependencies {
    implementation 'com.google.android.play:core:1.3.4'
}

Note: Do not forget to add Google’s Maven Repository in project’s build.gradle.

Request an on-demand dynamic feature module

There are two ways to request an on-demand module:

  • Using SplitInstallManager.startInstall(): Your app needs to be in the foreground to submit the request. When your app requests an on-demand module, the Play Core Library employs a “fire-and-forget” strategy in an async fashion. That is, it sends the request to download the module to the platform, but it does not monitor whether the installation succeeded. So you are responsible for monitoring the request state (explained later).
SplitInstallManager splitInstallManager =
    SplitInstallManagerFactory.create(context);

SplitInstallRequest request = SplitInstallRequest.newBuilder()
        .addModule("dynamic-module-1")
        .addModule("dynamic-module-2")
        .build();

splitInstallManager.startInstall(request)
    .addOnSuccessListener(sessionId -> { ... })
    .addOnFailureListener(exception -> { ... });

Note: To have immediate access to the module’s code and resources, your app needs to enable SplitCompat.

  • Using SplitInstallManager.deferredInstall(): If you want to defer installation for when the app is in the background. Request for deferred install is best-effort and you cannot track its progress. So, before trying to access a module you have specified for deferred installation, you should check whether the module has been installed or not (explained later).
splitInstallManager.deferredInstall(Arrays.asList("dynamicModule"));

Note: It’s okay to request a dynamic feature module that’s already installed on the device. The API instantly considers the request as completed if it detects the module is already installed.

Monitor the Request State of an on-demand module

int mySessionId = 0;
// Creates a listener for request status updates.
SplitInstallStateUpdatedListener listener = state -> {
    if (state.status() == SplitInstallSessionStatus.FAILED
       && state.errorCode() == SplitInstallErrorCode.SERVICE_DIES) {
       // Retry the request.
       return;
    }
    if (state.sessionId() == mySessionId) {
        switch (state.status()) {
            case SplitInstallSessionStatus.DOWNLOADING:
              int totalBytes = state.totalBytesToDownload();
              int progress = state.bytesDownloaded();
              // Update progress bar.
              break;

            case SplitInstallSessionStatus.INSTALLED:
              //Module is downloaded successfully
              break;
        }
    }
};
// Registers the listener.
splitInstallManager.registerListener(listener);

splitInstallManager.startInstall(request)
    .addOnSuccessListener(sessionId -> { mySessionId = sessionId; })
    .addOnFailureListener(exception -> {
        switch(((SplitInstallException) exception).getErrorCode()) {
            case SplitInstallErrorCode.NETWORK_ERROR:
                //Network Error
                break;
            case SplitInstallErrorCode.MODULE_UNAVAILABLE:
                //Module Not Available
                break;
            ...
     });

// When your app no longer requires further updates, unregister the listener.
splitInstallManager.unregisterListener(listener);
Possible states for the install request
Possible states for the install request
The possible Error States for the install request
The possible Error States for the install request

See More:
Install Google’s New Fuchsia OS on Your Android
Google’s engaged on a replacement mobile operating system called Fuchsia,...

Managing dynamic feature modules

  • To cancel a request before it is installed, you can do so by invoking the cancelInstall() method using the request’s session ID.
splitInstallManager.cancelInstall(mySessionId);
Set<String> installedModules = splitInstallManager.getInstalledModules();
splitInstallManager.deferredUninstall(Arrays.asList("moduleName"));

Here is the Sample Project for Dynamic Delivery Feature Module:

Deploy your app

  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 drop-down menu next to Deploy, select APK from app bundle.
  4. Under Dynamic features to deploy, check the box next to each dynamic feature module, if any, you want to include when deploying your app.
  5. Click OK.

By Tell Me How

It is a technology blog and admin has excellent experience in programming from 5+ year. You can contact us at ceo.tellmehow@gmail.com

Share your thoughts

Leave a Reply

Loading Facebook Comments ...
Loading Disqus Comments ...