Android Gradle 的配置从 Groovy 迁移到 KTS

目录

#1. 引用

#2.常用术语

#3.脚本文件命名

#4.Gradle迁移示例

1.准备工作:对 Groovy 做简单转换

2. plugins 代码块迁移

3. 显式和隐式 buildTypes

4.默认配置:defaultConfig

5.签名配置:signingConfigs

6.打包配置:applicationVariants

7.编译选项:compileOptions

8.依赖配置:dependencies

9.参数配置:ext

10.迁移 project/build.gradle

11.迁移 setting.gradle

#5.更多资源


#1. 引用

Android Gradle 插件 4.0 支持在 Gradle 构建配置中使用 Kotlin 脚本 (KTS),用于替代 Groovy(过去在 Gradle 配置文件中使用的编程语言)。

将来,KTS 会比 Groovy 更适合用于编写 Gradle 脚本,因为采用 Kotlin 编写的代码可读性更高,并且 Kotlin 提供了更好的编译时检查和 IDE 支持。

虽然与 Groovy 相比,KTS 当前能更好地在 Android Studio 的代码编辑器中集成,但采用 KTS 的构建速度往往比采用 Groovy 慢,因此在迁移到 KTS 时应考虑构建性能。

本页介绍了有关将 Android 应用的 Gradle build 文件从 Groovy 转换为 KTS 的基本信息。

如需查看更全面的迁移指南,请参阅 Gradle 的官方文档

⚠️  采用 KTS 的构建速度往往比采用 Groovy 慢,因此在迁移到 KTS 时应考虑构建性能。

#2.常用术语

KTS:是指 Kotlin 脚本,这是 Gradle 在构建配置文件中使用的一种 Kotlin 语言形式。Kotlin 脚本是可从命令行运行的 Kotlin 代码。

Kotlin DSL:主要是指 Android Gradle 插件 Kotlin DSL,有时也指底层 Gradle Kotlin DSL。

在讨论从 Groovy 迁移时,术语“KTS”和“Kotlin DSL”可以互换使用。换句话说,“将 Android 项目从 Groovy 转换为 KTS”与“将 Android 项目从 Groovy 转换为 Kotlin DSL”实际上是一个意思。 

#3.脚本文件命名

  • 用 Groovy 编写的 Gradle build 文件使用 .gradle 文件扩展名。
  • 用 Kotlin 编写的 Gradle build 文件使用 .gradle.kts 文件扩展名。

#4.Gradle迁移示例

⚠️ 在迁移之前,我们要一次迁移一个文件:

由于可以在项目中结合使用 Groovy build 文件和 KTS build 文件,因此将项目转换为 KTS 的一个简单方法是先选择一个简单的 build 文件(例如 settings.gradle),将其重命名为 settings.gradle.kts,然后将其内容转换为 KTS。之后,确保您的项目在迁移每个 build 文件之后仍然可以编译。

1.准备工作:对 Groovy 做简单转换

一些简单的 Kotlin 和 Groovy 语言差异会使转换脚本变得乏味:

  • 字符串:Groovy 可以用单引号'string'或双引号引用"string",而 KTS 需要双引号"string"。

  • 括号:Groovy 允许在调用函数时省略括号,而 KTS 需要括号。

  • 赋值运算符:Groovy 允许在分配属性时省略赋值运算符(=),而 Kotlin 需要赋值运算符(=)。

作为迁移的第一步,建议通过以下方式准备您的 Groovy 构建脚本

  • 使用双引号统一引号,

  • 分别使用括号和赋值运算符。

示例1.使用双引号统一引号

Groovy - app/gradle:
android {
    compileSdkVersion 30
    buildToolsVersion '30.0.2'
    ...
}
 
dependencies {
    implementation 'com.acme:example:1.0'
}

变成 KTS - app/gradle:

android {
    compileSdkVersion 30
    buildToolsVersion = "30.0.2"
    ...
}
 
dependencies {
    implementation "com.acme:example:1.0"
}

继续示例1中的更改

示例2.分别使用括号和赋值运算符

android {
    compileSdkVersion(30)
    buildToolsVersion = "30.0.2"
    ...
}
 
dependencies {
    implementation("com.acme:example:1.0")
}

⚠️ 后者涉及更多,因为在 Groovy 脚本中区分函数调用和属性分配可能并非易事,我们一开始并不能明确哪些地方该使用括号还是赋值运算符。一个好的策略是首先对所有不明确的语句进行属性分配,然后通过将失败的语句转换为函数调用来修复构建。
接下来,我们一起来看看具体的替换:

2. plugins 代码块迁移

Groovy 中的以下代码:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'dagger.hilt.android.plugin'
// or
plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'dagger.hilt.android.plugin'
}
 
apply from: '../signing.gradle'

在 KTS 中变为以下代码:

plugins {
    id("com.android.application")
    id("kotlin-android")
    id("dagger.hilt.android.plugin")
 }
 
 
apply(from = "../signing.gradle")

这里 id("kotlin-android") 也能写成 kotlin("android")

⚠️ plugins 代码块仅解析 Gradle 插件门户中提供的插件或使用 pluginManagement 代码块指定的自定义存储库中提供的插件。如果插件来自插件门户中不存在的 buildScript 依赖项,那么这些插件在 Kotlin 中就必须使用 apply 才能应用。例如:

apply(plugin = "kotlin-android")

3. 显式和隐式 buildTypes

⚠️ 在 Kotlin DSL 中,某些 buildTypes(如 debug 和 release,)是隐式提供的。但是,其他 buildTypes 则必须手动创建。

Groovy - buildTypes

// 例如,在 Groovy 中,您可能有 debug、release 和 staging 
 
buildTypes
  debug {
    ...
  }
  release {
    ...
  }
  staging {
    ...
  }

在 KTS 中,仅 debug 和 release, buildTypes 是隐式提供的,而 staging 则必须由您手动create(创建)出来:

KTS - buildTypes:

buildTypes
  getByName("debug") {
    ...
  }
  getByName("release") {
    ...
  }
  create("staging") {
    ...
  }

补充:buildTypes-debug的改变

Groovy - buildTypes-debug:

