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 迁移的主要内容,如果未能解决你的问题,请参考以下文章