Examining the Gradle Files

An Android Studio project usually has two build.gradle files, one at the project level and one at the “module” level (e.g., in the app/ directory).

The Project-Level File

The build.gradle file in the project directory controls the Gradle configuration for all modules in your project. The starter project has the single app module, and many projects only need one module.

If you downloaded the Kotlin edition of the starter project, your top-level build.gradle looks like this:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
  repositories {
    google()
    mavenCentral()
  }
  dependencies {
    classpath "com.android.tools.build:gradle:7.0.2"
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30"

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
  }
}

task clean(type: Delete) {
  delete rootProject.buildDir
}

If instead you have the Java-based starter project, you will have a very similar build.gradle file, one without the Kotlin references:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
  repositories {
    google()
    mavenCentral()
  }
  dependencies {
    classpath "com.android.tools.build:gradle:7.0.2"

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
  }
}

task clean(type: Delete) {
  delete rootProject.buildDir
}

In either case, the file contains three things (besides an opening comment):

In Groovy terms, a “closure” is a block of code wrapped in braces ({ }).

There are three main closures in the project-level build.gradle file.

buildscript

The buildscript closure in Gradle is where you list sources of plugins that you want to use in the project. Hence, here you are not configuring your project so much as you are configuring the build itself.

The repositories closure inside the buildscript closure indicates where plugins can come from. Here, jcenter() is a built-in method that teaches Gradle about JCenter, a popular location for obtaining open source libraries. Similarly, google() is a built-in method that teaches Gradle about a site where it can download plugins from Google.

The dependencies closure indicates libraries that contain Gradle plugins. In the Kotlin edition of the build.gradle file, there are two such dependencies:

(the Java edition of the project will lack the Kotlin plugin)

The identifiers of the libraries (e.g., com.android.tools.build:gradle) are followed by a version number, indicating what particular version of those libraries should be used. From time to time, Android Studio will ask you to update those versions, just as it will ask on occasion for you to upgrade the version of Gradle specified in gradle-wrapper.properties. Google maintains a page listing the Gradle versions supported by each Android Gradle Plugin version

allprojects

The allprojects closure says “apply these settings to all modules in this project”. Here, we are setting up jcenter() and google() as places to find libraries used in any of the modules in our project. We will use lots of libraries in our projects — having these “repositories” set up in allprojects makes it simpler for us to request them. We will talk a bit more about libraries later in this chapter.

clean

Like many build systems, Gradle is based around tasks. Plugins and your own Gradle files teach Gradle about various tasks that it should be able to perform when requested. The clean() task in the top-level build.gradle file is one such task. As written, this task is almost useless, and it is unclear why Google includes it, other than perhaps to point out that you are able to define custom tasks.

The Module-Level Gradle File

In your app/ module, you will also find a build.gradle file. This has settings unique for this module, independent of any other module that your project may have in the future.

The Kotlin project’s edition of app/build.gradle includes a number of Kotlin references:

plugins {
  id 'com.android.application'
  id 'kotlin-android'
}

android {
  compileSdk 31

  defaultConfig {
    applicationId "com.commonsware.jetpack.hello"
    minSdk 21
    targetSdk 31
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
  kotlinOptions {
    jvmTarget = '1.8'
  }
}

dependencies {

  implementation 'androidx.core:core-ktx:1.6.0'
  implementation 'androidx.appcompat:appcompat:1.3.1'
  implementation 'com.google.android.material:material:1.4.0'
  implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
  testImplementation 'junit:junit:4.+'
  androidTestImplementation 'androidx.test.ext:junit:1.1.3'
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

…while the Java edition does not:

plugins {
  id 'com.android.application'
}

android {
  compileSdk 31

  defaultConfig {
    applicationId "com.commonsware.jetpack.hello"
    minSdk 21
    targetSdk 31
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {

  implementation 'androidx.appcompat:appcompat:1.3.1'
  implementation 'com.google.android.material:material:1.4.0'
  implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
  testImplementation 'junit:junit:4.+'
  androidTestImplementation 'androidx.test.ext:junit:1.1.3'
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

The android closure contains all of the Android-specific configuration information. The Android plugin will use this closure, where the plugin itself comes from the id 'com.android.application' line at the top, coupled with the classpath line from the project-level build.gradle file. We will explore some of the specific values defined in this closure in the next section.

This build.gradle file also has a dependencies closure. Whereas the dependencies closure in the buildscript closure in the top-level build.gradle file is for libraries used by the build process, the dependencies closure in the module’s build.gradle file is for libraries used by your code in that module. We will talk more about libraries later in the chapter.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.