As many of you are already aware, Android Studio is using Gradle behind the scenes to build your applications and libraries. Over the last year and a half, both Android Studio and Gradle have matured significantly.  With the recent Android Studio 0.8.11 release, there was a Gradle update of major versions from 1.12 to 2.1.  While most devs won’t notice a difference other than Studio telling you the newer Android plugin (version 0.13.0) requires 2.1, the jump forward can affect your Gradle based builds.  The impact comes both from the version shift from 1.x to 2.x and the Android Gradle plugin.  Let’s start with a look at the 2.0 release of Gradle.

 

Gradle 2.0

The Gradle update to 2.0 was a major step forward for the build tool.  Like many tools it introduced a number of improvements and fixed issues along the way.  In the Gradle team’s announcement about 2.0 it was stated that the major version bump is being used as a clear signal that there will be compatibility shift.  The Gradle team has done an outstanding job of maintaining backwards compatibility throughout its lifetime.  But, like any good software project, it continues to evolve and often features which are not widely used or deemed unmaintainable are dropped.  Gradle’s team indicates these features to be culled by marking them as deprecated in the documentation as well as within the tool itself.  Thus, the 2.x release indicates a clean break where things will no longer be fully compatible with previous releases.

By and large this Gradle update should have minimal to no effect on simple Android builds.  Most of the changes really had an impact on the plugin developers.  But, I did say, “minimal to no effect,” which means there are obviously some items which could kill your existing builds.  Here’s a quick punch list of major features which can affect your build:

  • Build scripts are assumed to be in UTF-8 encoding.  For Android Studio users, this isn’t a problem as that is the default.  If you are manually creating your own build files, you’ll need to watch for this.
  • Groovy update to 2.x.  This primarily affects plugin developers, but if your build scripts are heavily using Groovy you may encounter some hiccups.  On the flip side, your scripts can now also take advantage of newer Groovy features, such as JDK 7 functionality and static type checking.
  • Certain features and APIs have been deprecated.  If you have seen warnings in your command line builds about a deprecated feature, it has most likely shifted to be an error/exception in Gradle 2.0.  The policy the team uses is if a feature has been marked deprecated for at least 2 releases then it can be removed.
    • The most common feature I’ve seen warnings (and now exceptions) with is dynamic properties.  Gradle has been warning about this for a while:
      ...
      Compiling build file '.../build.gradle' using BuildScriptTransformer.
      Creating properties on demand (a.k.a. dynamic properties) has been deprecated and is scheduled to be removed in Gradle 2.0...
      ...
      
    • If your build scripts are tapping into Gradle’s GradleRunnerFactory, UIFactory or ExternalUtility will fail as these have been removed.
    • The Project class has had numerous deprecated methods removed, most have been replaced with another API or have an alternative mechanism for getting the same funcitonality.
  • Gradle DSL changes for file and dependency management
    • The Project.file() and CopySpec.into() methods no longer accept arbitrary inputs: the types have to be recognized or it is an error.
    • The Project.tarTree() and Project.zipTree() methods will now error out if it cannot find specified file(s).
    • In order to provide RepositoryHandler.mavenCentral() with URLs, use the artifactUrls option rather than the urls option.
    • An ArtifactRepository cannot be modified after it has been added to a container
    • In order to use M2_HOME for mavenLocal(), it must be set as an environment variable rather than a system property
  • Task changes
    • Making changes to tasks during execution, such as calling doLast{ }, dependsOn or changing inputs/outputs is not allowed and will cause an exception
    • Tasks must have a single, public, zero-args constructor or if using an alternate constructor must use the @Inject annotation
    • The zero-args constructor paradigm has affected a number of core Gradle task types.  If you are deriving or using core Gradle tasks this could affect you.

 

Gradle 2.1

The Gradle 2.1 update builds upon the 2.0 release, adding more functionality, removing more deprecated features and fixing various issues.  Let’s start with the new features which are interesting for Android app/library builds:

  • Community plugins are easier to use via the Gradle Plugin Portal (incubating feature)
  • Faster Java builds due to more refined incremental Java build support (incubating feature)
  • Dependency exclusions are now included in POM file created by the maven-publish plugin (incubating feature)
  • Tooling APIs (used by Android Studio / Eclipse / IntelliJ) add support for cancelation and task visibility
  • Command line builds now have a ‘report’ feature to better show how builds are being performed

Luckily, of all the changes made to this Gradle update, only a couple should have any effect on Android builds:

  • JUnit class loading has been changed so that it is not done until the first test case is executed.  This change was made specifically for the Android test framework Robolectric.
  • If you are using the incubating class TaskParameter, it has been replaced with TaskExecutionRequest.

As I mentioned before, most of the 2.x changes really only affect plugins, so the average Android build should see very few issues with the Gradle update.  That being said, this means that the Android Gradle Plugin has undergone some changes.

 

Android Gradle Plugin 0.13.0

The final item to cover is the Android Gradle plugin.  While generally backwards compatible, there are a handful of changes which can affect your builds and project setup.  For those who are new to Android Studio, this is a non-issue as you’re just getting started.  However, for those already using Studio or Gradle for your builds, the work begins with your project setup.

Start by updating your project’s top level build.gradle file to use 0.13.0 of the plugin:

buildscript {
    ...
    dependencies {
        classpath 'com.android.tools.build:gradle:0.13.0'
        ...
    }
}

Gradle Update Error

As you can see, Android Studio complains in the Messages pane that Gradle 2.1 is required. The confusing part here is that you never previously installed Gradle yourself! Android Studio’s integration with the Gradle wrapper does an excellent job of hiding these details from you and maintaining the right version. But, during upgrades isn’t not always completely seamless. If you click the link in the message, Migrate to Gradle wrapper and sync project it will fix the problem automatically for you. But, what exactly did it do? If your project is using VCS this should be easy to spot. For those who are not (do it now!), have a look at the gradle/wrapper/gradle-wrapper.properties file beneath the top level project directory. The distributionUrl parameter is what is used to specify the version of Gradle used by the wrapper and it is now set to gradle-2.1-all.zip.

Having properly updated our plugin and Gradle version, we can start using the new Gradle/Groovy features. But, there are some additional things to be aware of before doing so:

  • The Android Gradle plugin has changed the way the variant output file handling is done.  This is an undocumented change which can cause custom build file errors as described here.  Now outputs are a collection of files and/or directories.
  • Manifests can now be included for test apps.
  • Library projects can have placeholder manifest files which use placeholders.  These are resolved during the build of the project using the lib when the manifests are merged.
  • The connectedCheck task will now fail if there are no tests defined

There are numerous other changes, these are just the ones which may affect existing Android builds.  For the full test, check out the Android Tools page announcements and release notes.

Overall, the rest update of the Android Graldle plugin is a great step forward.  It not only picks up the latest Gradle release features and bugfixes, but a big bump in Groovy functionality.  The migration is pretty straightforward for more builds.  What has been your experience with the update?  Did you run into any issues which I’ve not outlined here?