Customize your Android Gradle with Kotlin -Part 1
Hi, this is my very fist English article, most time in my life, I speak in Chinese. And all my other Medium posts is written in Chinese. So maybe this article have many grammar errors, I apologize for that. If you see anything that is not very clear to you and you’d like to correct my poor English, please connect me anytime.
OK, Let’s begin!
Something you need to know…
- Kotlin advanced language features like: receiver type, extension function
- Basic understanding for build.gradle and Android gradle plugin.
Kotlin + BuildSrc make your life easier
First thing I’d like to talk about is buildSrc
, it’s a top-level folder in your project. When you start to run your Gradle tasks, everything inside the buildSrc
will automatically compile and you can use it in all of your gradle files. But we don’t need to compile it manually, Android Studio will do this job for you. There are already many articles talk about how to use buildSrc
for dependency management, so this article won’t cover that, heres’ some reference:
- https://proandroiddev.com/gradle-dependency-management-with-kotlin-94eed4df9a28
- https://handstandsam.com/2018/02/11/kotlin-buildsrc-for-better-gradle-dependency-management/
So what else buildSrc
can do? More than dependency management? Imagine you have a custom gradle task, and your project is a multi-module project, you will need to write it in every module. Also, if you are not familiar with Groovy, you can’t write your own DSL easily for your daily job. So, in the following session, I will provide a step-to-step guide for how to write custom gradle android extensions and custom tasks.
Before we start, please make sure you’ve already setup and compiles buildSrc
successfully.
Gradle Android extensions
Step1. Import Android gradle plugin
This step might seem weird to you. I am already using Android gradle plugin in project-level build.gradle
, why do I need to import it? That because for all gradle files in buildSrc
. the priority is higher than project-level build.gradle
. So, in order to write custom Android gradle extension inside buildSrc
, we need to add dependencies like this:
Step 2. Write your first extension
One thing that is not very convenient for our daily development is buildConfigField()
, you can use this function to add constants in your BuildConfig.java
file. But this function is error prone, you will need to write the TYPEs in STRING, sometimes you might misspell or pair STRING with FALSE accidentally:
buildConfigField("String", "ADS_ENABLE", "true")
The way to improve API this is very simple, just let the function check types for me. In other words, let’s use function overloading
fun buildConfigField(key: String, value: Boolean)
fun buildConfigField(key: String, value: String)
fun buildConfigField(key: String, value: Int)
But you can not call the implementation of buildConfigField
directly. It is a public function in BaseFlavor.java
. You can navigate directly in build.gradle
:
That brings up another question, then how can I call this function in build.gradle
? where is BaseFlavor comes from? Shouldn’t it write like this?
baseFlavor.buildConfigField(...)
That’s because we are writing code in the defaultConfig block, with the help of receiver type, the scope we are using is defaultConfig. Furthermore, DefaultConfig is extended from BaseFlavor.
Now we all know how this DSL works, its much easier to write extension right now, we just write a extension function for BaseFlavor, let’s create a file AndroidBuildExt.kt in buildSrc/src/main/java
:
Step 3. Call extension function from module’s gradle file
This is easiest part, you don’t need to do anything! This function is already compiled by Android Studio, you can call it in any module.
What else ?
If you knows how to write Kotlin DSL very well, you can do much more than that. For example, if you are tired of typing module’s name, maybe you can create a custom DSL like this:
Next I will show how to write custom task in Kotlin, the example will be jacoco coverage report for Multi-Module project. Before I use Kotlin, it’s hard to imagine that I can use Groovy to write a gradle task like this.
Thanks for your reading! any feedback is welcome!
Twitter: @YanbinHung
Facebook: https://www.facebook.com/hung.yanbin