Build Android project with multi flavour on Jitpack

Lately my team has built an Android project that needs to run on multiple channels and platform: Google, Amazon, mobile, tablet and TV. It took us sometime to plan to enable us working in parallel within tight Sprint schedule.

At the end we designed a structure that includes a core module which is shared on Jitpack, with locally build UI modules that supports different platforms. We also used Gitflow to ensure smooth merging with control.

This plan worked till we had challenges over selecting multi building variants from Android studio’s drop down list, after uploading the core module to Jitpack. The end goal is to allow us to do so without developers have to manually change their environment in code each time.

Step 1: Add build flavour in core module build.gradle

Define keywords for your platform environment in flavorDimensions column, and assign them to approriate categories inside the Product flavours block. The if function after dependencies build variants into release version of aar, so that they are available to use from Jitpack.

apply plugin: 'com.android.library'
android {
compileSdkVersion compileSdkVersion
buildToolsVersion buildToolsVersion
flavorDimensions "platform", "environment"
publishNonDefault true
defaultConfig {minSdkVersion minSdkVersion}
buildTypes {
release { ... }
debug { ... }
}
productFlavors {
amazon {dimension "platform"}
playstore {dimension "platform"}
production {dimension "environment"}
preprod {dimension "environment"}
}
dependencies {...}
if (android.productFlavors.size() > 0) {
android.libraryVariants.all { variant ->
if (variant.name.toLowerCase().contains(“debug”)) {
return
}
def bundleTask = tasks[“bundle${variant.name.capitalize()}Aar”]
artifacts {
archives(bundleTask.archivePath) {
classifier variant.name.capitalize().replace(“Release”, “”)
builtBy bundleTask
name = project.name
}
}

Step 2: Add configuration in your module gradle

I am using Gradle version of gradle-4.6-all and the Gradle files so far looks similar to core module, except the last part, where we need to define importing libraries as a function, and call them from the configuration block. The line of “transitive = true” is optional, which enables dependencies sharing from the core module. For example, if Dagger was imported using api keyword in core module, setting “transitive = true” means you don’t need to import Dagger again in app module, to keep libraries version consistent.

apply plugin: 'com.android.application'

...
buildscript {...}

android {
...
flavorDimensions "platform", "environment"
defaultConfig {...}

productFlavors {
amazon {dimension "platform"}
playstore {dimension "platform"}
production {dimension "environment"}
preprod {dimension "environment"}
} }
configurations {
playstorePreprodImplementation {}
playstoreProductionImplementation {}
amazonPreprodImplementation {}
amazonProductionImplementation {}
}

dependencies {
...
def coreModule = "com.github.xxx:xxx-core"

playstorePreprodImplementation ("$coreModule:1.1.0:[email protected]") { transitive = true }
playstoreProductionImplementation ("$coreModule:1.1.0:[email protected]") { transitive = true }


amazonPreprodImplementation ("$coreModule:1.1.0:[email protected]") { transitive = true }
amazonProductionImplementation ("$coreModule:1.1.0:[email protected]") { transitive = true }

}