Migrating to Kotlin DSL
This article assumes you understand a bit of Gradle Groovy build scripts
In a group project we are working on (at the time of my writing of this article) I, decided to pick up an enhancement issue on migrating to Kotlin DSL(Domain Specific Language). Initially, when you create a new Android application, the build script set up is Groovy. Here are some reasons why we should migrate to Kotlin DSL;
- Auto-Completion 😄
- Compile time errors instead of Run-time errors 🤯
- Navigation to source 😱
- Content assist 😏
- Function calls and variable assignments 😋
- I’ve used it and find it really amazing 😎
So how do we migrate? 🤔
Before we migrate we need to update the gradle version to 4.10 or higher and create a central file for all our dependencies as good practice and also to make it easy for management.
First create a buildSrc
Directory on the root folder of the project and add a build.gradle.kts
inside it and add the following code;
import org.gradle.kotlin.dsl.`kotlin-dsl`
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
kotlinDslPluginOptions {
experimentalWarning.set(false)
}
Also inside the buildSrc
create the following nested child directories src->main->kotlin
and inside it create a file and give it a name, say, Dependencies.kt
inside it add the following code;
object Versions {
//Version code and name for the application
const val name = "1.0"
const val code = 1
//Version codes for all the libraries
const val kotlin = "1.3.61"
const val buildToolsVersion = "3.5.3"
const val jetPack = "1.1.0"
const val constraintLayout = "1.1.3"
const val ktx = "1.1.0"
const val material = "1.0.0"
//Version codes for all the test libraries
const val junit4 = "4.12"
const val testRunner = "1.1.1"
const val espresso = "3.2.0"
const val annotation = "1.1.0"
}
object BuildPlugins {
//All the build plugins are added here
const val androidGradlePlugin = "com.android.tools.build:gradle:${Versions.buildToolsVersion}"
const val kotlinGradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}"
const val androidApplication = "com.android.application"
const val kotlinAndroid = "kotlin-android"
const val kotlinAndroidExtensions = "kotlin-android-extensions"
}
object Libraries {
//Any Library is added here
const val kotlinStandardLibrary = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}"
const val appCompat = "androidx.appcompat:appcompat:${Versions.jetPack}"
const val constraintLayout = "androidx.constraintlayout:constraintlayout:${Versions.constraintLayout}"
const val ktxCore = "androidx.core:core-ktx:${Versions.ktx}"
const val materialComponents = "com.google.android.material:material:${Versions.material}"
}
object AndroidSDK{
//minimum, compile and target SDK versions
const val min = 21
const val compile = 29
const val target = compile
}
object TestLibraries {
//any test library is added here
const val junit4 = "junit:junit:${Versions.junit4}"
const val testRunner = "androidx.test:runner:${Versions.testRunner}"
const val espresso = "androidx.test.espresso:espresso-core:${Versions.espresso}"
const val annotation = "androidx.annotation:annotation:${Versions.annotation}"
}
object BuildModules{
const val App = ":app"
}
You can add as many objects as possible according to your liking.
Kotlin uses (“”) as compared to the (‘’) that groovy allows.
Now lets rename build.gradle
(Project) to build.gradle.kts
and make the following code changes
The gradle command to clean the build directory which initially looks like this :
task clean(type: Delete) {
delete rootProject.buildDir
}
Would turn to:
tasks.register("clean").configure{
delete("build")
}
and
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.3'
}
since we had defined the variable in the Dependencies file, changes to:
dependencies {
classpath(BuildPlugins.androidGradlePlugin)
classpath(BuildPlugins.kotlinGradlePlugin)
}
now lets make the following changes to build.gradle (App)
. First refactor it to build.gradle.kts
Then;
The plugins as shown below
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
changes to;
plugins{
id(BuildPlugins.androidApplication)
id(BuildPlugins.kotlinAndroid)
id(BuildPlugins.kotlinAndroidExtensions)
}
Under android{}
make the following changes;
Initially;
compileSdkVersion 29
defaultConfig {
applicationId "com.app.example"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
changes to;
compileSdkVersion(AndroidSDK.compile)
buildToolsVersion("29.0.2")
defaultConfig {
applicationId = "com.app.example"
minSdkVersion(AndroidSDK.min)
targetSdkVersion(AndroidSDK.target)
versionCode = Versions.code
versionName = Versions.name
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
then
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
changes to
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
and under dependencies{}
before
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
changes to
implementation (fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(Libraries.kotlinStandardLibrary)
implementation(Libraries.appCompat)
implementation (Libraries.ktxCore)
implementation (Libraries.constraintLayout)
implementation (Libraries.materialComponents)
testImplementation (TestLibraries.junit4)
androidTestImplementation (TestLibraries.testRunner)
androidTestImplementation (TestLibraries.espresso)
androidTestImplementation (TestLibraries.annotation)
and finally you should change your settings.gradle
to settings.gradle.kts
and have the following changes
include ':app'
rootProject.name='example'
changes to
include(BuildModules.App)
rootProject.name = "example"
Now sync your project and you are done 😁
Click here to check out the sample app on github.