Gradle bits for beginners

The following tips are meant especially for who is quite new to Android Studio and Android application development in general.

Gradle Version

Any project in Android Studio can set to use the Gradle Wrapper or the local Gradle distribution.

The latter is actually stored within Android Studio and it gets updated along with the IDE.

There are two important points to highlight:

  • if we want to update the Gradle version, we have to install it manually and then tell Android Studio where to find it.
  • if we update Android Studio, importing the preferences from the previous installation, and this new version updates the Gradle version, we will have a wrong Gradle home setting. This is not pointed out clearly, so it’s always a good idea to double check.
Gradle settings
Gradle settings

Gradle Wrapper

The Gradle Wrapper is meant to ease our life, since we don’t have to deal with manual installation: it is essentially a script and a property file, which will be included in any project and it will take care of our builds.

A property file, called, is generated the first time we create a new project, pointing to a specific version of Gradle. So, if we work for weeks if not months, very likely this version will become old or obsolete.


What we have to do is simply to update the name of the zip file with a newer version of Gradle: here we can check the latest available stable version and its link.

We cannot anyway pick any Gradle version as we’ll see later.

Gradle Plugin

The Android build system uses the Android Plugin for Gradle to support building Android applications with the Gradle build toolkit.

In other words, this plugin provides all the tasks required to build, test, and package Android applications and libraries.

The version being used is generally set in the main build.gradle file of any project.

classpath ''

So, if we want to update the plugin version to get new features, we just have to update this dependency: all the revisions are provided by the official documentation.

As anticipated earlier, not all the combinations of Gradle and the Android Plugin for Gradle can work together: it’s always a good idea to have a look at the version compatibility summary page.

Projects and tasks

Projects in Gradle are something that can be built, such a JAR library or an Android APK, but also something to be done, for example deploying an application to the production environment, which actually doesn’t build a “thing”.

Any project, is made of one or more tasks, defined in the build script: these are essentially a list of actions to be performed by the build process.

In the Android context, we can see the list of the available tasks for our project in two ways.

First, from Android Studio, clicking on the Gradle label on the right side:

Gradle tasks
Gradle tasks

Second, issuing the following command in the terminal, from the root folder of our project:

./gradlew tasks
Gradle tasks
Gradle tasks

As we can see, the Android Plugin already defines several tasks for us, so we don’t have to do anything to clean or build the project, to produce an APK or to run tests on the emulator or a device.

These tasks are executed each time we click on some buttons of the Studio, like the Run green arrow for example: we know that it will trigger a build, to produce an APK to be deployed on a running emulator instance or any attached device.

In fact, opening the Gradle Console view, we can see all the details of the build being executed (debug variant in the screenshot):

Run a debug build
Run a debug build

Dry run

If we need to check which steps are performed by any task, without actually executing them, we can launch it in dry run mode.

./gradlew TASK_NAME --dry-run

We can also activate this mode using -m.

dry run
dry run

Types, flavors, variants?

We often read or hear about build types, product flavors and build variants, but what exactly are they in the context of an Android project built with Gradle?

By default, the Android Plugin sets up the project to build two types of the application, debug and release. The debug type is the default one, so it’s not necessary to declare it in the build script: all its settings are already defined for us, in order to be able to develop and test our application.

The other types, like release, can be defined in the buildTypes block of the build script.


When we create a new build type, we don’t have to set all its properties any time, but we can initialize it with an existing type, using the initWith() method, with the possibility to override properties.


If using the build types, we define different builds of the same application, with flavors we define customized versions of the application to build.

Typical examples are paid and free flavors, or in the case of a white label application, flavors can represent all the different branding. Same code base, but different theme colors, logo, images and backend URL.

In the build script, flavors can be defined in this way:

productFlavors {
        flavor1 {

        flavor2 {

Build type or flavor? In general, the suggestion is to create a new flavor when the new APK will be uploaded to the Google Play Store or published externally.

Build Type + Product Flavor = Build Variant

That’s it, a variant is obtained simply combining a build type with a product flavor. Every time a type or a flavor is defined, a new variant will be generated. Not only, but the Android Plugin will also create tasks for all the variants defined in the build script, so we don’t have to do that manually.


In a project with a lot of dependencies or with different modules having few dependencies in common, or anyway if we want to have a clean solution, there’s a nice approach firstly proposed by Fernando Cejas in his Android – Clean Architecture sample app.

The main idea is to declare the version of all the dependencies in a separate Gradle file, which can be stored anywhere in the project hierarchy folder.

Let’s call it dependencies.gradle and place it in the root folder of our project.

ext {
    // Android
    androidBuildToolsVersion = "23.0.2"
    androidMinSdkVersion = 21
    androidTargetSdkVersion = 23
    androidCompileSdkVersion = 23

    // Libraries
    androidSupportLibraryVersion = '23.1.1'

    // Testing
    robolectricVersion = '3.0'
    jUnitVersion = '4.12'

    appDependencies = [

    appTestDependencies = [

Complete file can be found on GitHub here.

Then, in the main build.gradle of our project, we include the dependency script, so it will be visible from all the modules:

apply from: 'dependencies.gradle'

Then, in the build.gradle of our module, we use it to declare our dependencies:

dependencies {
    def dataDependencies = rootProject.ext.appDependencies
    def testDependencies = rootProject.ext.appTestDependencies

    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile dataDependencies.appCompat
    compile dataDependencies.recyclerView
    compile dataDependencies.annotations
    compile dataDependencies.customTabs

    testCompile testDependencies.junit
    testCompile testDependencies.robolectric

Again, the complete file is available here on GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *