An overview of the

As is known to all, we use Gradle to compile in Android Studio. Gradle is a building tool based on Groovy language. The syntax structure in Gradle that we often see in Build. Gradle is actually the DSL function provided by Groovy.

A DSL is a Domain Specific Language (DSL). It is a special ability that programming languages give developers to write code that appears to be detached from its original syntax structure, thus building a proprietary syntax structure.

There is no doubt that Kotlin supports DSL, and Gradle supports writing Gradle build scripts in Kotlin. Gradle website also provides guidance for migrating Kotlin in Groovy.

Let’s create a new project to transform Gradle files from 0 to one written by Kotlin.

Gradle script modification

For an Android project built on Gradle, the configuration file of Gradle usually consists of the following:

  • setting.gradle
  • app/build.gradle
  • project/build.gradle

So our transformation is nothing more than the transformation of these several documents.

Modified Settings. Gradle

The main function of this file is to be responsible for the declaration of modules in our project. Let’s take a look at its original code, as follows:

include ':app'
rootProject.name = "KotlinGradleDSL"
Copy the code

This code is very simple, which is to declare the main Module of app and define the name of our project. We can rewrite it by using the syntax of Kotlin. Before rewriting, we first change the name of the file to Settings.gradle.kts.

include("app")
rootProject.name = "KotlinGradleDSL"
rootProject.buildFileName = "build.gradle.kts"
Copy the code

Renovation project/build. Gradle

Again, we need to change the name of build.gradle to build.gradle.kts. Let’s take a look at the original code, as follows:

buildscript {
    ext.kotlin_version = "1.4.31"

    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath "Com. Android. Tools. Build: gradle: 4.1.2." "
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
Copy the code

The modified code is as follows:

buildscript {

    val gradle_version = 4.1.3 ""
    val kotlin_version = "1.4.31"

    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath("com.android.tools.build:gradle:$gradle_version")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

tasks {
    val clean by registering(Delete::class) {
        delete(buildDir)
    }
}
Copy the code

In Groovy, we have an extension to Ext, which we don’t have in Kotlin, so we have to declare a local variable ourselves, which we import through string templates, and global dependencies introduced by classpath, which we enclose in curly braces. There is also a clean task, which also needs rewriting.

Next, let’s rewrite the app/build.gradle with the most content.

Modified app/build. Gradle

App /build.gradle contains a lot of content. Let’s look at how each module should be modified.

Plug-in introduction modification

The plugin for Groovy syntax is introduced as follows:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}
Copy the code

Using Kotlin, it can be modified as follows:

plugins {
    id("com.android.application")
    kotlin("android")
    kotlin("android.extensions")}Copy the code

The introduction of the SDK

The SDK for Groovy syntax is introduced as follows:

compileSdkVersion 30
buildToolsVersion "30.0.3"
Copy the code

Using Kotlin, it can be modified as follows:

compileSdkVersion(30)
buildToolsVersion("30.0.3")
Copy the code

Default configuration modification

The default configuration of Groovy syntax looks like this:

defaultConfig {
    applicationId "com.example.kotlingradledsl"
    minSdkVersion 23
    targetSdkVersion 30
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Copy the code

Using Kotlin, it can be modified as follows:

defaultConfig {
    applicationId = "com.example.kotlingradledsl"
    minSdkVersion(23)
    targetSdkVersion(30)
    versionCode = 1
    versionName = "1.0"

    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Copy the code

Compile type modification

The compilation type of Groovy syntax looks like this:

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile ('proguard-android-optimize.txt'), 'proguard-rules.pro'}}Copy the code

Using Kotlin, it can be modified as follows:

buildTypes {
    getByName("release") {
        isMinifyEnabled = false
        proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")}}Copy the code

Specify JDK modifications

The specified JDK for Groovy syntax looks like this:

compileOptions {
    sourceCompatibility JavaVersion . VERSION_1_8
    targetCompatibility JavaVersion . VERSION_1_8
}
kotlinOptions {
    jvmTarget = '1.8'
}
Copy the code

Using Kotlin, it can be modified as follows:

compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
    jvmTarget = "1.8"
}
Copy the code

Dependent modification

The dependencies of Groovy syntax are as follows:

dependencies {
    implementation "Org. Jetbrains. Kotlin: kotlin - stdlib: 1.4.31"
    implementation 'androidx. Core: the core - KTX: 1.2.0'
    implementation 'androidx. Appcompat: appcompat: 1.1.0'
    implementation 'com. Google. Android. Material: material: 1.1.0'
    implementation 'androidx. Constraintlayout: constraintlayout: 1.1.3'
}
Copy the code

Using Kotlin, it can be modified as follows:

dependencies {
    implementation("Org. Jetbrains. Kotlin: kotlin - stdlib: 1.4.31")
    implementation("Androidx. Core: the core - KTX: 1.2.0")
    implementation("Androidx. Appcompat: appcompat: 1.1.0." ")
    implementation("Com. Google. Android. Material: material: 1.1.0." ")
    implementation("Androidx. Constraintlayout: constraintlayout: 1.1.3.")}Copy the code

Complete code display

So far, we have changed all the contents of the automatically generated app/build.gradle. Let’s take a look at the complete code, as shown below:

plugins {
    id("com.android.application")
    kotlin("android")
    kotlin("android.extensions")
}

android {
    compileSdkVersion(30)
    buildToolsVersion("30.0.3")

    defaultConfig {
        applicationId = "com.example.kotlingradledsl"
        minSdkVersion(23)
        targetSdkVersion(30)
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {

    implementation("Org. Jetbrains. Kotlin: kotlin - stdlib: 1.4.31")
    implementation("Androidx. Core: the core - KTX: 1.2.0")
    implementation("Androidx. Appcompat: appcompat: 1.1.0." ")
    implementation("Com. Google. Android. Material: material: 1.1.0." ")
    implementation("Androidx. Constraintlayout: constraintlayout: 1.1.3.")}Copy the code

Add more advanced features to app/build.gradle

The content in the above app/build.gradle is the most basic, we still need to add some more advanced features, such as automatic packaging, output APK name modification, etc. On the basis of the above app/build.gradle, let’s start to improve.

Automatic packaging

To implement automatic packaging, we need to create a new signature file. After we have the signature file, we need to configure it in app/build.gradle.

// Configure the signature
signingConfigs {
    release {
        / / alias
        keyAlias 'zjgsu'
        // Alias password
        keyPassword '123456'
        / / path
        storeFile file('.. /app/src/main/jks/kotlindsl.jks')
        / / password
        storePassword '123456'}}Copy the code

Then in the compile type, the release type can be referenced, as shown below:

signingConfig signingConfigs.release
Copy the code

Using Kotlin, it can be modified as follows:

// The signature type
signingConfigs {
    register("release") {
        / / alias
        keyAlias = "zjgsu"
        // Alias password
        keyPassword = "123456"
        / / path
        storeFile = file("src/main/jks/kotlindsl.jks")
        // Sign the file password
        storePassword = "123456"}}Copy the code

Then in the compile type, the release type can be referenced, as shown below:

signingConfig = signingConfigs.getByName("release")  
Copy the code

After configuring the signature, you can package the APK directly using the command or using the tools provided by Android Studio, as shown below:

Double click assemble to assemble apK. The resulting APK looks like this:

Output Type Configuration

App-debug and app-release are the apK we need, but the name is definitely not what we need, so we need to configure the output type in app/build.gradle, otherwise we have to manually change the name every time we package apK, which is too troublesome. Let’s first take a look at how Groovy syntax is configured, as follows:

// Output type configuration
android.applicationVariants.all { variant ->
    def buildType = variant.buildType.name
    def fileName
    variant.outputs.each {
        if (buildType == "release") {
            fileName = "APP_NAMEV-${defaultConfig.versionName}.apk"
        } else if (buildType == "debug") {
            fileName = "APP_NAMEV-${defaultConfig.versionName}_${buildType}.apk"
        }
        it.outputFileName = fileName
    }
}
Copy the code

Using Kotlin, it can be modified as follows:

 // Output type
android.applicationVariants.all {
    // Compile type
    val buildType = this.buildType.name
    outputs.all {
        // Check whether the output type is APK
        if (this is com.android.build.gradle.internal.api.ApkVariantOutputImpl) {
            this.outputFileName = "KOTLIN_DSL_V${defaultConfig.versionName}_$buildType.apk"}}}Copy the code

Assemble to assemble apK. The resulting APK looks like this:

Use buildSrc to centrally manage Gradle dependency versions

In Groovy, we often extract build_config.gradle as a global variable control. In Kotlin, we need to use buildSrc to manage gradle dependency versions. Interested can see the introduction of the official website.

To see how this works, we first need to create a buildSrc folder in the root directory, and then create a series of directories, as shown below:

Once the directory is created, you need to write settings.gradle.kts, as follows:

rootProject.buildFileName = "build.gradle.kts"
Copy the code

After writing settings.gradle. KTS, write build.gradle. KTS as follows:

apply {
    plugin("kotlin")
}
buildscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath(kotlin("gradle-plugin"."1.4.31"))
    }
}
dependencies {
    implementation(gradleKotlinDsl())
    implementation(kotlin("stdlib"."1.4.31"))
}
repositories {
    gradlePluginPortal()
}
Copy the code

After compiling, we can write the kotlinConstants.kt public class as follows:

// Global constants
object KotlinConstants {

    / / Gradle version
    const val gradle_version = 4.1.3 ""

    / / Kotlin version
    const val kotlin_version = "1.4.31"
}

// Apply the configuration
object AppConfig {

    // Dependent version
    const val compileSdkVersion = 30

    // Compile the tool version
    const val buildToolsVersion = "30.0.3"

    / / package name
    const val applicationId = "com.example.kotlingradledsl"

    // Minimum support for SDK
    const val minSdkVersion = 23

    // Currently based on the SDK
    const val targetSdkVersion = 30

    // Version encoding
    const val versionCode = 1

    // Version name
    const val versionName = "1.0"
}

// Dependency configuration
object DependenciesConfig {

    / / Kotlin based library
    const val STD_LIB = "org.jetbrains.kotlin:kotlin-stdlib:${KotlinConstants.kotlin_version}"
}
Copy the code

With the kotlinconstants.kt we can use it in.gradle files like app/build.gradle.kts code as follows:

// Reference the plug-in
plugins {
    id("com.android.application")
    kotlin("android")
    kotlin("android.extensions")}/ / Android attributes
android {
    compileSdkVersion(AppConfig.compileSdkVersion)
    buildToolsVersion(AppConfig.buildToolsVersion)

    defaultConfig {
        applicationId = AppConfig.applicationId
        minSdkVersion(AppConfig.minSdkVersion)
        targetSdkVersion(AppConfig.targetSdkVersion)
        versionCode = AppConfig.versionCode
        versionName = AppConfig.versionName

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    // The signature type
    signingConfigs {
        register("release") {
            / / alias
            keyAlias = "zjgsu"
            // Alias password
            keyPassword = "123456"
            / / path
            storeFile = file("src/main/jks/kotlindsl.jks")
            // Sign the file password
            storePassword = "123456"}}// Compile type
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
            // Automatic signature package
            signingConfig = signingConfigs.getByName("release")
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro")}}// Output type
    android.applicationVariants.all {
        // Compile type
        val buildType = this.buildType.name
        outputs.all {
            // Check whether the output type is APK
            if (this is com.android.build.gradle.internal.api.ApkVariantOutputImpl) {
                this.outputFileName = "KOTLIN_DSL_V${defaultConfig.versionName}_$buildType.apk"}}}/ / specify JDK
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {

    implementation(DependenciesConfig.STD_LIB)
    implementation("Androidx. Core: the core - KTX: 1.2.0")
    implementation("Androidx. Appcompat: appcompat: 1.2.0")
    implementation("Com. Google. Android. Material: material: 1.3.0")
    implementation("Androidx. Constraintlayout: constraintlayout: 2.0.4.")}Copy the code

At this point, we are done with Gradle Kotlin DSL.

The source code

The source code has been uploaded to Github, as needed.