Dynamic Feature Module
For A/B Testing a New Product
Deni Rohimat
ADB Ngabuburit - 16 May 2020
Overview
A/B Testing
What is A/B Testing ?
A method for comparing two versions of an application page to see which one has a better impact (usually in the form of conversion rate)
How are the stages?
Dynamic Delivery
Intro
In 2018, Google Play introduced a new application serving model, the Dynamic Delivery, to help generating and serving optimized APKs based on the device configuration. It uses the Android App Bundle format to dynamically generate the APK for each device variant, which is much better than manually generating them.
Dynamic Delivery not only optimizes the APK, it also enables another feature in our apps: the Dynamic Feature Modules. These dynamic modules can be automatically installed based on device configuration or downloaded later, after the app is already installed and running.
Base Feature
Configurations APKs
Dynamic Feature APKs
Bundle Split Options
To configure your build for multiple APKs, add a splits block to your module-level build.gradle file.
Within the splits block, provide a density block that specifies how Gradle should generate per-density APKs, or an abi block that specifies how Gradle should generate per-ABI APKs.
You can provide both density and ABI blocks, and the build system creates an APK for each density and ABI combination.
bundle {
language {
enableSplit = false
}
density {
enable true
reset()
include "mdpi", "hdpi"
}
abi {
enable true
reset()
include "x86", "x86_64"
}
}
Main Objective
The main objective is creating a simple application with a Dynamic Feature Module which will be manually downloaded by the user.
This scenario represents a feature that may be used only a few times, or that might not be needed right away.
Modules such as paid functionalities, chat support and plugins are examples of possible On-demand Dynamic Features.
Requirements
Unfortunately, your application can only connect to Google Play and download the Dynamic Feature Module after being published.
To publish your Android App you will need to subscribe on Google Play. For more information about how to publish, please take a look at the official documentation.
Install Time Inclusion
Install-time inclusion defines how and when this Dynamic Feature will be available for the user.
In this example, we will use the default, Do not include module at install-time (on-demand only). For more information about other inclusion options, please refer to official docs.
Pre-Lollipop (API 21) does not support Dynamic Features, you need to specify if the feature should be available at install-time via Fusing preference. In this example, we will include these devices.
Some differences between a Dynamic Feature module and a regular Feature one:
:app
:ondemand
<dist:module
dist:instant="false"
dist:title="@string/title_ondemand">
<dist:delivery>
<dist:on-demand />
</dist:delivery>
<dist:fusing dist:include="true" />
</dist:module>
android {
...
dynamicFeatures = [":ondemand"]
}
Downloading the Dynamic Feature on application
Now we will add the Play Core Library to connect to Google Play. This dependency needs to be added in app/build.gradle to download and install the module and in ondemand/build.gradle to load the resources after the installation.
implementation 'com.google.android.play:core:1.7.2'
Add DynamicApp class in your :app module
class DynamicApp : Application() {
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
SplitCompat.install(this)
}
}
Add OnDemandActivity class in your :ondemand module
class OnDemandActivity : AppCompatActivity() {
// other lifecycle functions
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
SplitCompat.install(this)
}
}
Update MainActivity to be like this, have a two button.�One for downloading the Dynamic Feature and a disabled button that will be enabled as soon as the new dynamic feature is installed.
First of all, we will get an instance of SplitInstallManager to be able to install the new module. In our example we will do it lazily:
private val manager: SplitInstallManager by lazy {
SplitInstallManagerFactory.create(this)
}
MainActivity.kt
In the Download Button, we will implement the SplitInstallRequestto build a request to download our Dynamic Feature and start the installation:
val request = SplitInstallRequest.newBuilder()
.addModule("ondemand")
.build()
manager.startInstall(request)
MainActivity.kt
We will also add listeners to show visual information about the installation:
manager.registerListener {
when (it.status()) {
SplitInstallSessionStatus.DOWNLOADING -> showToast("Downloading feature")
SplitInstallSessionStatus.INSTALLED -> {
showToast("Feature ready to be used")
updateDynamicFeatureButtonState()
}
else -> { /* Do nothing in this example */ }
}
}
MainActivity.kt
In the second button, we will set its enabled state based on the Dynamic Feature installation status:
val isEnabled = manager.installedModules.contains("ondemand")
button_app_open.isEnabled = isEnabled
MainActivity.kt
This will enable the button when our Dynamic Feature has been installed and it is ready to launch. Since the Application module does not depend on the Dynamic module, it is not possible to access the Activity directly. There are several ways to access this module, but to keep it simple, we will use the good ol’ reflection:
val intent = Intent()
intent.setClassName(BuildConfig.APPLICATION_ID, "net.derohimat.adbondemand.OnDemandActivity")
startActivity(intent)
MainActivity.kt
Your App is ready to be published!
Unfortunately, if you simply run your app through Android Studio, it will not work because it needs a connection with Google Play.
This is a problem because you would need to upload your application to Google Play every time you do a single change. That’s why Google released Internal App Sharing.
Using Internal App Sharing
The internal app sharing allows developers to quickly share apps faster and without all the restrictions imposed by the Google Play Console.
For sharing, all you need to do is log in with your developer account on the Internal App Sharing page and upload the apps.
The only restriction here is that you can only upload apps that you own, meaning the application must be already published on Google Play.
After uploading the application, a link will be available to download it through the Google Play app. Before you use this link, there is one last step to be taken.
Did you know that Google Play app has a developer mode?
This is a settings for internal testing availability
Open Google Play App > Settings > Click multiple time on Play Store version
After enabling the developer mode, a new option Internal App Sharing is shown in the option. Turn this feature on to allow installation of apps shared using this tool
Now you can use the link generated in the Internal App Sharing page to download the app on your device.
Note:
Everytime you upload a new apk or bundle to Internal App Sharing, they will generate a new Link.
What Next ?
https://github.com/Triple-T/gradle-play-publisher
GPP is Android's unofficial release automation Gradle Plugin. It can do anything from building, uploading, and then promoting your App Bundle or APK to publishing app listings and other metadata.
Reference
Thank You