GloballyDynamic: Multi-platform dynamic delivery with a unified client API

Jesper Åman
4 min readAug 22, 2020

--

This is the third article in a three part article series on how you can leverage GloballyDynamic to accomplish tasks such as:

  • Enabling dynamic delivery for environments where it would be otherwise unavailable (e.g. Firebase App Distribution).
  • Testing various outlying dynamic delivery scenarios during development.
  • Making life easier when working with multiple dynamic delivery platforms (e.g. Play Feature Delivery or Dynamic Ability) for the same project.

Series outline:

This article will build upon the previous two articles in this series and illustrate how a project can be configured to use multiple dynamic delivery platforms without having to provide individual integrations for their respective client libraries. If you haven’t already, I suggest you give the previous two articles a quick scan before proceeding.

When I say Multi-platform in this context, it does not refer to Kotlin Multiplatform, but rather multiple dynamic delivery platforms, such as Play Feature Delivery and Dynamic Ability.

The Android library, which is introduced in the first article of the series, provides an abstraction layer on top of different dynamic delivery client APIs, you can therefore write your Kotlin/Java code once, and have it run with every underlying platform.

The library comes in different flavours, one for each underlying platform. The currently available ones are:

  • Google Play Store (Play Feature Delivery): com.jeppeman.globallydynamic.android:gplay:1.0.0
  • Huawei App Gallery (Dynamic Ability): com.jeppeman.globallydynamic.android:huawei:1.0.0
  • Self-hosted with GloballyDynamic Server (Firebase App Distribution, local development etc): com.jeppeman.globallydynamic.android:selfhosted:1.0.0

All of these flavours expose an identical API, while delegating operations to their respective underlying platforms. The way in which you configure what platform to be delegated to is through build flavours.

The remainder of this article will go through an example on how to configure a project to use dynamic delivery with 4 different environments:

  • Local development
  • Google Play
  • Huawei App Gallery
  • Firebase App Distribution

1) Adding a local development configuration

This is covered in depth in the first article of this series, however, in this article we will incorporate the development setup into a multi-platform one:

android {
globallyDynamicServers {
studioEmbedded {
throttleDownloadBy 5000
applyToBuildVariants 'debug'
}
}
}
repositories {
mavenCentral()
}
dependencies {
debugImplementation '
com.jeppeman.globallydynamic.android:selfhosted:1.0.0'
}

2) Adding a Google Play configuration

Since Google Play Store already supports dynamic delivery natively, configuring the library to delegate operations to Play Core is straightforward — we merely create a product flavour called gplay, and declare the corresponding dependency for it, like so:

android {
flavorDimensions 'platform'
productFlavors {
gplay {
dimension 'platform'
}
}
globallyDynamicServers {
studioEmbedded {
throttleDownloadBy 5000
applyToBuildVariants 'gplayDebug'
}
}
}
repositories {
mavenCentral()
google()
}
configurations {
gplayReleaseImplementation {}
}
dependencies {
debugImplementation 'com.jeppeman.globallydynamic.android:selfhosted:1.0.0'
gplayReleaseImplementation 'com.jeppeman.globallydynamic.android:gplay:1.0.0'
}

Note: the configurations {} block is necessary when declaring a dependency that is specific to both a build type and a product flavour, this is because the Android Gradle Plugin creates the combined configurations later in the build pipeline, you therefore have to declare placeholder configurations. More on that here.

If you’d rather like to use Internal App Sharing during development for Google Play, you can just remove the gplayDebug directive from applyToBuildVariants, and also change gplayReleaseImplementation to gplayImplementation.

3) Adding a Huawei App Gallery configuration

The story is the same for Huawei App Gallery as with Google Play Store; it support dynamic delivery natively. Hence configuring for operations to be delegated to Dynamic Ability is also straightforward:

android {
flavorDimensions 'platform'
productFlavors {
gplay {
dimension 'platform'
}
huawei {
dimension 'platform'
}

}
globallyDynamicServers {
studioEmbedded {
throttleDownloadBy 5000
applyToBuildVariants 'gplayDebug', 'huaweiDebug'
}
}
}
repositories {
mavenCentral()
google()
maven { url 'http://developer.huawei.com/repo' }
}
configurations {
gplayReleaseImplementation {}
huaweiReleaseImplementation {}
}
dependencies {
debugImplementation 'com.jeppeman.globallydynamic.android:selfhosted:1.0.0'
gplayReleaseImplementation 'com.jeppeman.globallydynamic.android:gplay:1.0.0' huaweiReleaseImplementation 'com.jeppeman.globallydynamic.android:huawei:1.0.0'
}

4) Adding a Firebase App Distribution configuration

Enabling dynamic delivery for Firebase App Distribution is covered in depth in the second article in this series, in this article we’re incorporating that setup into this multi-platform one. As illustrated below, we’ll now have to configure two different globallyDynamicServers:

android {
flavorDimensions 'platform'
productFlavors {
gplay {
dimension 'platform'
}
huawei {
dimension 'platform'
}
firebase {
dimension 'platform'
firebaseAppDistribution {
apkPath "${buildDir}/outputs/universal_apk/firebaseRelease/universal.apk"
}
}
}
globallyDynamicServers {
studioEmbedded {
throttleDownloadBy 5000
applyToBuildVariants 'gplayDebug', 'huaweiDebug', 'firebaseDebug'
}
firebase {
serverUrl 'http://<ip-to-server>:8080'
username 'johndoe'
password 'my-secret-password'
applyToBuildVariants 'firebaseRelease'
}

}
}
repositories {
mavenCentral()
google()
maven { url 'http://developer.huawei.com/repo' }
}
configurations {
gplayReleaseImplementation {}
huaweiReleaseImplementation {}
firebaseReleaseImplementation {}
}
dependencies {
debugImplementation 'com.jeppeman.globallydynamic.android:selfhosted:1.0.0'
gplayReleaseImplementation 'com.jeppeman.globallydynamic.android:gplay:1.0.0' huaweiReleaseImplementation 'com.jeppeman.globallydynamic.android:huawei:1.0.0' firebaseReleaseImplementation 'com.jeppeman.globallydynamic.android:selfhosted:1.0.0'
}

5) Putting it all together

Phew, that’s it as far as configuration goes. While the configuration becomes fairly meaty and involved when working with this many platforms, it allows you to only write the actual Kotlin/Java code once — as you switch between build variants you can use your same calls toGlobalSplitInstallManager.startInstall(...), without needing to modify anything.

A complete version of these steps are coalesced into the gist below, which also contains all plugin definitions you need:

With that we’ve reached the conclusion of this series of articles — for more information on the subject, such as how to publish an app on Amazon App Store or Samsung Galaxy Store with dynamic delivery, head over to the website. You can also have a look at my example project which is published on various platforms with dynamic delivery enabled.

Useful links

--

--