পোস্টটি পড়া হয়েছে 98 বার
android dynamic feature delivery

Mastering Android Dynamic Feature Delivery (1/3)

Introduction

Dynamic Feature Modules (DFMs) in Android development are a powerful tool for modularising your app, reducing size, and enabling on-demand delivery. In this comprehensive guide, we’ll walk through everything from setting up your first DFM to solving common issues that developers often face.

3 parts of this blog series

Full Source Code — GitHub.Com

Problem Statement

We know that, on average, 80% of users use only 20% of the features in an application. Suppose you have an application with 30 features (20 MB), and all of your features are in the app module. So, every user will download a 20 MB app, and it will occupy the required storage after installation. However, most of the features are not used by a user. For a specific user, it’s a waste of memory because they may only need 20–30% of the features.

Here we have only one module. Name: app

What would it be like if we could download only the parts of our app that we needed? Consider an eCommerce application with a customer support feature that includes chat and audio call capabilities. To implement this feature, you have used a third-party SDK (e.g., 5 MB).

You know that this feature is not necessary for every user. So, the idea is to exclude the customer support feature from your main app module. When a user taps on the customer support button, they will be able to download this feature from the Play Store. After downloading, the user can use the feature.

Understanding Dynamic Feature Module

Generally, when we start Android development, we work in a monolithic app module. There is only one module in our application, and all features remain in this app module. We upload the .apk or .aab file to the Play Store, and users download our entire application at once.

On the other hand, in a dynamic feature module, we can split our application into a few modules. The user will download the base module (app module) for the first time. After that, they will be able to download other feature modules at runtime.

Example

Suppose you have an eCommerce application. Another feature is customer support (chat & audio-video call). Your main feature is online shopping (app module, for example, its size is 10 MB). However, for some special cases, users need to chat or call customer support. So, you can develop your customer support feature as a dynamic feature module outside the app module (for example, the customer support feature size is 5 MB).

Android dynamic on demand feature module delivery tutorial
Wireframe of Android on Demand dynamic feature module

The first time a user downloads the app, they will get the app module without the customer support feature. So, they will download a 10 MB app. When someone needs to contact customer support, they will click on your specific button and download the customer support module (size 5 MB) from the Play Store on-demand basis. This way, lots of users save an additional 5 MB cost.

That’s the idea of On-Demand Dynamic Feature Delivery Module!

Setup Dynamic Feature Module

First of all, I have created a new project with the App ID com.hellohasan.hasanerrafkhata. This app is already on the Play Store, and I have developer access on the Google Play Console. The App ID is important here for testing the dynamic feature module. You need to upload the .aab file to the Google Play Store or use Google Play Internal App Sharing. So, make sure you have access to the Play Store for your mentioned Application ID.

After creating the project with my own app ID, I added dependencies in the build.gradle.kts. In some tutorials, I found instructions to add the Google Play Core library. However, I believe it’s enough to add the feature-delivery library for this case.

build.gradle.kts (app module)

dependencies {
    // other dependencies

    implementation("com.google.android.play:feature-delivery:2.0.0")
    implementation("com.google.android.play:feature-delivery-ktx:2.0.0")
}

After syncing the project, I encountered the first error!

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:checkDebugDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
   > Duplicate class android.support.v4.app.INotificationSideChannel found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.app.INotificationSideChannel$Stub found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.app.INotificationSideChannel$Stub$Proxy found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.os.IResultReceiver found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.os.IResultReceiver$Stub found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.os.IResultReceiver$Stub$Proxy found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.os.ResultReceiver found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.os.ResultReceiver$1 found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.os.ResultReceiver$MyResultReceiver found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     Duplicate class android.support.v4.os.ResultReceiver$MyRunnable found in modules core-1.9.0-runtime (androidx.core:core:1.9.0) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
     
     Go to the documentation to learn how to <a href="d.android.com/r/tools/classpath-sync-errors">Fix dependency resolution errors</a>.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 9s

To solve this error, I added these two lines in the gradle.properties file.

android.useAndroidX=true
android.enableJetifier=true

Create Dynamic Feature Module

Create a new module like below:

Creating Dynamic Feature module in Android
Confirmation of creating new dynamic feature module with required configuration

In the above configuration, I have set ‘Do not include module at Install-time (on-demand only)’ because I want to install the dynamic module on demand only. So, my dynamic module will not be included at install time. After creating the translation dynamic module, my project structure looks like the one below:

Now there are two modules in our project. app & translationdynamicmodule

Then, I created a new Activity, CustomerSupportActivity.kt, inside the customer_support module. Android Studio internally changed some configurations in a few different places. If you want to convert any existing feature module into an on-demand dynamic module, you have to configure these manually. Let’s check them!

Changes in build.gradle.kts (app level)

android {
    // other configurations

    // this line is automatically added by Android Studio
    // after creating a new dynamic module
    dynamicFeatures += setOf(":customer_support")
}

AndroidManifest.xml (dynamic module)

<dist:module
    dist:instant="false"
    dist:title="@string/title_customer_support">
    <dist:delivery>
       <dist:on-demand />
    </dist:delivery>

    <dist:fusing dist:include="false" />
</dist:module>

build.gradle.kts (dynamic module)

plugins {
    id("com.android.dynamic-feature")
    id("org.jetbrains.kotlin.android")
}

// others configurations

dependencies {
    implementation(project(":app"))

    // other dependencies
}

build.gradle.kts (Project level gradle)

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id("com.android.application") version "8.1.4" apply false
    id("org.jetbrains.kotlin.android") version "1.8.10" apply false
    id("com.android.dynamic-feature") version "8.1.4" apply false
}

settings.gradle.kts

include(":app")
include(":customer_support")

So, we are done with the basic setup part. In next blog we will implement the main functionalities of Dynamic Feature Module. Please check here.

Enjoy!

3 thoughts on “Mastering Android Dynamic Feature Delivery (1/3)

Leave a Reply

Your email address will not be published. Required fields are marked *