Gradle Revisited

Back in May 2013 Google announced at IO that they were working on a completely new IDE based upon IntelliJ IDEA which would be based upon the Gradle build system. At the end of June in the same year I began a series of posts which ended up as a series of 9 posts (the longest in the history of Styling Android) covering various aspects of the Gradle build system for Android. Looking back at the code it used Gradle 1.6 and V 0.5.x of the Android Gradle plugin. Now that Android Studio is fully released along with V1.x of the Android Gradle plugin, we’ll revisit this project, take a look at what has changed, and bring it up-to-date so that it works with the latest build tools.

The obvious first thing that we need to look at is the versions of both Gradle and the Android Gradle plugin that we’re going to use for the build. For Gradle we simply need to update the gradle-wrapper.properties file:

All we need to do here is update to the latest version of Gradle (which is 2.2.1 at the time of writing).

Next we need to update to the latest Android build tools. Back in the original series we looked at how we could define certain build attributes such as target and minimum SDK versions in one place so that we only needed to change things one in order to apply those changes to all sub-projects. This is where we reap the benefits of that – we can change things in one place and it will change both of the child projects:

build.gradle

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript{

repositories{

jcenter()

}

dependencies{

classpath'com.android.tools.build:gradle:1.0.0'

}

}

ext.compileSdkVersion=21

ext.buildToolsVersion="21.1.2"

ext.minSdkVersion=7

ext.targetSdkVersion=21

While we’re at it, we’ll also switch the repository that we’re using to jcenter instead of Maven Central.

The next thing that we need to do is change the name of the plugins that we’re going to apply to the two child projects. This is because the plugin names were changed from android and android-library to com.android.application and com.android.library respectively. The other things worth doing is updating the version of the support library that we’re using:

Here I must confess to a bug in the code in the original article. In the code where we add custom tasks to the existing dependencies, the piece of code which defines the task we wish to add appears outside of the check that the taskName matches a specific pattern – so we’ll effectively replace the implementation of all tasks which get added after we set up this handler. In the current Android Gradle plugin the debug signing credentials get inject via a custom task – and this bug was blocking that. So we need to change this:

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

task custom(description:'This is our custom task')<<{task->

println"Running task ${task.name}"

}

assemble.dependsOn(custom)

assemble.dependsOn('customAssemble')

project.tasks.addRule("Pattern: customAssemble<TaskName>"){taskName->

if(taskName.startsWith("customAssemble")){

println"Creating task ${taskName}"

android.applicationVariants.all{variant->

println"Adding dependency to assemble${variant.name}"

def targetTask=project.tasks.findByName("assemble${variant.name}")

if(targetTask!=null){

targetTask.dependsOn("customAssemble${variant.name}")

}

}

task(taskName)<<{task->

println"Running custom task ${task.name}"

}

}

}

And with that, our project will now build with the current (at the time of writing) Android build tools – Android Gradle plugin V1.0.0 and Android Studio V1.0.2.

Although the project from the previous series now works, we’re not quite finished yet. I recently had to align an existing, rather more complex project with the release build tools and had some additional issues to resolve. In the final few Android Gradle plugin releases prior to the full 1.0.0 release, there were a number of tidy ups which removed some deprecated stuff. This meant that stuff which was working perfectly with the old deprecated methods suddenly failed. An example of this was the packageName deprecation which we encountered earlier. After I had updated all of these in the build config for the project I was still getting errors and I suspected that there were the build configs for third party libraries which were causing this.

The way to track this down was first to comment out all of the third party dependencies, and gradually re-add them one at a time to establish which of these libraries were causing the problem. Then it was a case of checking for a newer version of the libraries that were failing – and in each problem case I found a newer version was available which was compliant with 1.0.0 – so it was simply a case of changing the version number in the dependency declaration. Once all of these has been identified and updated, the build worked perfectly!

That concludes our Gradle update. The source code for this article is available here.

Many thanks to Sebastiano Poggi for the conversation which prompted this article.