Written by Jacek Kwiecień
Android Developer
Published January 5, 2016

Setup Gradle for your Android project like a boss – part 1

Gradle build system gained its popularity with the native support in Android Studio a while ago. It’s quite powerful but not every developer knows how to use it to their advantage. I can’t really tell that I use all capabilities of gradle but I’ll share what I know. You might like it!

Gradle – yay! Right?

Not quite right. Gradle often gives me a headache. I was so happy to switch from Eclipse to Android Studio back in the early preview days. It was a lot faster then. Sadly, I got a feeling it became much slower within time when it comes to build time. It’s mainly gradle’s fault. Hopefuly this gets better with Android Studio 2.0, I haven’t tested it yet. It’s in early beta stage right now.

Something in return

Like every difficult relationships, the one with gradle has it’s bright ups. Let me show you what do you get in return for the terrible build time. At least the part of it I know about.

Basics

Every project you start comes with 2 build.gradle files. One applies to the whole project and the second to the app module. Later you can add more modules, like some internal libraries. Every module will get it’s own build.gradle file.

 

You have them all lisasgroupingted nicely when switching to Android grouping style in project inspector.

 

 

 

 

 

App version

Tired of incrementing version code or naming each version you build or release? Gradle can help you with that. If you’re also using git, and I hope you do, I can show you an easy way to automate that.

Gradle uses groovy programing language. Try putting this code on the top of build.gradle file of your app module:

import java.text.SimpleDateFormat

def gitSha() {
    return "git --git-dir=${rootDir}/.git --work-tree=${rootDir} rev-parse --short HEAD".execute().text.trim()
}

def buildTime() {
    def df = new SimpleDateFormat("ddMMyyyy")
    df.setTimeZone(TimeZone.getTimeZone("UTC"))
    return df.format(new Date())
}

def gitCount() {
    return "git --git-dir=${rootDir}/.git --work-tree=${rootDir} rev-list HEAD --first-parent --count".execute().text.trim()
}

def gitTag() {
    return "git --git-dir=${rootDir}/.git --work-tree=${rootDir} describe --tags --abbrev=0".execute().text.trim()
}

def getAutoVersionName() {
    return this.hasProperty("publish") ? "${gitTag()}" : "${gitTag()}-${gitSha()}-${gitCount()}-${buildTime()}"
}

def getAutoVersionCode() {
    return gitCount().toInteger()
}

Then change those 2 lines to use your newly written functions instead making you type it all over again every build:

defaultConfig {
    versionCode getAutoVersionName()
    versionName getAutoVersionCode()
}

How does it work? Well, the naming convention is up to you. With some groovy you can modify it. This is just a sample of automation process that uses count of commits as a version code.

You’re ready to build the apk the cool way. I’m using console for that. Let’s start from the kind of build you don’t intend to upload to Google Play. Enter your project directory in console and input command:

./gradlew assembleProdRelease

If everything goes fine, you’re going to see BUILD SUCCESSFUL at the end. But where is the APK? How is the file named?

Look for apk under {project_directory}/{app_module}/build/outputs/apk

The file should be named app-prod-release.apk

That’s still “meh” for me. How am I suppose to know that? Maybe I want to change file name as well? In this case I paste this code into the app build.gradle inside android {} section:

android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        output.outputFile = new File(output.outputFile.parent, "myappname-${variant.baseName}.apk")
    }

    // print the APK path after assemble is done
    variant.assemble.doLast {
        println "\nAPK: ${variant.outputs[0].outputFile}"
        println "Version: ${getAutoVersionName()} (${getAutoVersionCode()})"
    }
}

Now build again and see the console output. There are additional lines for you there:

APK: /Users/jacekkwiecien/Documents/myapp/app/build/outputs/apk/myappname-prod-release.apk
Version: 0.3.6-406ee19-195-22122015 (195)

BUILD SUCCESSFUL

Now you know where to look. Also the file is named nicely. Cool, right? 195 is version code. The longer string is a version name. What does it contain? Whatever we put in there. Let’s look again on the function that generates the name:

def getAutoVersionName() {
    return this.hasProperty("publish") ? "${gitTag()}" : "${gitTag()}-${gitSha()}-${gitCount()}-${buildTime()}"
}

This is a non-publish build, so we look on this part only:

"${gitTag()}-${gitSha()}-${gitCount()}-${buildTime()}"

First we have a git tag, if it’s there. I use tags to input version names myself when I publish the app. Later git sha comes, which is the sha of the latest commit. Finally we have git commit count and current time.

So what if it’s a build we want to publish?

First – there is an important thing to remember. Version code should be always bigger than the previous build. It doesn’t have to be latest + 1 though. If you want to release APK to Google Play – always build from the master branch, otherwise you might end up with the code lower than the latest one.

On the master branch, or whatever branch you picked to be the release branch? Good, we can choose the version name for the upcoming release. Let’s assume the latest version was named 0.3.6. In this case we want the next one to be 0.3.7. We want to set a git tag for that. To set the tag input following in the command line:

git tag -a 0.3.7

This will ask you for some comment message. You can input anything there, it’s not very relevant. Let’s just retype 0.3.7 in there. Your latest commit is tagged. We can build the APK now. Please note that we’re adding a publish param to the command.

./gradlew assembleProdDebug -Ppublish=true

The output:

APK: /Users/jacekkwiecien/Documents/myapp/app/build/outputs/apk/myappname-prod-release.apk
Version: 0.3.7 (195)

BUILD SUCCESSFUL

Now the users in the Google Play will see 0.3.7 as the version name instead some hard to read name that we used for non-publish builds.

What’s next?

Liked the version automation? Stay tuned for more. In the next part I’m going to write about easier but also very helpful features. Even if you lack some understanding of this, give it a shot just by pasting the code into your configuration file. Still good thing to brag about around your colleagues 😉

Written by Jacek Kwiecień
Android Developer
Published January 5, 2016