记录迁移gradle到kts

记录迁移gradle到kts

前言

最近练手了《Android依赖管理实践与总结》,里面关于Version Catalogs的部分鸽了,因为我练手的项目没有升到gradle7.x,最近花了点时间搞了下,这里记录下吧,也踩了一些坑,希望能够对读者有帮助。

知识了解

这里还是推荐修改之前,先看下Android官方的文档吧:

将 build 配置从 Groovy 迁移到 KTS

我这也参考了几篇文章,也贴一下,他们写的会更全一些(虽然并不能完全解惑),我这就是希望做个记录:

Android gradle迁移至kts

Android gradle 插件升级和 kts 迁移踩坑指南

小伙快把你的Gradle从Groovy迁移到KTS

有一定了解之后,我们就开始下手改了!

迁移gradle到kts

升级gradle版本

看下官方文档的说明,要使用KTS,AGP要升级到4.0,也就是说gradle版本要对应升级到6.1.1:

Android Gradle 插件 4.0 支持在 Gradle build 配置中使用 KTS。

我这用的版本是: Gradle Version 7.5.1,AGP 7.4.2。还有个问题就是,要注意下Android Studio,gradle以及AGP之间的关系。

修改文件名

这里需要把安卓项目中的.gradle文件,全部改成.gradle.kts,一般来说,主要就下面三个吧:

  • setting.gradle
  • 项目的build.gradle
  • module的build.gradle

如果还使用了ext来做依赖管理,可能麻烦一些,需要另外处理一下

变量修改

因为从groovy语言换到了kotlin,语法有点变化,需要修改下,主要是下面几个内容:

  • 字符串
  • 括号
  • 等于号
  • Boolean变量

下面一个一个说,官方文档也有,但是肯定要比官方文档简单些吧。

替换字符串

这里就是拿别人的正则替换去修改:

bash 复制代码
正则表达式
'(.*?[^\])'
作用范围为
"$1"

在AS中ctrl + shift + r开启全局替换,指定file mask为"*.gradle",大致瞄一眼查找结果,给它全部替换了就行。

增加括号

对括号的增加也可以用正则替换,和上面类似:

scss 复制代码
正则表达式
(\w+) (([^={\s]+)(.*))
作用范围为
$1($2)

增加等于号

上面两步改完之后,还是有一些问题的,我这改的比较多的就是括号问题,比如:

scss 复制代码
android {
    compileSdk(BuildVersion.compileSdkVersion)
    ...
}
// 应该是下面这样
compileSdk  = BuildVersion.compileSdkVersion

剩下的minSdk、targetSdk等也是一样要加等于号,再一个就是仓库的也要加等于号,比如引入阿里云的仓库:

ini 复制代码
maven{ url = uri("https://maven.aliyun.com/repository/google/") }
maven{ url = uri("https://maven.aliyun.com/repository/public/") }

我看其他项目可以去掉等于号的,直接url带括号,不知道是不是有设置插件。

修改Boolean变量

这里修改Boolean变量,实际就是对minifyEnabled修改,因为都会遇到这个:

arduino 复制代码
minifyEnabled false
// 改为:
isMinifyEnabled = false

修改仓库配置

gradle7.x后把依赖管理放到了setting.gradle里面,这里要处理下,把原先项目build.gradle仓库放到这,比如:

scss 复制代码
// 插件管理
pluginManagement {
    repositories {
        // 是用于从 Gradle 插件门户下载插件的默认仓库。
        gradlePluginPortal()
        maven{ url = uri("https://maven.aliyun.com/repository/google/") }
        maven{ url = uri("https://maven.aliyun.com/repository/public/") }
        mavenCentral()
        maven { setUrl("https://jitpack.io") }
    }
}

dependencyResolutionManagement {
    // 存储库模式: 在项目的子 module 中配置仓库信息会导致编译失败。
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven{ url = uri("https://maven.aliyun.com/repository/google/") }
        maven{ url = uri("https://maven.aliyun.com/repository/public/") }
        google()
        mavenCentral()
        maven { setUrl("https://jitpack.io") }
    }
}

// 指定根目录,不加这个好像也没报错
rootProject.name = "fundark"
include(":app")

这时候就可以把项目的build.gradle.kts改成下面这样了:

scss 复制代码
buildscript {
    // 不知道为什么我这不加这个repositories会报错。。。
    repositories {
        maven{ url = uri("https://maven.aliyun.com/repository/google/") }
        maven{ url = uri("https://maven.aliyun.com/repository/public/") }
        mavenCentral()
        maven { setUrl("https://jitpack.io") }
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.4.2")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0")
    }
}

// 这个task也需要修改,groovy语法不对了
task<Delete>("clean") {
    delete(rootProject.buildDir)
}

按理来说build.gradle.kts的buildscript里面放dependencies就行了,可是我这会报错,还得把repositories加上。

这个task也是一个修改点,这里提前说一下。

问题处理

修改的地方大致就上面这些,后面就是处理升级带来的坑了。

task语法问题

第一个就是上面提到的task语法问题了,我这sync时会报错,修改如下:

scss 复制代码
task clean(type: Delete) {
    delete rootProject.buildDir
}
// 改为
task<Delete>("clean") {
    delete(rootProject.buildDir)
}

