Stephen McCormick Stephen McCormick - 1 year ago 92
Android Question

Android White Labeling using Android Studio Flavors

I have recently moved from Eclipse to Android Studio, and after some effort have the application up and running. Now I face the second obstacle - generating white label versions of the application. I have read everything I can find on the Flavor mechanism in Android Studio and I believe it will work but there are few questions I still have.

But first let me explain the current white labeling mechanism that we use employing Ant (due to an upgrading of the support library I don't think I can use it anymore since it does require the presence of Jar files in lib folder?). This Ant script reads a

build.xml
file where we have specified the location of the new values (
strings.xml
and
colors.xml
) and resource folders (images and such) specific to the white label. It basically copies the new files (only a few are different) and then runs the build, renaming the APK and giving it a new App Id. So in one fell swoop I can build upwards of 100 white labels with a press of a button. Included in this build is a copy mechanism which creates a copy of the new APK with a version associated with it, so if the basic flavor is
MYAPP.apk
and we are on version 44, it copies that and makes a
44-MYAPP.apk
which we keep around in case we need to roll back for those customers pulling directly from our S3 and not from GooglePlay - yeah, that is a requirement for some of them.

I think I can mimic most of this with flavors, with the following questions:


  1. I want all the builds to have the same version name and version code. If I leave the flavor config values empty, will they pick up the versions from the AndroidManifest.xml file?

  2. Is it possible to have each APK have it's own application name when generated, such
    AppHeyYou.apk
    and
    WhereIsThat.apk
    for another flavor? The examples I have seen seem to tack on a suffix to the end of APK name, I need a completely new APK name (and without the "
    Release
    " tacked on).

  3. Can I have it build the flavor, then copy it and rename it (such as
    MyApp.apk
    and copy to
    44-MyApp.apk
    ) using the version from the
    AndroidManifest.xml
    or the default config? Since there are close to a 100, changing this in each flavor config would be not be practical with each release.

  4. Is there a way to force the generation of ALL the white labels with a single push of the button. Again, doing this for each would be impractical.



Thanks for any help!

UPDATE

Just to be helpful I thought I would show the full gradle script of what I ended up with. Here is what it does:


  1. Defines the flavors

  2. When building them, gives them the name of the flavor, but with the version code tacked on in front (so Red flavor with version code 44 becomes "44-Red.apk"). I used a task to do this, but I think it works without that wrapper. However it is very slow - took a while to show up in the correct directory.

  3. I then copy that file and rename it back to just the flavor name ("Red.apk").

  4. These are copies to an external directory I name specifically for each flavor (another crazy requirement I had).



In the end my build.gradle for the application looks like this:

buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
}

dependencies {
classpath 'io.fabric.tools:gradle:1.+'
}
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'

repositories {
maven { url 'https://maven.fabric.io/public' }
}


android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
defaultConfig {
applicationId "com.mycompany.ourapp"
minSdkVersion 14
targetSdkVersion 23
versionCode 62
versionName "1.0.62"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
signingConfig signingConfigs.config
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
productFlavors {
Red {
setProperty("archivesBaseName", "red")
}
Blue {
setProperty("archivesBaseName", "blue")
}
}


applicationVariants.all { variant ->
variant.outputs.each { output ->
def path = "C:/AndroidBuilds/MyCompany.Build/" + archivesBaseName + "/"
def SEP = "-"
def flavor = variant.productFlavors[0].name
def version = variant.versionCode
def newApkName = path + version + SEP + flavor
def newApkNameNoVersion = path + flavor
output.outputFile = new File(newApkName + ".apk")
def copyMyApkTask = tasks.create(name: "copy" + variant.name + "Apk") {
copy {
from newApkName + ".apk"
into path
rename (version + SEP + flavor + ".apk", flavor + ".apk")
}
}
copyMyApkTask.mustRunAfter variant.assemble
}
}
}

dependencies {
}
}


When I have got the white labeling working and the auto run for all of those I will tack that on this too.

Answer Source

I apologize for not knowing the precise gradle terms of art, but...

I want all the builds to have the same version name and version code. If I leave the flavor config values empty, will they pick up the versions from the AndroidManifest.xml file?

If you don't specify versionCode or versionName in the productFlavors block, whatever you defined in the defaultConfig block will be applied.

Is it possible to have each APK have it's own application name when generated, such AppHeyYou.apk and WhereIsThat.apk for another flavor? The examples I have seen seem to tack on a suffix to the end of APK name, I need a completely new APK name (and without the "Release" tacked on).

Check out the applicationVariants property. It will let you write something like

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def newName = [build your filename here]
        output.outputFile = new File(output.outputFile.parent, newName);
    }
}

Can I have it build the flavor, then copy it and rename it (such as MyApp.apk and copy to 44-MyApp.apk) using the version from the AndroidManifest.xml or the default config? Since there are close to a 100, changing this in each flavor config would be not be practical with each release.

In the above applicationVariants.all block, you can access defaultConfig.versionCode and .versionName to create copies with filenames that include versioning info.

Is there a way to force the generation of ALL the white labels with a single push of the button. Again, doing this for each would be impractical.

I believe you can just run the command gradlew assemble. Running gradlew tasks outputs this (and a lot of other tasks):

Build tasks
-----------
assemble - Assembles all variants of all applications and secondary packages.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download