记录迁移gradle到kts
前言
最近练手了《Android依赖管理实践与总结》,里面关于Version Catalogs的部分鸽了,因为我练手的项目没有升到gradle7.x,最近花了点时间搞了下,这里记录下吧,也踩了一些坑,希望能够对读者有帮助。
知识了解
这里还是推荐修改之前,先看下Android官方的文档吧:
我这也参考了几篇文章,也贴一下,他们写的会更全一些(虽然并不能完全解惑),我这就是希望做个记录:
Android gradle 插件升级和 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"))
}
        有些括号自动替换的时候多余了,可以手动去掉。
总结
没什么技术含量,迁移过程遇到挺多坑,有些现在还没弄明白,就记录下吧!