Introduction

During software development process developers and QAs may want to have installed release and debug version of the app on a single device, what can be very helpful when they want to develop and use application at the same time. Another advantage is the fact that debug and release version of the app may need different configuration. It this post I will show you an example in which we are changing application name and launcher icon, but we can also change different values during compilation in the same way (e.g. address of the webservice). Some time ago, I’ve created similar template, but it was using older version of Build Tools, Android SDK and Android Studio. I’ve created new template, with the newest version of Android Studio (1.0.2) and newest version of Build Tools (1.0.0), so in that case, build.gradle file is smaller and simpler, but does its work correctly.

Exemplary repository

You can find exemplary project template at: https://github.com/FutureProcessing/android-debug-release-template. All important information are included in README.md file and build.gradle file with project configuration. Important files:

Source of essential build.gradle file presenting main idea is as follows:

import java.text.SimpleDateFormat

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"

    def appNameRelease = "My app"
    def appNameDebug = "My app debug"
    def launcherIconRelease = "@drawable/ic_launcher"
    def launcherIconDebug = "@drawable/ic_launcher_debug"

    signingConfigs {
        releaseConfig {
            storeFile file("../key/android-debug-release-template.jks")
            storePassword "SamplePassword1234"
            keyAlias "android-debug-release-template"
            keyPassword "SamplePassword1234"
        }
    }

    defaultConfig {
        applicationId "fp.com.debugreleasetemplate"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 1
        versionName gitSha() + '-' + buildTime()
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    buildTypes {
        debug {
            applicationIdSuffix '.debug'
            versionNameSuffix '-DEBUG'
            resValue "string", "app_name", appNameDebug
        }

        release {
            resValue "string", "app_name", appNameRelease
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.releaseConfig
        }
    }

    android.applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.processManifest.doLast {
                if (variant.buildType.isDebuggable()) {
                    def manifestOutFile = output.processManifest.manifestOutputFile
                    def newFileContents = manifestOutFile.getText('UTF-8').replace(launcherIconRelease, launcherIconDebug)
                    manifestOutFile.write(newFileContents, 'UTF-8')
                }
            }
        }
    }
}

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

def buildTime() {
    def df = new SimpleDateFormat("yyyyMMddHHmmss")
    df.setTimeZone(TimeZone.getTimeZone("Europe/Warsaw"))
    return df.format(new Date())
}

def gitSha() {
    return 'git rev-parse --short HEAD'.execute().text.trim()
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.2.1'
}