Configuring git submodules on a Gradle Android project can be painful when shared dependencies need to be updated. I’ve lost count of how many times I’ve had to reconfigure my project and its submodule dependencies after updating my Android SDK. I encountered this annoyance again recently and decided that there must be a better way to handle the matter. Enter Gradle extra properties extension.
After updating my Android framework, I compiled my project in Android Studio and immediately got this error:
Error:The SDK Build Tools revision (23.0.3) is too low for project ':standardlib'. Minimum required is 25.0.0
<a href="fix.build.tools.version">Update Build Tools version and sync project</a><br><a href="openFile:/root_project_path/standardlib/build.gradle">Open File</a>
I found this to be quite aggravating, and my initial reaction was to manually increment the submodule’s build tools version. This turned out to be a poor decision because I saved little time in the moment to maintain my momentum with the feature I was working on. I suffered the consequence from the decision because I encountered the same issue again when I started a new feature before merging the one I’d just finished.
I decided to pay the cost and implement Gradle extra properties extension (
read more here
) in my project’s root
build.gradle
. This allows me to configure the submodule from my root project so hopefully, I won’t encounter this again. I also won’t need to modify the submodule’s
build.gradle
again. Well, not for this reason, anyway.
In my root project’s
build.gradle
I added an
ext
block at the root level:
buildscript {
ext {
buildToolsVersion = "25.0.2"
compileSdkVersion = 25
In my submodule’s
build.gradle
I had to reference those properties:
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
And my work is done, right? Well, sort of – I had another submodule that needed to be updated. I can also use these same properties in my app module’s
build.gradle
file so that I only need to update this value in one place. Configuring the app module works exactly the same as configuring a library submodule. I just replaced the values for
compileSdkVersion
and
buildToolsVersion
in the
android
block with the references to
rootProject.ext.compileSdkVersion
and
rootProject.ext.buildToolsVersion
respectively.
Related: Level-up with Android Studio Shortcuts and Live Templates
This feature of Gradle can be quite useful. I am also using it to configure support library versions in use throughout the project. I added a value to the
ExtraPropertiesExtension
for the support libraries,
androidSupportLibraryVersion
and gave it a value corresponding to the latest support library version,
"25.3.0"
. Now, my
ext
block in my root
build.gradle
file looks something like this:
buildscript {
ext {
buildToolsVersion = "25.0.2"
compileSdkVersion = 25
androidSupportLibraryVersion = "25.3.0"
I only had to make the appropriate references in my other
build.gradle
files to get everything compiled and using the same support library version. Here is an excerpt from my app’s
build.gradle
with that change in place:
dependencies {
compile project(':standardlib')
compile "com.android.support:support-v4:$rootProject.ext.androidSupportLibraryVersion"
compile "com.android.support:appcompat-v7:$rootProject.ext.androidSupportLibraryVersion"
compile "com.android.support:recyclerview-v7:$rootProject.ext.androidSupportLibraryVersion"
compile "com.android.support:cardview-v7:$rootProject.ext.androidSupportLibraryVersion"
compile "com.android.support:design:$rootProject.ext.androidSupportLibraryVersion"
Note that in this case, you need to ensure that the string is in double quotes instead of single quotes and lead the reference with a dollar sign
$
so that the string interpolation will function correctly. Now I have all of my modules using the same support library version.
It is important to understand that the names I’ve chosen for my extra properties are for my convenience only and could have been anything. You can add whatever extra properties you like and use them any way that best suits your project.
For example, I am using a Gradle plugin called
GrGit
to help me set my
versionName
in a reasonable fashion based on the contents of source control:
import org.ajoberstar.grgit.Grgit
buildscript {
dependencies {
classpath 'org.ajoberstar:grgit:1.6.0'
ext {
git = Grgit.open()
gitVersionName = "${git.describe()}"
buildToolsVersion = "25.0.2"
compileSdkVersion = 25
androidSupportLibraryVersion = "25.3.0"
Now, in my app module’s
build.gradle
I can easily set the version name based on the most recent tag and the number of commits since then:
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {