Gradle 从 Groovy 到 KTS 迁移

Posted 川峰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gradle 从 Groovy 到 KTS 迁移相关的知识,希望对你有一定的参考价值。

本文主要记录Groovy版本和kotlin版本的Gradle 相关设置。以便备忘或以后迁移参考。

settings.gradle

settings.gradle

pluginManagement 
 	// 所有Gradle插件的下载远程仓库地址
    repositories 
        gradlePluginPortal()
        //google()
        //mavenCentral()
        // 阿里云镜像
        maven  url 'https://maven.aliyun.com/repository/central' 
        maven  url 'https://maven.aliyun.com/repository/public' 
        maven  url 'https://maven.aliyun.com/repository/jcenter' 
        maven  url 'https://maven.aliyun.com/repository/google' 
        maven  url 'https://maven.aliyun.com/repository/releases' 
        maven  url 'https://maven.aliyun.com/repository/snapshots' 
        maven  url 'https://maven.aliyun.com/repository/gradle-plugin' 
    

dependencyResolutionManagement 
	// 所有模块依赖库的下载远程仓库地址
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories 
        //google()
        //mavenCentral()
        // 阿里云镜像
        maven  url 'https://maven.aliyun.com/repository/central' 
        maven  url 'https://maven.aliyun.com/repository/public' 
        maven  url 'https://maven.aliyun.com/repository/jcenter' 
        maven  url 'https://maven.aliyun.com/repository/google' 
        maven  url 'https://maven.aliyun.com/repository/releases' 
        maven  url 'https://maven.aliyun.com/repository/snapshots' 
        maven  url 'https://maven.aliyun.com/repository/gradle-plugin' 
    

rootProject.name = "My Application"
include ‘:app’

settings.gradle.kts

pluginManagement 
 	// 所有Gradle插件的下载远程仓库地址
    repositories 
        gradlePluginPortal()
        //google()
        //mavenCentral()
        // 阿里云镜像
        maven(url = "https://maven.aliyun.com/repository/central")
        maven(url = "https://maven.aliyun.com/repository/public")
        maven(url = "https://maven.aliyun.com/repository/jcenter")
        maven(url = "https://maven.aliyun.com/repository/google")
        maven(url = "https://maven.aliyun.com/repository/releases")
        maven(url = "https://maven.aliyun.com/repository/snapshots")
        maven(url = "https://maven.aliyun.com/repository/gradle-plugin")
    

dependencyResolutionManagement 
	// 所有模块依赖库的下载远程仓库地址
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories 
        //google()
        //mavenCentral()
        // 阿里云镜像
        maven(url = "https://maven.aliyun.com/repository/central")
        maven(url = "https://maven.aliyun.com/repository/public")
        maven(url = "https://maven.aliyun.com/repository/jcenter")
        maven(url = "https://maven.aliyun.com/repository/google")
        maven(url = "https://maven.aliyun.com/repository/releases")
        maven(url = "https://maven.aliyun.com/repository/snapshots")
        maven(url = "https://maven.aliyun.com/repository/gradle-plugin")
    

rootProject.name = "My Application"
include ‘:app’

推荐使用阿里云的Maven镜像仓库地址,下载速度很快。

根目录 build.gradle

build.gradle

ext 
    sdkVersion = 33 
    appcompatVersion = "1.6.0"
    ...

plugins  
	// apply false只能用于顶层build.gradle文件,切勿写在子模块中
    id 'com.android.application' version '7.3.1' apply false 
    id 'com.android.library' version '7.3.1' apply false
    id 'org.jetbrains.kotlin.android' version '1.7.21' apply false

build.gradle.kts

ext 
    extra["sdkVersion"] = 33 
    extra["appcompatVersion"] = "1.6.0"
    ...

plugins  
	// apply false只能用于顶层build.gradle文件,切勿写在子模块中
    id("com.android.application") version "7.3.1" apply false
    id("com.android.library") version "7.3.1" apply false
    id("org.jetbrains.kotlin.android") version "1.7.21" apply false

子模块 build.gradle

build.gradle

plugins 
    id 'com.android.application'
 
