1 of 47

Dynamic Feature Module

For A/B Testing a New Product

Deni Rohimat

ADB Ngabuburit - 16 May 2020

2 of 47

Overview

  • What is A/B Testing ?
  • What is Dynamic Delivery ?
  • How to build a simple Dynamic Feature ?
  • Using Internal App Sharing

3 of 47

A/B Testing

4 of 47

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)

5 of 47

How are the stages?

  • Determine the goals to be achieved
  • Determine what parts you want to be tested using A / B Testing and the hypothesis
  • Prepare the application to be able to display both versions of the page
  • Distribute both versions of the page
  • Analyze the results

6 of 47

Dynamic Delivery

7 of 47

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.

8 of 47

Base Feature

  • 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.
  • Google Play generates the base APK for your app from your project’s app (or base) module. �If you are concerned with reducing your app’s initial download size, it’s important to keep in mind that all code and resources included in this module are included in your app’s base APK.

9 of 47

Configurations 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. Unlike the base and dynamic feature modules, you don't create a separate module for configuration APKs.

10 of 47

Dynamic Feature APKs

  • Each of these APKs contains code and resources for a feature of your app that you modularize using dynamic feature modules.
  • Through Dynamic Delivery, you can then customize how and when that feature is downloaded onto a device. For example, 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.
  • Dynamic features may not be available at install time, you should include any common code and resources in the base APK.
  • Google Play generates dynamic feature APKs for your app from your project’s dynamic feature modules.

11 of 47

12 of 47

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"

}

}

13 of 47

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.

14 of 47

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.

15 of 47

16 of 47

17 of 47

18 of 47

19 of 47

20 of 47

21 of 47

22 of 47

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.

23 of 47

Some differences between a Dynamic Feature module and a regular Feature one:

  • Plugin in ondemand/build.gradle is com.android.dynamic-feature
  • The dependency between :app and :ondemand is inverted. Meaning that :ondemand knows :app, but not the opposite.

:app

:ondemand

24 of 47

  • Dynamic Feature AndroidManifest.xml containing the preferences:

<dist:module

dist:instant="false"

dist:title="@string/title_ondemand">

<dist:delivery>

<dist:on-demand />

</dist:delivery>

<dist:fusing dist:include="true" />

</dist:module>

25 of 47

  • The app/build.gradle adds the Dynamic Feature:

android {

...

dynamicFeatures = [":ondemand"]

}

26 of 47

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'

27 of 47

Add DynamicApp class in your :app module

class DynamicApp : Application() {

override fun attachBaseContext(base: Context?) {

super.attachBaseContext(base)

SplitCompat.install(this)

}

}

28 of 47

Add OnDemandActivity class in your :ondemand module

class OnDemandActivity : AppCompatActivity() {

// other lifecycle functions

override fun attachBaseContext(base: Context?) {

super.attachBaseContext(base)

SplitCompat.install(this)

}

}

29 of 47

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.

30 of 47

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

31 of 47

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

32 of 47

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

33 of 47

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

34 of 47

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

35 of 47

Your App is ready to be published!

36 of 47

37 of 47

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.

38 of 47

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.

39 of 47

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?

40 of 47

This is a settings for internal testing availability

41 of 47

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

42 of 47

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.

43 of 47

44 of 47

45 of 47

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.

46 of 47

Reference

47 of 47

Thank You