Android gradle groovy改为kotlin总结

前言: Android gradle 的 Groovy 转 Kotlin 的难点在于groovy非常不规范,以为是一个变量其实是一个方法,以为是方法其实是一个一个字符串,koltin提供了更严格的语法。改为kotlin之后最大的变化就是扩展字段了,和groovy的语法完全不一样,需要好好了解学习一下,本文也会讲到。

下面是我对自己的项目改造总结,使用的gradle版本是gradle-7.3.3,agp版本是7.2.1。

文件重命名

改造前首先要将原来的gradle文件加上‘kts’后缀,如build.gradle改为build.gradle.kts,kts是Kotlin Script的缩写。重命名后AndroidStudio会自动识别为kotlin dsl。

项目的build.gradle

  • groovy

    // Top-level build file where you can add configuration options common to all sub-projects/modules.
    apply from: 'config.gradle'
    apply plugin: 'com.alibaba.arouter'
    
    buildscript {
        repositories {
            maven { url "https://maven.aliyun.com/repository/public" }
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:7.2.1'
            classpath "com.alibaba:arouter-register:1.0.2"
        }
    }
    
    allprojects {
        repositories {
            maven { url "https://maven.aliyun.com/repository/public" }
        }
    
        configurations.all {
            // fix 依赖冲突
            resolutionStrategy.force "androidx.appcompat:appcompat:1.4.2"
            resolutionStrategy.force "androidx.recyclerview:recyclerview:1.2.1"
        }
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    
  • kotlin

    apply(from = "config.gradle.kts")
    apply(plugin = "com.alibaba.arouter")
    
    buildscript {
        repositories {
            maven("https://maven.aliyun.com/repository/public")
        }
    
        dependencies {
            classpath(libs.android.gradlePlugin)
            classpath(libs.greendao.gradlePlugin)
        }
    }
    
    allprojects {
        repositories {
            maven("https://maven.aliyun.com/repository/public")
        }
    
        configurations.all {
            resolutionStrategy.force("androidx.appcompat:appcompat:1.4.2")
            resolutionStrategy.force("androidx.recyclerview:recyclerview:1.2.1")
        }
    }
    
    tasks.create<Delete>("clean") {
        delete(rootProject.buildDir)
    }
    

module的build.gradle

  • groovy

    apply plugin: 'com.android.application'
    apply plugin: 'org.greenrobot.greendao'
    
    android {
        compileSdk = libs.versions.compileSdk.get().toInteger()
        ndkVersion = libs.versions.ndkVersion.get()
    
        defaultConfig {
            applicationId "com.myapp.sample"
    
            minSdkVersion(libs.versions.minSdk.get().toInteger())
            targetSdkVersion(libs.versions.targetSdk.get().toInteger())
            versionCode 1
            versionName "1.0"
    
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
            multiDexEnabled true
            externalNativeBuild {
                cmake {
                    cppFlags ""
                    abiFilters "arm64-v8a", "armeabi-v7a", "x86"
                }
            }
        }
    
        signingConfigs {
            app {
                keyAlias 'appkey'
                keyPassword '******'
                storeFile file('key.jks')
                storePassword '******'
            }
        }
    
        buildTypes {
            release {
                minifyEnabled true
                zipAlignEnabled true
                signingConfig signingConfigs.app
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro', 'proguard-android.pro', 'proguard-third-libs.pro'
            }
    
            debug {
                minifyEnabled false
                debuggable true
                signingConfig signingConfigs.app
            }
        }
    
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    
        buildFeatures {
            dataBinding true
        }
    
        greendao {
            schemaVersion 1
        }
    
        externalNativeBuild {
            cmake {
                path "src/main/cpp/CMakeLists.txt"
                version "3.10.2"
            }
        }
    
        lintOptions {
            abortOnError false
        }
    }
    
    dependencies {
        configurations.all {
            // check for updates every build
            resolutionStrategy.cacheChangingModulesFor 30, 'seconds'
        }
    
        implementation(libs.glide)
        annotationProcessor(libs.glide.compiler)
        implementation(libs.androidx.constraintlayout)
        implementation(project(':easyPhotos'))
        implementation(libs.google.zxing.core) {
            exclude group: 'com.google.guava'
        }
    }
    
  • kotlin

    plugins {
        id("com.android.application")
        id("org.greenrobot.greendao")
    }
    android {
        compileSdk = libs.versions.compileSdk.get().toInt()
        ndkVersion = libs.versions.ndkVersion.get()
    
        defaultConfig {
            applicationId = "com.myapp.sample"
    
            minSdk = libs.versions.minSdk.get().toInt()
            targetSdk = libs.versions.targetSdk.get().toInt()
            versionCode = 1
            versionName = "1.0"
    
            testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
            multiDexEnabled = true
            externalNativeBuild {
                cmake {
                    cppFlags += listOf()
                    abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86")
                }
            }
        }
        signingConfigs {
            create("release") {
                keyAlias = "appkey"
                keyPassword = "******"
                storeFile = file("key.jks")
                storePassword = "******"
            }
        }
    
        buildTypes {
            release {
                isMinifyEnabled = true
                isZipAlignEnabled = true
                signingConfig = signingConfigs.getByName("release")
                proguardFiles(
                    getDefaultProguardFile("proguard-android.txt"),
                    "proguard-rules.pro",
                    "proguard-android.pro",
                    "proguard-third-libs.pro"
                )
            }
    
            debug {
                isMinifyEnabled = false
                isDebuggable = true
                signingConfig = signingConfigs.getByName("release")
            }
        }
    
        compileOptions {
            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8
        }
    
        buildFeatures {
            dataBinding = true
        }
    
        greendao {
            schemaVersion = 1
        }
    
        externalNativeBuild {
            cmake {
                path("src/main/cpp/CMakeLists.txt")
                version = "3.10.2"
            }
        }
    
        lintOptions {
            isAbortOnError = false
        }
    
    }
    
    dependencies {
        configurations.all {
            // check for updates every build
            resolutionStrategy.cacheChangingModulesFor(30, TimeUnit.SECONDS)
        }
    
        implementation(libs.glide)
        annotationProcessor(libs.glide.compiler)
        implementation(project(":easyPhotos"))
        implementation(libs.androidx.constraintlayout)
        implementation(libs.google.zxing.core) {
            //也可这么写  exclude(group = "com.google.guava")
            exclude(mapOf("group" to "com.google.guava"))
        }
    }
    

关于扩展字段

一、首先是新增扩展字段

groovy要新增扩展字段只需在ext{}里面随便加字段,kotlin改为用extra,语法也做了改变,具体看下面例子:

  • groovy

    //这里在项目根目录的user.gradle下新增用户名和密码
    ext {
        username = 'JohnSnow'
        password = 'abcxxx'
    }
    
  • kotlin 有三种写法

    // 写法一,如果不写rootProject默认会加上当前的project
    rootProject.extra.apply {
        set("username", "JohnSnow")
        set("password", "abcxxx")
    }
    
    // 写法二
    val username : String by rootProject.extra("JohnSnow")
    val password : String by rootProject.extra("abcxxx")
    
    // 写法三,大括号里面可以写语句,最后一行是返回值
    val username : String by rootProject.extra{
        val name = "JohnSnow"
        name
    }
    val password : String by rootProject.extra{"abcxxx"}
    
二、使用扩展字段
  • groovy

    def name = rootProject.ext.username
    def pwd = rootProject.ext.password
    
  • kotlin 有两种使用方式

    //方式一,这种方式就是Map的key-value形式
    val name = rootProject.extra["username"] as String
    val pwd = rootProject.extra["password"] as String
    
    //方式二,这是kotlin dsl提供的语法糖,这种方式指定的变量名username必须与extra里的"username"一致,
    //且必须指定字段类型(String)
    val username: String by rootProject.extra
    val password: String by rootProject.extra
    

关于上传到maven的写法区别

上传到maven有两种写法,

  1. 一种是直接在当前要上传的library模块的build.gradle里写上传脚步代码

这种方式自带模块的project环境,kotlin dsl做了一些适配,写法会更简单些

  1. 第二种是放到一个单独的maven.gradle里统一处理,这种方式适用于有很多个library需要上传的情况,不用每个模块都写一遍上传脚本;

这种方式是在单独的gradle里编写没有自带project的环境,所以第二种方式的写法会复杂一些,而且没有代码提示。

一、在library模块编写
  • groovy

    apply plugin: 'com.android.library'
    
    android {
        ...//提交到顺丰maven所需的配置
        publishing {
            singleVariant('release') {
                withSourcesJar()
            }
        }
    }
    // maven插件
    apply plugin: 'maven-publish'
    
    afterEvaluate {
        def GROUP_ID = "com.free.sdk"
        def ARTIFACT_ID = "wo-util"
        def VERSION = "1.0.0"
    
        publishing {
            publications {
                //mylib名字随意
                mylib(MavenPublication) {
                    from components.release
                    groupId = GROUP_ID
                    artifactId = ARTIFACT_ID
                    version = VERSION
                    pom.withXml {
                        println "!!!!>>>>>> ${project.name} 要上传的版本-> $groupId:$artifactId:$version"
                        println "!!!!>>>>>> ${project.name} 依赖的包:"
                        configurations.implementation.allDependencies.each {
                            if (it.version != "unspecified") { // 过滤项目内library引用
                                println "   " + it.group + ":" + it.name + ":" + it.version
                            }
                        }
                    }
                }
            }
            //需要发布的目标仓库
            repositories {
                maven {
                    url = rootProject.extra["mavenUrl"] as String
                    credentials {//密码认证
                        username = rootProject.extra["username"] as String
                        password = rootProject.extra["password"] as String
                    }
                }
            }
        }
    }
    
  • kotlin

    plugins {
        id("com.android.library")
        //注意maven插件要写在头部
        `maven-publish`
    }
    
    android {
        ...//提交到顺丰maven所需的配置
        publishing {
            singleVariant("release") {
                withSourcesJar()
            }
        }
    }
    
    afterEvaluate {
        val GROUP_ID = "com.free.sdk"
        val ARTIFACT_ID = "wo-util"
        val VERSION = "1.0.0"
    
        publishing {
            publications {
                //mylib名字随意
                register<MavenPublication>("mylib") {
                    from(components["release"])
                    groupId = GROUP_ID
                    artifactId = ARTIFACT_ID
                    version = VERSION
                    pom.withXml {
                        println("!!!!>>>>>> ${project.name} 要上传的版本-> $groupId:$artifactId:$version")
                        println("!!!!>>>>>> ${project.name} 依赖的包:")
                        configurations.implementation.allDependencies.forEach { dependency ->
                            if (dependency.version != "unspecified") {
                                println("   ${dependency.group}:${dependency.name}:${dependency.version}")
                            }
                        }
                    }
                }
            }
    
            repositories {
                maven {
                    setUrl(rootProject.extra["mavenUrl"] as String)
                    credentials {
                        username = rootProject.extra["username"] as String
                        password = rootProject.extra["password"] as String
                    }
                }
            }
        }
    }
    

二、在maven.gradle里统一处理

  • 在library的build.gradle.kts里引入maven.gradle

    plugins {
        id("com.android.library")
    }
    apply(from = "${rootProject.rootDir}/maven.gradle.kts")
    
  • maven.gradle.kts里的代码

    import org.gradle.api.publish.PublishingExtension
    
    apply(plugin = "maven-publish")
    
    val libraries: Map<String, Map<String, String>> by rootProject.extra
    val library = libraries[project.name]!!
    val sonatype: Map<String, String> by rootProject.extra
    
    val repositoryUrl = if ((library["version"] as String).endsWith("SNAPSHOT")) {
        sonatype["snapshotUrl"]!!
    } else {
        sonatype["releaseUrl"]!!
    }
    
    //publishing报错, 改为 configure<PublishingExtension>原因:
    //https://stackoverflow.com/questions/54654376/why-is-publishing-function-not-being-found-in-my-custom-gradle-kts-file-within
    configure<PublishingExtension> {// --------不同点1️⃣
        publications {
            register<MavenPublication>("mylib") {
                afterEvaluate { from(components["release"]) }
                groupId = rootProject.extra["groupId"] as String
                artifactId = library["artifactId"]
                version = library["version"]
                pom.withXml {
                    println("!!!!>>>>>> ${project.name} 要上传的版本-> $groupId:$artifactId:$version")
                    println("!!!!>>>>>> ${project.name} 依赖的包:")
                    configurations {
                        "implementation" {// --------不同点2️⃣
                            allDependencies.forEach {
                                if (it.version != "unspecified") { // 过滤项目内library引用
                                    println("   " + it.group + ":" + it.name + ":" + it.version)
                                }
                            }
                        }
                    }
                }
            }
        }
    
        repositories {
            maven {
                setUrl(repositoryUrl)
                credentials {
                    username = sonatype["username"]
                    password = sonatype["password"]
                }
            }
        }
    }
    

参考:

【Gradle-18】从Groovy迁移至Kotlin - 掘金

Gradle Kotlin DSL Primer

stackoverflow

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值