/ android studio

Setup build.gradle to Build Multiple Android APKs

Android is a platform with varies devices and OSes, which make it is more or less interesting with developers. Since Eclipse era, developers want to build multiple Android binary with multiple resources while sharing same code base. We have achieved this by using Ant script to invoke many complex commands, copy file, redirect resources, packaging, multiple key hash and so on. Android Studio takes this feature a leap by natively support for multiple flavours Android binary with Gradle. Today we are going to create a bone project, ready with multiple-binary build and use some tricks to create better team-work experiment, as well as utilize Gradle performance and speed.

Create Project

Creating a new project using Android Studio is straightforward:

AS_NewProject

Continue to create activity. We left the fields as default because we do not care about them for now.

AS_NewActivity

Now when Android Studio is completed its Gradle building, we care about Project Window and Gradle Task Window:

AS_GradleWindow AS_ProjectWindow

buid.gradle Blocks

We will take a look at build.gradle inside our module, there are several important blocks:

apply plugin: 'com.android.application'

This command asks Gradle to apply a specific plugin to current module.

dependencies { compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0' }

Dependencies block lists all local or remote dependencies of current module. Gradle will download and build the dependency if needed, then link it to the module.

android {
  compileSdkVersion 22
  buildToolsVersion "22.0.1"
  defaultConfig {
    applicationId "com.codentrick.multipleflavours"
    minSdkVersion 15
    targetSdkVersion 22
    versionCode 1
    versionName "1.0"
  }
  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

Android block, contains configurations for the module. You can see we have compileSdkVersion, is SDK which will be used to compile project, and version of buildTools. We also have defaultConfig, which lists appId, minSdk, targetSdk, versionCode and versionName of the module. We have another buildTypes block, which apply configurations to each build type.

Enable Global Build Tools Settings

As build.gradle inside a module specifies its own compileSdk, buildTools, minSdk and targetSdk, sometimes when you want use these parameters for all modules inside project with an unified value. Assume that you have 4 separate modules, then if you want to change buildTools version or want to target another Android version, you have to manually change this value inside each module’s build.gradle.

Or, we can use Groovy, to have all our build.gradle to read those value from a properties file. We open up the gradle.properties file. Note that this file is at top-level, project scope instead of be inside a module.

# Project-wide Gradle settings.
# ...
# org.gradle.parallel=true

The idea here, is to put our common values inside this file, we should have it to declare 4 values like this:

ANDROID_BUILD_MIN_SDK_VERSION=15 
ANDROID_BUILD_TARGET_SDK_VERSION=22 
ANDROID_BUILD_TOOLS_VERSION=22.0.1
ANDROID_BUILD_SDK_VERSION=22

Then we refer to those values inside our build.gradle:

android {
  compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) 
  buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION 
  defaultConfig {
    ...
    minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION) 
    targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION) ... } 
    ...

By this way, our values will be refered to global properties, and when we need to change the value, we only change properties file, then sync project again if needed.

Create Build Flavours

Android Studio supports we create multiple flavours for our project. Each flavour has its own release and debug build. For example, in my project, I want to have two versions: one has advertisings, and other does not. In code, it should be defined by a Boolean constant, but that’s not enough to create multiple APKs. We don’t want to change the flag and rebuild project everytime. Gradle allows us to define such value inside our build.gradle so we can refer to it from our code. Like this:

defaultConfig {
  ...
  minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION) 
  targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
  ... 
  resValue "bool", "build_variant_ad", "false"
}

Here, I define a constant called build_variant_ad of type Bool, with value is false. This constant can be refered using R.bool.build_variant_ad just like normal values defined inside resource directory.

Then, inside android block, I create a productFlavors entry:

productFlavors {
  adEnabled {
    resValue "bool", "build_variant_ad", "true"
  }

  adDisabled {
    resValue "bool", "build_variant_ad", "false"
  }
}

Here I have two flavors for my app called adEnabled and adDisabled. Within each flavor, I redefine the build_variant_ad constant with different value. This configuration will make Gradle to create corresponding build. So, how to ask Android Studio to build such version?

Using Gradle Tasks

Now take a look at Gradle window:

AS_FlavorTask

You can see the plugin has automatically create corresponding tasks. Each flavor has its own debug and release task to use. So, double click on:

  • assembleAdDisabledDebug: will build debug apk with ad is disabled
  • assembleAdDisabledRelease: will build release apk with ad is disabled
  • assembleAdEnabledDebug: will build debug apk with ad is enabled
  • assembleAdEnabledRelease: will build release apk with ad is enabled
  • assembleAdDisabled: will build both debug and release apks with ad is disabled
  • assembleAdEnabled: will build both debug and release apks with ad is enabled
  • assembleDebug: will build debug apks with all flavors
  • assembleRelease: will build release apks with all flavors
  • assemble: will build all combinated apks

With Gradle, creating multiple version for our app is now easier than Eclipse and Ant era. It is also a powerful tool for us to create more complex tasks and configurations with Android. So, wish you are happy with this tutorial and see you in next post.