Gradle 从 Groovy 到 KTS 迁移

27 篇文章 2 订阅
5 篇文章 0 订阅

本文主要记录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 依赖项可公开原生库供您的应用使用。在 AAR 中,prefab 目录包含 Prefab 软件包,后者包含原生依赖项的头文件和库。

每个依赖项最多可公开一个包含一个或多个模块的 Prefab 软件包。Prefab 模块是一个单独的库,它可以是共享库或静态库,也可以是仅针对头文件的库。

软件包和模块的名称均已知时,才能使用相应库。按照惯例,软件包名称应与 Maven 工件名称相匹配,模块名称应与 C/C++ 库名称相匹配,但并非必须如此。请参考相应依赖项的文档来确定依赖项所用的名称。

必须为您的 Android Gradle 模块启用 prefab 功能。

为此,请将以下内容添加到您模块的 build.gradle 文件的 android 代码块中:

groovy:

buildFeatures {
  prefab true
}

kotlin:

buildFeatures {
  prefab = true
}

从 AAR 导入的依赖项将通过 CMAKE_FIND_ROOT_PATH 向 CMake 公开。当系统调用 CMake 时,Gradle 会自动设置此值,因此如果您的 build 修改了此变量,请务必确保对其附加相应值而不是直接赋值。

每个依赖项都会向您的 build 公开 config-file 软件包。这些软件包是通过 find_package 命令导入的。此命令会搜索与给定软件包名称和版本匹配的 config-file 软件包,并公开为您的 build 指定的目标。例如,如果您的应用定义了 libapp.so,且使用 cURL,则您的 CMakeLists.txt 应包含以下内容:

add_library(app SHARED app.cpp)

# Add these two lines.
find_package(curl REQUIRED CONFIG)
target_link_libraries(app curl::curl)

app.cpp 现在能够执行 #include “curl/curl.h”,系统会在构建时自动将 libapp.so 与 libcurl.so 相关联,并将 libcurl.so 包含在应用中。

在 AAR 中发布原生库

在 AGP 4.1 中首次添加了创建原生 AAR 的功能。

如需导出原生库,请将以下代码添加到库项目的 build.gradle 文件的 android 代码块中:

groovy:

buildFeatures {
    prefabPublishing true
}

prefab {
    mylibrary {
      headers "src/main/cpp/mylibrary/include"
    }

    myotherlibrary {
        headers "src/main/cpp/myotherlibrary/include"
    }
}

kotlin:

buildFeatures {
    prefabPublishing = true
}

prefab {
    create("mylibrary") {
      headers = "src/main/cpp/mylibrary/include"
    }

    create("myotherlibrary") {
        headers = "src/main/cpp/myotherlibrary/include"
    }
}

在本例中,您的 ndk-build 或 CMake 外部原生 build 中的 mylibrary 和 myotherlibrary 库会打包到您的 build 生成的 AAR 中,并且各自会将头文件从指定的目录导出到依赖于它们的项。

使用 Maven Publish 插件

Android Gradle 插件 3.6.0 及更高版本支持 Maven Publish Gradle 插件,可让您将构建工件发布到 Apache Maven 代码库。Android Gradle 插件会为应用或库模块中的每个构建变体工件创建一个组件,您可以使用它来自定义要发布到 Maven 代码库的发布内容。

Android 插件所创建的组件取决于模块是否使用应用或库插件,如下表所述。

Android Gradle 插件发布内容工件组件名称
com.android.libraryAARcomponents.variant
com.android.applicationAPK 和可用的 ProGuard 或 R8 映射文件的 ZIPcomponents.variant_apk
com.android.applicationAndroid App Bundle (AAB)components.variant_aab

以下代码示例为 AAR 库的发布和调试构建变体创建了发布内容。每项发布内容都会应用匹配的组件,并自定义所生成 POM 的属性,如 Maven 坐标。

// Because the components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.
afterEvaluate {
    publishing {
        publications {
            // Creates a Maven publication called "release".
            release(MavenPublication) {
                // Applies the component for the release build variant.
                from components.release

                // You can then customize attributes of the publication as shown below.
                groupId = 'com.example.MyLibrary'
                artifactId = 'final'
                version = '1.0'
            }
            // Creates a Maven publication called “debug”.
            debug(MavenPublication) {
                // Applies the component for the debug build variant.
                from components.debug

                groupId = 'com.example.MyLibrary'
                artifactId = 'final-debug'
                version = '1.0'
            }
        }
    }
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

川峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值