buildTypes {
        debug {
            minifyEnabled false
            testCoverageEnabled project.hasProperty("coverage")
            debuggable true
            applicationIdSuffix ".dev"
            versionNameSuffix "-DEV"
            signingConfig signingConfigs.debug
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        release {
        }
    }

KTS - buildTypes-debug 对应的更改:

buildTypes {
        getByName("debug") {
            isMinifyEnabled = false
            isTestCoverageEnabled = project.hasProperty("coverage")
            isDebuggable = true
            applicationIdSuffix = ".dev"
            versionNameSuffix = "-DEV"
            signingConfig = signingConfigs.getByName("debug")
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
 
        getByName("release") {
            ...
        }
    }

4.默认配置:defaultConfig

Groovy - defaultConfig:

defaultConfig {
    applicationId "com.android.testplaydemo"
    minSdkVersion 21
    targetSdkVersion 30
    versionCode 1
    versionName "1.0"
 
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

KTS - defaultConfig: 

defaultConfig {
    applicationId = "com.android.testplaydemo"
    minSdkVersion(21)
    targetSdkVersion(30)
    versionCode = 1
    versionName = "1.0"
 
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

5.签名配置:signingConfigs

Groovy - signingConfigs

    signingConfigs {
        release {
            keyAlias 'test'
            keyPassword '123456'
            storeFile file('../test.jks')
            storePassword '123456'
            v1SigningEnabled true
            v2SigningEnabled true
        }
        debug {
            keyAlias 'test'
            keyPassword '123456'
            storeFile file('../test.jks')
            storePassword '123456'
        }
    }

KTS - signingConfigs

    signingConfigs {
        create("release") {
            keyAlias = "test"
            keyPassword = "123456"
            storeFile = File("../test.jks")
            storePassword = "123456"
            isV1SigningEnabled = true
            isV2SigningEnabled = true
        }
        getByName("debug") {
            keyAlias = "test"
            keyPassword = "123456"
            storeFile = File("../test.jks")
            storePassword = "123456"
        }
    }

6.打包配置:applicationVariants

 Groovy 示例:

// 自定义多渠道打包 apk名称
applicationVariants.all { variant ->
    def buildType = variant.buildType.name
    variant.outputs.all { output ->// each 改为 all
        def date = new Date().format("ddHHmm", TimeZone.getTimeZone("GMT+08"))
        def fileName = "MVVM_${productFlavors[0].name}_${versionName}_${versionCode}_${date}.apk"
        def outFile = output.outputFile
        if (outFile != null && buildType == "release") {
            outputFileName = fileName // output.outputFile 改为 outputFileName
        }
    }
}
 
// 多渠道配置
flavorDimensions "code"
productFlavors {
    google {
    }
    baidu {
    }
    other {
    }
}
productFlavors.all {
        flavor -> flavor.manifestPlaceholders = [CHANNEL_VALUE: name]
}

 KTS 示例:

// 自定义多渠道打包 apk名称
applicationVariants.all {
    val buildType = buildType.name
    outputs.all {
        if (this is com.android.build.gradle.internal.api.ApkVariantOutputImpl) {
            if (buildType == "release") {
                outputFileName = "DEMO_v${versionCode}_${flavorName}_${Versions.dateFormat}.apk"
            }
        }
    }
}
 
// 多渠道配置
flavorDimensions("code")
productFlavors {
    create("google")
    create("baidu")
    create("other")
}
productFlavors.all {
    manifestPlaceholders["CHANNEL_VALUE"] = name
}

7.编译选项:compileOptions

Groovy - compileOptions 

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

KTS - compileOptions  

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

8.依赖配置:dependencies

Groovy - dependencies

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.6.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

KTS - dependencies

dependencies {
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
    implementation("org.jetbrains.kotlin:kotlin-stdlib:${Libs.kotlin_version}")
    implementation("androidx.core:core-ktx:1.6.0")
    implementation("androidx.appcompat:appcompat:1.3.1")
    implementation("com.google.android.material:material:1.4.0")
    implementation("androidx.constraintlayout:constraintlayout:2.1.0")
    testImplementation("junit:junit:4.12")
    androidTestImplementation("androidx.test.ext:junit:1.1.3")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
}

⚠️  需要注意:implementation fileTree(dir: "libs", include: ["*.jar"]) 这行的改动!
在kts中写法为:implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) 。

9.参数配置:ext

关于参数的配置的更改(比如:应用版本号,兼容最低Android sdk版本号,依赖版本号,签名)如下示例:(Groovy

// 一般放入 build.gradle 中
ext {
        minAndroidSdk = 21
        targetSdk = 29
        verCode = automatedVerCode
        verName = "1.0.0-${project.findProperty('buildNumber') ?: 0}"
 
        // 依赖包版本号 配置
        kotlin_version = "1.4.10"
        other_version = "2.2.0"
    }
 
// 一般会创建一个 signing.gradle 来存放签名配置参数
ext {
    StoreFile = "test.keystore"
    StorePassword = "202121"
    KeyAlias = "test"
    KeyPassword = "202121"
}

我们需要删除原来的 ext 参数配置,并在根目录上右键新建 buildSrc 目录。目录结构与文件如下所示:

创建参数的示例:(KTS

// 应用版本号/兼容sdk版本号 配置
object Versions {
    const val applicationId = "com.android.mvvm"
 
    const val minAndroidSdk = 21
    const val targetSdk = 30
    const val verCode = 100     // XYZ
    const val verName = "1.0.0" // X.Y.Z; X = Major, Y = minor, Z = Patch level
}
 
// 依赖包版本号 配置
object Libs {
    const val KOTLIN_VERSION = "1.4.10"
    const val OTHER_VERSION = "2.2.0"
}
 
// 签名 配置
object Signing {
    const val StoreFile = "test.keystore"
    const val StorePassword = "123456"
    const val KeyAlias = "test"
    const val KeyPassword = "123456"
}

 补充:其中需要看下 buildSrc 目录中的 build.gradle.kts 配置:

// build.gradle.kts
plugins {
    `kotlin-dsl`
}
 
repositories {
    gradlePluginPortal()
}

以上为 app/build.gradle.kts 的迁移。

需要更多更详细,请查看已迁移文件:app/build.gradle.kts

10.迁移 project/build.gradle

第一步:需要删除原来的 ext 参数配置;第二步:根据依赖配置做相应的更改:

示例(Groovy

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext {
        kotlin_version = "1.4.32"
        other_version = "2.2.0"
    }
 
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.1.2"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
 
allprojects {
    repositories {
        google()
        jcenter()
    }
}
 
task clean(type: Delete) {
    delete rootProject.buildDir
}

示例(KTS

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:4.0.1")
        classpath(kotlin("gradle-plugin", version = Libs.KOTLIN_VERSION))
        classpath("com.google.dagger:hilt-android-gradle-plugin:${Libs.HILT_VERSION}")
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle.kts files
    }
}
 
allprojects {
    repositories {
        google()
        jcenter()
    }
}
 
tasks.register("clean", Delete::class) {
    delete(rootProject.buildDir)
}

⚠️  这里需要注意创建任务的写法:

// Groovy
task clean(type: Delete) {
    delete rootProject.buildDir
}
 
// KTS
tasks.register("clean", Delete::class) {
    delete(rootProject.buildDir)
}

11.迁移 setting.gradle

最后就很简单,示例(Groovy

include ':app'
rootProject.name = "TestDemo"

 示例(KTS

include(
    ":app"
)
rootProject.name = "TestDemo"

#5.更多资源

如需查看用 KTS 编写的 Gradle build 文件的可运行示例,

请参阅 GitHub上提供的 MVVM 示例应用 - Groovy-To-KTS分支

也可以参阅 GitHub 上的官方提供的 IOSched 示例应用

猜你喜欢

转载自blog.csdn.net/xiaowang_lj/article/details/131251544