Gradle: Configure variables for all Android project modules in one place

Ali Muzaffar
3 min readJun 14, 2015

Gradle’s dependency management system has reduced the need to have several modules in your project, however, we may still need to include modules because of the way our project is set-up or because we are still supporting Eclipse compatible projects.

One issues that you may have come across repeatedly in old projects is that when build tools or the Android SDK is updated or you need to change variables such as the targetSdkVersion, buildToolsVersion, compileSdkVersion and more. If your project has modules, you may need to change these in each module.

Admittedly, changing these is not a very common scenario, however, the build tools usually update often enough to have made this a point of pain for me.

Solve the problem with universal variables

Fortunately, Gradle already provides us various mechanism to tackle this problem. You can create and use universal variables instead of hard coding your values. For Android projects one solution may be to configure your variables in gradle.properties, an other solution may be to use the ExtraPropertiesExtension. The advantage of ExtraPropertiesExtension is that it’s not only limited to Android Studio projects and you can control whether your variables are Strings, Integers or Floats.

Side notes:

  • For Android Studio projects it’s rather easy to manage a settings for your project by simply selecting `file > project structure` and the settings for your modules, you don’t have to do it through the text files. However, lets face it, you’ll probably do it through the text files.
  • I've noticed that Android Studio does tend to automatically update buildToolsVersion at least, I'm note sure if this is only the case when the buildToolsVersion is not longer supported by your build of Android Studio or whether it does this to keep your projects on the latest build tools. Either way, this may not may not be desirable behaviour.

Using gradle.properties to create universal variables

This solution is limited to Android projects as far as I know. In <project base>/gradle.properties you can define your universal or project level variables as such:

#gradle.properties
myBuildToolsVersion=20.0.0
myMinSdkVersion=10
myTargetSdkVersion=22
myCompileSdkVersion=22

Then, after a sync, you can use these in your gradle.properties files for all your modules as follows:

android {
compileSdkVersion project.myCompileSdkVersion.toInteger()
buildToolsVersion project.myBuildToolsVersion

defaultConfig {
applicationId "com.alimuzaffar.android"
minSdkVersion project.myMinSdkVersion.toInteger()
targetSdkVersion project.myTargetSdkVersion.toInteger()
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

Caution: I don’t like this approach because values are parsed as Strings. If you provide a value for something that should be an integer, you may see an error when you sync your project:

Error:Cause: failed to find target 22 : Install missing platform(s) and sync project

If you come across this, try using `toInteger()` on the variables that should be integers or depending on your use case, `toFloat()` as shown in the example above.

Using the ExtraPropertiesExtension to create universal variables

The main advantage here as pointed out earlier is that you are not limited to Android Studio projects and this should work with all Gradle projects. Additionally, you can define something to be a String by putting it quotes or type a whole number for an Integer or a decimal number for a Float. In order to use the ExtraPropertiesExtension, in your <project base>/build.gradle add:

allprojects {
repositories {
jcenter()
}
//THIS IS WHAT YOU ARE ADDING
project.ext {
myBuildToolsVersion="20.0.0" //String
myMinSdkVersion=10 //Integer
myTargetSdkVersion=22
myCompileSdkVersion=22
}
}

Then after a sync, in your build.gradle files for each module you can use this like so:

android {
compileSdkVersion project.ext.myCompileSdkVersion
buildToolsVersion project.ext.myBuildToolsVersion

defaultConfig {
applicationId "com.alimuzaffar.android"
minSdkVersion project.ext.myMinSdkVersion
targetSdkVersion project.ext.myTargetSdkVersion
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

This works because we are setting properties in the extra properties scope. You may be tempted to use project.setProperty(…,…) to set an extra value or project.property(…) to read one, don’t do it; these methods search existing properties in the 5 scopes and throws exceptions of the property is not found.

Got any tips?

Do you have any tips for improving your builds using Gradle? Let me know in the comments.

For more Android development article or follow me on LinkedIn, Twitter, Google+.

--

--

Ali Muzaffar

A software engineer, an Android, and a ray of hope for your darkest code. Residing in Sydney.