Gradle configuration in multi-module Android projects

This post originally appeared on my personal blog https://handstandsam.com

In my work with Android projects using multiple modules help us split apart our code into logical components.  They also can enable faster incremental builds, and more modular code.  One problem with multi-module projects is that there is a lot of verboseness of configuration.  This post shows you a method of sharing common configuration between your Android Library modules in order to cut down on boilerplate Gradle configuration.

I made this change in a PR in my ShoppingApp Project on GitHub and ended up deleting a net 90 lines of code over 7 library modules.

GitHub pull request dashboard for "common gradle config for Android library modules"

apply from: “____.gradle”

You can add the contents of another Gradle file into your current one by using “apply from: ” and specifying the file whose content you want to add.

    apply from: "$rootProject.projectDir/android-library.gradle"
  

$rootProject.projectDir

Modules can exist in different directory structures, so by leveraging the $rootProject.projectDir property, we specify paths based on the root project directory.

Original library module build.gradle

    apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion Versions.compile_sdk

    defaultConfig {
        minSdkVersion Versions.min_sdk
        targetSdkVersion Versions.target_sdk
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    implementation project(Modules.models)
    implementation Libs.kotlin_std_lib
}
  

Resulting library module build.gradle

    apply from: "$rootProject.projectDir/android-library.gradle"

dependencies {
    implementation project(Modules.models)
    implementation Libs.kotlin_std_lib
}
  

Shared Gradle file

    apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion Versions.compile_sdk

    defaultConfig {
        minSdkVersion Versions.min_sdk
        targetSdkVersion Versions.target_sdk
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
}
  

If you do something 3+ times, extract out functionality

Whenever it’s possible and makes sense, use common configuration to reduce boilerplate.  This same rule applies if you are writing code, or writing Android Gradle configuration.  This post shares an “easy win” that you may be able to use to help better manage your multi-module project. There is so much more you can do to clean up your builds by leveraging buildSrc where you can write in Kotlin, Java, or Groovy, but that’s for another post.

Check out more Android content on my personal blog https://handstandsam.com


Sam Edwards, Lead Software Engineer, Mobile

Google Developer Expert (GDE) for Android & Kotlin, Lead Android Developer at Capital One, Instructor at Caster.io, Android Summit Conference co-organizer. Tech Blogger: https://handstandsam.com and I have over 500 handstands across the world: http://handstandsam.onamap.net

Related Content