Android uses Kotlin to build Gradle

Keywords: Android Gradle Junit Google

Android Studio Gradle
3.4.2 5.1.1

First of all, kotlin-dsl is nothing new. Gradle 5.0 was released
Gradle Kotlin DSL The current version is 1.0.2

Is it possible to abandon groovy and embrace kotlin now? Migration is still a bit of a hassle!

Currently, when creating a project in Android Studio, Groovy is used by default to create Gradle scripts, so how to migrate to kotlin-dsl?

Grammar substitution

Generally, Groovy uses single or double quotation marks to express strings. But Kotlin must have double quotes.

Find and replace all single quotation marks (cmd + R) in Gradle script (take build.gralde in app directory for example) and change them all to double quotation marks.
Then one by one, turn to the grammar in kotlin-dsl

apply plugin: "com.android.application"

apply plugin: "kotlin-android"

apply plugin: "kotlin-android-extensions"

After the conversion: (no need to deal with a large number of errors first)

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

Before conversion:

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.1"
    defaultConfig {
        applicationId "com.crucio.test"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
        }
    }
}


Replace with

android {
    compileSdkVersion (29)
    buildToolsVersion ("29.0.1")
    defaultConfig {
        applicationId = "com.crucio.test"
        minSdkVersion (21)
        targetSdkVersion (29)
        versionCode = 1
        versionName = "1.0"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

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



dependencies {
    val kotlin_version = "1.3.41"
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
    implementation ("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version")
    implementation ("androidx.appcompat:appcompat:1.0.2")
    implementation ("androidx.core:core-ktx:1.0.2")
    implementation ("androidx.constraintlayout:constraintlayout:1.1.3")
    testImplementation ("junit:junit:4.12")
    androidTestImplementation ("androidx.test:runner:1.2.0")
    androidTestImplementation ("androidx.test.espresso:espresso-core:3.2.0")
}

At this point, we changed the name of the build.gradle file to build.gradle.kts
If there are no grammatical errors, the following figure will appear:

Tip: New script dependencies are available. Click Enable auto-reload at this time

At this time, it was found that the migration was successful. But can kotlin implement groovy ext-like dependencies? BuilSrc debuts~

buildSrc

Auto Completion + Click Jump, no need to switch back and forth between files manually~
Look at the official pair first. buildSrc introduce

  1. Create a new folder named buildSrc in the project root directory (the same level as the app folder in the project).

  2. Create a file named build.gradle.kts in the buildSrc folder

plugins{
    `kotlin-dsl`
}

repositories {
	 // Essential
    jcenter()
}
  1. Create the src/main/kotlin folder in the buildSrc folder, as shown below. Create kt file under this folder.

After we have written the dependency code, we go to build.gradle.kts file to replace it.

See? It's ready to be filled automatically.

BuilSrc plug-in

If it's a bit troublesome to abandon manual buildSrc, there are plug-ins.

Take an example buildSrcVersions The buildSrc directory is automatically generated, but the plug-in generates an empty settings.gradle.kts file, which can be considered for deletion.

supplement

About custom build types
In groovy, we customize the component type as follows

buildTypes {
  release {
    ...
  }
  debug {
    ...
  }
}

But in kotlin-dsl, buildTypes rely on NamedDomainObjectContainer

	/**
     * Encapsulates all build type configurations for this project.
     *
     * <p>For more information about the properties you can configure in this block, see {@link
     * BuildType}.
     */
    public void buildTypes(Action<? super NamedDomainObjectContainer<BuildType>> action) {
        checkWritability();
        action.execute(buildTypes);
    }

NamedDomainObjectContainer and the parent NamedDomainObjectCollection have several functions for accessing these string keys
By default, there will be release s and debug s. We can use getByName because the default is mapped in the build container.

	/**
     * Locates an object by name, failing if there is no such object. The given configure action is executed against
     * the object before it is returned from this method.
     *
     * @param name The object name
     * @param configureAction The action to use to configure the object.
     * @return The object with the given name, after the configure action has been applied to it. Never returns null.
     * @throws UnknownDomainObjectException when there is no such object in this collection.
     * @since 3.1
     */
    T getByName(String name, Action<? super T> configureAction) throws UnknownDomainObjectException;

If you want to customize the component type, getByName throws an exception. We can use maybe Create

/**
     * Looks for an item with the given name, creating and adding it to this container if it does not exist.
     *
     * @param name The name to find or assign to the created object
     * @return The found or created object. Never null.
     */
    T maybeCreate(String name);

Ending

Let's start by saying so much.

Attach build.gradle.kts to the root directory

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath(Libs.com_android_tools_build_gradle)
        classpath(Libs.kotlin_gradle_plugin)
    }
}

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

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


Posted by techjosh on Thu, 18 Jul 2019 23:16:43 -0700