Migrating to Kotlin DSL

Evans Chepsiror
4 min readFeb 18, 2020

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;

  1. Auto-Completion 😄
  2. Compile time errors instead of Run-time errors 🤯
  3. Navigation to source 😱
  4. Content assist 😏
  5. Function calls and variable assignments 😋
  6. 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.

--

--

Evans Chepsiror
Evans Chepsiror

Written by Evans Chepsiror

Android app developer and Kotlin enthusiast

No responses yet