android  
	// 每个 Android 模块都有一个命名空间,此命名空间用作其生成的 R 和 BuildConfig 类的 Java 或 Kotlin 软件包名称。
    namespace 'com.example.myapp' 
    compileSdk 33 
    defaultConfig  
        applicationId 'com.example.myapp' 
        minSdk 21 
        targetSdk 33 
        versionCode 1 
        versionName "1.0"
        manifestPlaceholders = [hostName:"www.example.com"]
        javaCompileOptions 
            annotationProcessorOptions 
                argument 'key1', 'value1'
                argument 'key2', 'value2'
            
        
         kapt 
            includeCompileClasspath false
        
      
    signingConfigs 
        release 
            storeFile file("myreleasekey.keystore")
            storePassword "password"
            keyAlias "MyReleaseKey"
            keyPassword "password"
        
    
    buildTypes  
        release 
              minifyEnabled true // Enables code shrinking for the release build type.
              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
              signingConfig signingConfigs.release
        
        debug 
            applicationIdSuffix ".debug" // 在 applicationId 后面追加一段
            debuggable true
        
        staging 
            initWith debug // 允许您从其他构建类型复制配置,然后只配置您想更改的设置。
            manifestPlaceholders = [hostName:"internal.example.com"]
            applicationIdSuffix ".debugStaging"
        
      
    flavorDimensions "tier"
    productFlavors 
        free 
            dimension "tier"
            applicationId 'com.example.myapp.free'
            applicationIdSuffix ".demo"
            versionNameSuffix "-demo"
         
        paid 
            dimension "tier"
            applicationId 'com.example.myapp.paid'
            applicationIdSuffix ".full"
            versionNameSuffix "-full"
        
    
    // 过滤变体
    variantFilter  variant ->
	      def names = variant.flavors*.name
	      // To check for a certain build type, use variant.buildType.name == "<buildType>"
	      if (names.contains("minApi21") && names.contains("demo")) 
	          // Gradle ignores any variants that satisfy the conditions above.
	          setIgnore(true)
	      
	 
	 sourceSets  
	    main  
	      java.srcDirs = ['other/java'] 
	      res.srcDirs = ['other/res1', 'other/res2'] 
	      manifest.srcFile 'other/AndroidManifest.xml'
	      ...
	     
	    androidTest  
	      setRoot 'src/tests'
	      ...
	    
	
 
configurations 
    // 将产品变种和 build 类型组合在一起的变体添加依赖项,就必须在 configurations 代码块中初始化配置名称。
    freeDebugRuntimeOnly 

dependencies 
    implementation project(":lib")
    implementation 'androidx.appcompat:appcompat:1.6.0'
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation files('libs/foo.jar', 'libs/bar.jar')
    freeImplementation 'com.google.firebase:firebase-ads:9.8.0'
    freeDebugRuntimeOnly fileTree(dir: 'libs', include: ['*.jar'])
	
	// 排除传递依赖项
	implementation('some-library') 
        exclude group: 'com.example.imgtools', module: 'native'
    
	 // 从测试配置中排除传递依赖项
	android.testVariants.all  variant ->
	    variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
	    variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
	
	
	compileOnly 'com.google.dagger:dagger:version-number' 
	// 注意:Android Plugin for Gradle 3.0.0 及更高版本不再支持 android-apt 插件
    annotationProcessor 'com.google.dagger:dagger-compiler:version-number'
	
	testImplementation 'junit:junit:4.12' 
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.0.2'

build.gradle.kts

plugins 
    id("com.android.application")
 
android  
	// 每个 Android 模块都有一个命名空间,此命名空间用作其生成的 R 和 BuildConfig 类的 Java 或 Kotlin 软件包名称。
    namespace = "com.example.myapp" 
    compileSdk = 33  
    defaultConfig  
        applicationId = "com.example.myapp" 
        minSdk = 21 
        targetSdk = 33 
        versionCode = 1 
        versionName = "1.0"
        manifestPlaceholders["hostName"] = "www.example.com"
        javaCompileOptions 
            annotationProcessorOptions 
                arguments += mapOf("key1" to "value1",
                                   "key2" to "value2")
            
        
        kapt 
            includeCompileClasspath = false
        
     
    signingConfigs 
        create("release") 
            storeFile = file("myreleasekey.keystore")
            storePassword = "password"
            keyAlias = "MyReleaseKey"
            keyPassword = "password"
        
    
    buildTypes   
        getByName("release") 
            isMinifyEnabled = true // Enables code shrinking for the release build type.
            proguardFiles(
                getDefaultProguardFile("proguard-android.txt"),
                "proguard-rules.pro"
            )
            signingConfig = signingConfigs.getByName("release")
        
        getByName("debug") 
            applicationIdSuffix = ".debug" // 在 applicationId 后面追加一段
            isDebuggable = true
        
         create("staging") 
            initWith(getByName("debug")) // 允许您从其他构建类型复制配置,然后只配置您想更改的设置。
            manifestPlaceholders["hostName"] = "internal.example.com"
            applicationIdSuffix = ".debugStaging"
        
    
    flavorDimensions += "tier"
    productFlavors 
        create("free") 
            dimension = "tier"
            applicationId = "com.example.myapp.free"
            applicationIdSuffix = ".demo"
            versionNameSuffix = "-demo"
         
        create("paid") 
            dimension = "tier"
            applicationId = "com.example.myapp.paid"
            applicationIdSuffix = ".full"
            versionNameSuffix = "-full"
        
    
    sourceSets.getByName("main") 
	    java.setSrcDirs(listOf("other/java"))
	    res.setSrcDirs(listOf("other/res1", "other/res2"))
	    manifest.srcFile("other/AndroidManifest.xml")
	    ...
	 
  	sourceSets.getByName("androidTest")  
	      setRoot("src/tests")
	      ...
  	
 
// 过滤变体
androidComponents 
    beforeVariants  variantBuilder ->
        // To check for a certain build type, use variantBuilder.buildType == "<buildType>"
        if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) 
            // Gradle ignores any variants that satisfy the conditions above.
            variantBuilder.enable = false
        
    