compileSdk等问题

这里有个很神奇的问题,估计是升级gradle版本的原因,我这之前都用的compileSdkVersion,给它赋值Int型,现在提示它只接受字符串了,后面看了下,这些都得改了:

ini 复制代码
android {
    compileSdkVersion BuildVersion.compileSdkVersion
    defaultConfig {
        applicationId "com.silencefly96.fundark"
        minSdkVersion BuildVersion.minSdkVersion
        targetSdkVersion BuildVersion.targetSdkVersion
        versionCode BuildVersion.versionCode
        versionName BuildVersion.versionName
        ...
    }
}
// 改为
android {
    compileSdk  = BuildVersion.compileSdkVersion
    defaultConfig {
        applicationId = ("com.silencefly96.fundark")
        minSdk  = (BuildVersion.minSdkVersion)
        targetSdk  = (BuildVersion.targetSdkVersion)
        versionCode = (BuildVersion.versionCode)
        versionName = (BuildVersion.versionName)
        ...
    }
}

依赖冲突

可能时升级了gradle版本,我这本来没问题的代码提示了一些依赖冲突,后面升级了几个依赖版本:

第一个是lifecycle_viewmodel_ktx:,从"2.2.0" 升级到了 "2.4.0"。

第二个是升级了kotlin-gradle-plugin,从1.5.20升级到了1.6.0,下面两个classpath会冲突:

scss 复制代码
classpath("com.android.tools.build:gradle:7.4.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0")

还看了一篇stackOverflow文章,有详细写为什么,有需要可以看下。

整体梳理

迁移过程可能会有很多问题,最好还是拿一个项目的来参考,我下面也贴一下我迁移后的三个文件吧: setting.gradle 、项目的build.gradle 、module的build.gradle,读者可以参考下:

setting.gradle

迁移前:

php 复制代码
include ':app'

迁移后:

scss 复制代码
pluginManagement {
    repositories {
        gradlePluginPortal()
        // 依赖本地仓库
        maven{ url = uri("./privacy_repo") }
        maven{ url = uri("https://maven.aliyun.com/repository/google/") }
        maven{ url = uri("https://maven.aliyun.com/repository/public/") }
        mavenCentral()
        maven { setUrl("https://jitpack.io") }
    }

}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven{ url = uri("https://maven.aliyun.com/repository/google/") }
        maven{ url = uri("https://maven.aliyun.com/repository/public/") }
        google()
        mavenCentral()
        maven { setUrl("https://jitpack.io") }
    }
}

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

项目的build.gradle

迁移前:

rust 复制代码
buildscript {
    // ext不能使用了
    ext.kotlin_version = "1.4.21"
    repositories {
        maven{ url'https://maven.aliyun.com/repository/google/' }
        maven{ url'https://maven.aliyun.com/repository/public/' }
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.4.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
    }
}

allprojects {
    repositories {
        maven{ url'https://maven.aliyun.com/repository/google/' }
        maven{ url'https://maven.aliyun.com/repository/public/' }//central仓和jcenter仓的聚合仓
        google()
        mavenCentral()
    }
}

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

迁移后:

scss 复制代码
buildscript {
    // 按理来说应该不用写了
    repositories {
        maven{ url = uri("https://maven.aliyun.com/repository/google/") }
        maven{ url = uri("https://maven.aliyun.com/repository/public/") }
        mavenCentral()
        maven { setUrl("https://jitpack.io") }
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.4.2")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20")
    }
}

task<Delete>("clean",{
    delete(rootProject.buildDir)
})

module的build.gradle

迁移前:

bash 复制代码
plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'kotlin-parcelize'
}

android {
    compileSdkVersion BuildVersion.compileSdkVersion
    defaultConfig {
        applicationId "com.silencefly96.fundark"
        minSdkVersion BuildVersion.minSdkVersion
        targetSdkVersion BuildVersion.targetSdkVersion
        versionCode BuildVersion.versionCode
        versionName BuildVersion.versionName

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled 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'
    }
    buildFeatures {
        viewBinding true
        dataBinding true
    }
}

dependencies {
    //从基础库继承各个依赖
    implementation project(':module_base')
}

迁移后:

ini 复制代码
plugins {
    id("com.android.application")
    id("kotlin-android")
    id("kotlin-kapt")
    id("kotlin-parcelize")
}

android {
    compileSdk  = BuildVersion.compileSdkVersion
    defaultConfig {
        applicationId = ("com.silencefly96.fundark")
        minSdk  = (BuildVersion.minSdkVersion)
        targetSdk  = (BuildVersion.targetSdkVersion)
        versionCode = (BuildVersion.versionCode)
        versionName = (BuildVersion.versionName)

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

    buildTypes {
        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"
    }
    buildFeatures {
        viewBinding = (true)
        dataBinding = (true)
    }
}

dependencies {
    //从基础库继承各个依赖
    implementation(project(":module_base"))
}

有些括号自动替换的时候多余了,可以手动去掉。

总结

没什么技术含量,迁移过程遇到挺多坑,有些现在还没弄明白,就记录下吧!

相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui