Understanding and exploring App Bundles — Part2

Aishwarya Iyer
5 min readFeb 24, 2021

In this part, we ‘ll go deep to implement an awesome feature of app bundle i.e. Dynamic Feature Module

Let’s take some steps to complete our part 2 series

Step 1: Create a dynamic feature module

Step 2: Configure a dynamic module

Step 3: Add the library and code for downloading features on demand

Step 4: Deploy the app

So let’s go step by step to build our app by adding dynamic feature modules, just before we dive into this series, let’s just remind ourselves what is dynamic features

Dynamic features modules allow the app to download the code on demand for devices running Android 5.0 (API level 21) and higher. This means there can be features in your app that can be downloaded at a later time when it is required so this helps to reduce the initial download size of the app

Step 1: Create a dynamic feature module

Select File > New > New Module from the menu bar. In the Create New Module dialog, select Dynamic Feature Module, and click Next.

Step 2: Configure a dynamic module

Click next Configure your module screen will appear

On the Configure your module screen, give your module a name. Here, I have given name as customer_support

Click next, you can see the Module download options screen

On the Module download options give your module a title

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.

Click Finish and allow the project to sync

At this point, once the sync is completed you can see the following things that are added to your build.gradle by Android studio IDE

  • The following Gradle plugin is added to the module’s build.gradle of dynamic feature module : apply plugin: 'com.android.dynamic-feature'
  • The app module’s dependency is added to the dynamic module. implementation project(':app')
  • When your dynamic module is created, it is added to the app module’s build.gradle file android { android.dynamicFeatures = [":customer_support"] }
  • Now let’s take a look at the Android Manifest for the dynamic feature module
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
package="com.aish.customer_support">
<dist:module
dist:instant="false"
dist:title="@string/title_customer_support">
<dist:delivery>
<dist:on-demand />
</dist:delivery>
<dist:fusing dist:include="true" />
</dist:module>
</manifest>
  • <dist:module : This XML element defines attributes that determine how the module is packaged and distributed as APKs.
  • dist:onDemand="true|false" | <dist:on-demand/>: Specifies whether the module should be available as an on-demand download.
  • <dist:install-time/>: Specifies whether the module should be available at the install time itself
  • dist:instant="true|false" : Specifies whether the module should be available as an instant experience. We will come to this again in part3 ;)
  • 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.

Step 3: Add the library and code for downloading features on demand

Let’s take a peek into our step 3

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

dependencies {
//Add the Play Core Library to connect to Google Play.
implementation 'com.google.android.play:core:1.7.3'
}

Next is to write the code for connecting to google play and downloading the dynamic feature module bundles from the play store. For this purpose, we ll use SplitInstall API

SplitInstallManager.startInstall(): For this to work, the app needs to be in the foreground to submit the request. When your app requests an on-demand module, the Play Core Library applies 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.

The SplitInstallStateUpdatedListener allows us to monitor the Request State of our on-demand module

Register this listener in onResume and unregister it in onPause to make sure disposing of the listener once it’s no longer needed. SplitInstallManager helps install/uninstall, deferred install/uninstall, registering and unregistering of the listener

override fun onResume() {
// Listener can be registered even without directly triggering a download.
manager.registerListener(listener)
super.onResume()
}
override fun onPause() {
manager.unregisterListener(listener)
super.onPause()
}

Let’s create a button click for launching the customer_support

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainLayoutParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_gravity="center"
android:background="@color/colorPrimary"
android:gravity="center">
<Button
android:id="@+id/load_customer_support"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="8dp"
android:background="@color/textColorPrimary"
android:textColor="@color/white"
android:text="@string/load_feature_aboutus"
/>

<ProgressBar
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:visibility="gone"
android:layout_marginEnd="8dp" />
<TextView
android:id="@+id/progress_text"
style="@android:style/TextAppearance.DeviceDefault.Medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:textColor="@color/textColorPrimary"
android:text="@string/loading" />
</LinearLayout>

Write a click listener for it and launch the module once it has been successfully loaded

The loadAndLaunchModule() creates a request and start installing the module. You can skip downloading the module if t’s already installed.

  • The API also allows you to listen for updates throughout the download/install process. You can utilize this progress data to display the progress of download/install to your users while they’re waiting for on-demand (dynamic feature module) to download, similar to showing progress while doing a network call.
  • For the large modules, you need to obtain the user confirmation before start download/install the dynamic feature module. You need to write the code for it.
  • Note: To see downloading of the dynamic module, the application has to be uploaded to the Play Store, you can upload it to Google Play Console internal test track

Step 4: Deploy the app

Select Run -> Edit Configurations from the menu bar.

In the dropdown menu next to Deploy, select APK from the app bundle

Under Dynamic features to deploy, check the box next to each dynamic feature module, if any, you want to include when deploying your app.

Click OK

This will deploy your app and you will be able to test your dynamic feature however as I previously said you won’t be able to see the downloading/installing process of dynamic feature modules, for that purpose you will require to upload your app to google play internal test

Soooo finally we have completed an end to end dynamic feature module integration yay!!

Here is the repository if you want to refer

Thank you so much for your valuable time, hope this was useful

Also, do claps if you liked it ;)

--

--