Customizing the build

There are a lot of ways to customize the build process, and when you are editing the build files in Android Studio, it is recommended to always sync the project with the Gradle files, no matter what you are customizing. This becomes especially important when you start adding dependencies or BuildConfig fields, which we will talk about soon.

Android Studio will show a message in the editor as soon as you edit settings.gradle or build.gradle, and it is possible to trigger the sync at all times by navigating to Tools | Android | Sync Project with Gradle Files or the corresponding button in the toolbar.

Customizing the build

Under the hood, the Android Studio Sync actually runs the generateDebugSources task to generate all the necessary classes, based on the configuration in the build files.

Manipulating manifest entries

We already saw that it is possible to configure applicationId, minSdkVersion, targetSdkVersion, versionCode, and versionName directly from the build files, instead of in the manifest file. There are a few more properties that you can manipulate:

  • testApplicationId is the application ID for the instrument test APK
  • testInstrumentationRunner is the name of the JUnit test runner to be used for running your test (see Chapter 6, Running Tests)
  • signingConfig (see Chapter 4, Creating Build Variants)
  • proguardFile and proguardFiles (see Chapter 9, Advanced Build Customization)

Inside Android Studio

Instead of manually making changes in the build files, you can also change the basic settings in the Project Structure dialog in Android Studio. You can open the dialog from the File menu, and it enables you to edit project-wide settings and settings per module. For every Android module, you can change the standard Android plugin properties and all the manifest properties. In the following screenshot, you can see the properties for the release version of the app module in the Project Structure dialog:

Inside Android Studio

Be aware that if you make any changes in the Project Structure dialog, Android Studio will write the changes to the Gradle build configuration file.

BuildConfig and resources

Ever since SDK tools revision 17, the build tools generate a class called BuildConfig, which contains a DEBUG constant that is set according to the build type. This is useful if you have code that you only want to run when debugging, such as logging. It is possible through Gradle to extend that file so that you can have constants that contain different values in debug and release.

These constants are useful for toggling features or setting server URLs, for example:

android {
    buildTypes {
        debug {
            buildConfigField "String", "API_URL", ""http://test.example.com/api""
            buildConfigField "boolean", "LOG_HTTP_CALLS", "true"
        }
        
        release {
            buildConfigField "String", "API_URL", ""http://example.com/api""
            buildConfigField "boolean", "LOG_HTTP_CALLS", "false"
        }
    }
}

The escaped double quotes around the string value are necessary for it to be generated as an actual string. After adding the buildConfigField lines, it is possible to use BuildConfig.API_URL and BuildConfig.LOG_HTTP in your actual Java code.

More recently, the Android Tools team has also added the possibility to configure resources in a similar manner:

android {
    buildTypes {
        debug {
            resValue "string", "app_name", "Example DEBUG"
        }
        
        release {
            resValue "string", "app_name", "Example"
        }
    }
}

The escaped double quotes are not necessary here, because resource values are always wrapped with value="" by default.

Project-wide settings

If you have multiple Android modules in one project, it can be useful to apply settings to all of them without manually changing the build file for every module. We already saw how the allprojects block is used in the generated top-level build file to define repositories, and you can use the same strategy to apply Android-specific settings as well:

allprojects {
    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 22
        buildToolsVersion "22.0.1"
    }
}

This will only work if all your modules are Android app projects though, because you need to apply the Android plugin to get access to the Android-specific settings. A better way to achieve this behavior is to define the values in the top-level build file, and then apply them in the modules. It is possible in Gradle to add extra ad hoc properties on the Project object. This means that any build.gradle file can define extra properties, and this happens in an ext block.

You can add an ext block with custom properties to the top-level build file:

ext {
    compileSdkVersion = 22
    buildToolsVersion = "22.0.1"
}

This makes it possible to use the properties in module-level build files using rootProject:

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
}

Project properties

The ext block in the previous example is a way of defining extra properties. You can use properties to customize a build process on the fly, and we will make use of them when we start writing custom tasks in Chapter 7, Creating Tasks and Plugins. There are several ways to define properties, but we will only look at the three most used ones:

  • The ext block
  • The gradle.properties file
  • The -P command-line parameter

Here is an example build.gradle file that incorporates those three ways of adding extra properties:

ext {
  local = 'Hello from build.gradle'
}

task printProperties << {
  println local        // Local extra property
  println propertiesFile        // Property from file
  if (project.hasProperty('cmd')) {
    println cmd        // Command line property
  }
}

This is the accompanying gradle.properties file (in the same folder):

propertiesFile = Hello from gradle.properties

Note

In the example, we create a new task. We will look at tasks and explain the syntax in Chapter 7, Creating Tasks and Plugins.

If you run the printProperties task with a command-line parameter, the output will look like this:

$ gradlew printProperties -Pcmd='Hello from the command line'
:printProperties
Hello from build.gradle
Hello from gradle.properties
Hello from the command line

Thanks to custom properties, changing the configuration of a build is as easy as changing a single property, or even just adding a command-line parameter.

Note

It is possible to define properties, both in the top-level build file and in the module build files. If a module defines a property that already exists in the top-level file, it will simply override it.

Default tasks

If you run Gradle without specifying a task, it runs the help task, which prints some information on how to work with Gradle. This happens because the help task is set as the default task. It is possible to override the default task and have a very common task, or even multiple tasks, run every time you execute Gradle without explicitly specifying the task.

To specify default tasks, add this line to the top-level build.gradle file:

defaultTasks 'clean', 'assembleDebug'

Now, when you run the Gradle wrapper without any parameters, it will run clean and assembleDebug. It is easy to see which tasks are set as default by running the tasks task and filtering the output.

$ gradlew tasks | grep "Default tasks"
Default tasks: clean, assembleDebug
..................Content has been hidden....................

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