// 将产品变种和 build 类型组合在一起的变体添加依赖项,就必须在 configurations 代码块中初始化配置名称。
val freeDebugRuntimeOnly by configurations.creating
dependencies 
    implementation(project(":lib"))
    implementation("androidx.appcompat:appcompat:1.6.0")
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
    implementation(files("libs/foo.jar", "libs/bar.jar"))
    freeImplementation("com.google.firebase:firebase-ads:9.8.0")
    freeDebugRuntimeOnly(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
	
	// 排除传递依赖项
	implementation("some-library") 
        exclude(group = "com.example.imgtools", module = "native")
    
    // 从测试配置中排除传递依赖项 
	android.testVariants.all 
	    compileConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp")
	    runtimeConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp")
	
	
	compileOnly("com.google.dagger:dagger:version-number") 
	// 注意:Android Plugin for Gradle 3.0.0 及更高版本不再支持 android-apt 插件
    annotationProcessor("com.google.dagger:dagger-compiler:version-number")
	
	testImplementation("junit:junit:4.12") 
    androidTestImplementation("androidx.test.espresso:espresso-core:3.0.2")

子模块build.gradle 引用全局属性

build.gradle

android  
    compileSdk rootProject.ext.sdkVersion
    ...

...
dependencies 
    implementation "androidx.appcompat:appcompat:$rootProject.ext.appcompatVersion"
    ...

build.gradle.kts

android  
    compileSdk = rootProject.extra["sdkVersion"] 
    val sdkVersion: Int by rootProject.extra // 可以使用kotlin委托语法
    ...
    compileSdk = sdkVersion

...
dependencies 
    implementation("androidx.appcompat:appcompat:$rootProject.ext.appcompatVersion")
    ...

为每个变体创建动态版本号

groovy:

android 
  ...
  defaultConfig 
    ...
    versionCode 4
  
  splits 
    ...
  


// Map for the version code that gives each ABI a value.
ext.abiCodes = ['armeabi-v7a':1, mips:2, x86:3]

// For per-density APKs, create a similar map like this:
// ext.densityCodes = ['hdpi': 1, 'xhdpi': 2, 'xxhdpi': 3, 'xxxhdpi': 4]

import com.android.build.OutputFile

// For each APK output variant, override versionCode with a combination of
// ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
android.applicationVariants.all  variant ->

  // Assigns a different version code for each output APK
  // other than the universal APK.
  variant.outputs.each  output ->

    // Stores the value of ext.abiCodes that is associated with the ABI for this variant.
    def baseAbiVersionCode =
            // Determines the ABI for this variant and returns the mapped value.
            project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))

    // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
    // the following code does not override the version code for universal APKs.
    // However, because we want universal APKs to have the lowest version code,
    // this outcome is desirable.
    if (baseAbiVersionCode != null) 

      // Assigns the new version code to versionCodeOverride, which changes the version code
      // for only the output APK, not for the variant itself. Skipping this step simply
      // causes Gradle to use the value of variant.versionCode for the APK.
      output.versionCodeOverride =
              baseAbiVersionCode * 1000 + variant.versionCode
    
  

kotlin:

android 
  ...
  defaultConfig 
    ...
    versionCode = 4
  
  splits 
    ...
  


// Map for the version code that gives each ABI a value.
val abiCodes = mapOf("armeabi-v7a" to 1, "mips" to 2, "x86" to 3)

// For per-density APKs, create a similar map like this:
// val densityCodes = mapOf("hdpi" to 1, "xhdpi" to 2, "xxhdpi" to 3, "xxxhdpi" to 4)

import com.android.build.api.variant.FilterConfiguration.FilterType.*

// For each APK output variant, override versionCode with a combination of
// abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
androidComponents 
    onVariants  variant ->

        // Assigns a different version code for each output APK
        // other than the universal APK.
        variant.outputs.forEach  output ->
            val name = output.filters.find  it.filterType == ABI ?.identifier

            // Stores the value of abiCodes that is associated with the ABI for this variant.
            val baseAbiCode = abiCodes[name]
            // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
            // the following code does not override the version code for universal APKs.
            // However, because we want universal APKs to have the lowest version code,
            // this outcome is desirable.
            if (baseAbiCode != null) 
                // Assigns the new version code to output.versionCode, which changes the version code
                // for only the output APK, not for the variant itself.
                output.versionCode.set(baseAbiCode * 1000 + (output.versionCode.get() ?: 0))
            
        
    

查看传递依赖项

在gradle面板中执行androidDependencies任务即可:

AAR 中的原生依赖项

Gradle 模块中的 AAR 依赖项可公开原生库供您的应用使用。

以上是关于Gradle 从 Groovy 到 KTS 迁移的主要内容,如果未能解决你的问题,请参考以下文章

将构建配置从 Groovy 迁移到 KTS

将构建配置从 Groovy 迁移到 KTS

将构建配置从 Groovy 迁移到 KTS

如何在 gradle kts 中排除(忽略)android 构建变体

如何从 Kotlin DSL build.gradle 中的所有依赖项中排除库?

如何将 gradle 中的 groovy 任务转换为 Gradle Kotlin DSL 以生成 pom.xml?