Chapter 2. Basic Build Customization

We started out by looking at the uses of Gradle, and creating and converting Android projects. Now it is time to get a better understanding of the build files, to look at some useful tasks, and to explore the possibilities of both Gradle and the Android plugin.

In this chapter, we will look at the following topics:

  • Understanding the Gradle files
  • Getting started with build tasks
  • Customizing the build

Understanding the Gradle files

When creating a new project with Android Studio, three Gradle files are generated by default. Two of those files, settings.gradle and build.gradle, end up on the top level of the project. Another build.gradle file is created in the Android app module. This is how the Gradle files are placed in the project:

MyApp
├── build.gradle
├── settings.gradle
└── app
    └── build.gradle

These three files each serve their own purpose, which we will further look into in the upcoming sections.

The settings file

For a new project containing only an Android app, settings.gradle looks like this:

include ':app'

The settings file is executed during the initialization phase, and defines which modules should be included in the build. In this example, the app module is included. Single module projects do not necessarily require a settings file, but multimodule projects do; otherwise, Gradle does not know which modules to include.

Behind the scenes, Gradle creates a Settings object for every settings file, and invokes the necessary methods from that object. You do not need to know the details of the Settings class, but it is good to be aware of this.

Note

A full explanation of the Settings class is out of the scope of this book. If you would like to know more, you can find a lot of information in the Gradle documentation (https://gradle.org/docs/current/dsl/org.gradle.api.initialization.Settings.html).

The top-level build file

The top-level build.gradle file is where you can configure options that need to be applied to all the modules in the project. It contains two blocks by default:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

The buildscript block is where the actual build is configured. We looked at this briefly in Chapter 1, Getting Started with Gradle and Android Studio. The repositories block configures JCenter as a repository. In this case, a repository means a source of dependencies or, in other words, a list of downloadable libraries that we can use in our apps and libraries. JCenter is a well-known Maven repository.

The dependencies block is used to configure dependencies for the build process itself. This means that you should not include dependencies that you need for your applications or libraries in the top-level build file. The only dependency that is defined by default is the Android plugin for Gradle. This is required for every Android module, because it is this plugin that makes it possible to execute Android-related tasks.

The allprojects block can be used to define properties that need to be applied to all modules. You can take it even further and create tasks in the allprojects block. Those tasks will then be available in all modules.

Note

As soon as you use allprojects, the modules are coupled to the project. This means that it will likely be impossible to build the modules separately, without the main project's build file. It might not seem like an issue at first, but later you might decide to separate an internal library into its own project, and then you will need to refactor your build files.

The module build file

The module-level build.gradle file contains options that only apply to the Android app module. It can also override any options from the top-level build.gradle file. The module build file looks like this:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.gradleforandroid.gettingstarted"
        minSdkVersion 14
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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

We will take a detailed look at the three main blocks.

Plugin

The first line applies the Android application plugin, which is configured as a dependency in the top-level build file, which we discussed earlier. The Android plugin is written and maintained by the Android Tools team at Google, and provides all tasks needed to build, test, and package Android applications and libraries.

Android

The biggest part of the build file is the android block. This block contains the entire Android-specific configuration, which is available through the Android plugin we applied earlier.

The only properties that are required are compileSdkVersion and buildToolsVersion:

  • The first one, compileSdkVersion, is the API version of Android that you want to use to compile your app
  • The second one, buildToolsVersion, is the version of build tools and compilers to use

The build tools contain command-line utilities, such as aapt, zipalign, dx, and renderscript; which are used to produce the various intermediate artifacts that make up your application. You can download the build tools through the SDK Manager.

The defaultConfig block configures core properties for the app. The properties in this block override the corresponding entries in the AndroidManifest.xml manifest file:

defaultConfig {
    applicationId "com.gradleforandroid.gettingstarted"
    minSdkVersion 14
    targetSdkVersion 22
    versionCode 1
    versionName "1.0"
}

The first property in this block is applicationId. This overrides the package name from the manifest file, but there are some differences between applicationId and the package name. Before Gradle was used as the default Android build system, the package name in AndroidManifest.xml had two purposes: it served as the unique identifier of an app, and it was used as the name for the package in the R resource class. Gradle makes it easier to create different versions of your app, using build variants. For example, it is very easy to make a free version and a paid version. These two versions need to have separate identifiers, so they appear as different apps on the Google Play Store, and can both be installed at the same time. The source code and generated R class, however, must retain the same package name at all times. Otherwise, all your source files would need to change, depending on the version you are building. That is why the Android Tools team has decoupled these two different usages of package name. The package, as defined in the manifest file, continues to be used in your source code and your R class, while the package name that is used by the device and Google Play as the unique identifier is now referred to as application id. This application ID will become a lot more interesting as we start experimenting with build types.

The next two properties in defaultConfig are minSdkVersion and targetSdkVersion. Both of these should look familiar because they have always been defined in the manifest as part of the <uses-sdk> element. The minSdkVersion setting is used to configure the minimum API level required to run the app. The targetSdkVersion setting informs the system that the app is tested on a specific version of Android, and that the operating system does not need to enable any forward-compatibility behavior. This has nothing to do with compileSdkVersion that we saw earlier.

The versionCode and versionName also have the same function as in the manifest file, and define a version number and a user-friendly version name for your app.

All values in the build file will override the values in the manifest file. It is therefore not required to define them in the manifest file if you define them in build.gradle. In case the build file does not contain a value, the manifest values will be used as a fallback.

The buildTypes block is where you define how to build and package the different build types of your app. We will take a detailed look at build types in Chapter 4, Creating Build Variants.

Dependencies

The dependencies block is a part of the standard Gradle configuration (that is why it is placed outside of the android block) and defines all dependencies for an app or library. By default, a new Android app has a dependency on all the JAR files in the libs directory. Depending on the options you select in the new project wizard, it might also depend on the AppCompat library. We will discuss dependencies in Chapter 3, Managing Dependencies.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.132.99