前言
25年主要工作是新App的开发和抽离,期间对Asm和Plugin方面工作较多,理所当然的需要和Gradle打交道,由于项目中使用的Gradle版本较低,且为Groovy版本,所以对Groovy7.0和Kts版本是如何使用的,之前看过但是没有实践过,所以就有了本篇记录文章,算是对25年上半年部分学习知识的总结。 ps:AI当道,虽然很多问题和疑惑直接让Cursor来实现就好了,但是该有的知识库积累还是要做的,好记性不如烂笔头。
Gradle简要介绍
注释:下边以Gradle kts 为例 简单展示下一般工程的项目结构图
bash
MyAndroidApp/
├── gradle/
│ ├── wrapper/
│ │ ├── gradle-wrapper.jar # 主要是Gradle的运行逻辑,包含下载Gradle
│ │ └── gradle-wrapper.properties # Wrapper 配置,定义了Gradle版本
│ └── libs.versions.toml # 版本目录(Gradle 7.0+)
│
├── app/ # 应用模块
│ ├── build.gradle.kts # 模块构建脚本
│ ├── proguard-rules.pro # ProGuard 规则
│ └── src/ # 源代码
│
├── ktslibrary/ # 库模块(可选)
│ ├── build.gradle.kts
│ └── src/
│
├── buildSrc/ # 自定义构建逻辑(可选)
│ ├── build.gradle.kts
│ └── src/
│
├── build.gradle.kts # 根项目构建脚本
├── settings.gradle.kts # 项目设置
├── gradle.properties # Gradle 属性配置
├── local.properties # 本地配置(不提交到 Git)
├── gradlew # Gradle Wrapper 脚本(Unix)
└── gradlew.bat # Gradle Wrapper 脚本(Windows)
gradle-wrapper.properties
kotlin
#Tue Nov 11 20:22:16 CST 2025
//下载的Gradle的压缩包解压后的主目录
distributionBase=GRADLE_USER_HOME
// 相对于distributionBase的解压后的Gradle的路径,为wrapper/dists
distributionPath=wrapper/dists
// Gradle版本的下载地址
distributionUrl=https://services.gradle.org/distributions/gradle-8.11.1-bin.zip
// 同distributionBase,不过是存放zip压缩包的主目录
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
和groovy版本变化不大,主要解释都在备注里了
settings.gradle.kts
kotlin
// 1. 插件管理配置
pluginManagement {
// 配置插件仓库
repositories {
// Google 的 Maven 仓库(Android 插件)
google {
// 内容过滤:只从 Google 下载特定包
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral() // Maven 中央仓库
gradlePluginPortal() // Gradle 插件门户
}
// 插件版本解析策略
resolutionStrategy {
eachPlugin {
// 自定义插件版本解析
if (requested.id.id == "com.example.plugin") {
useModule("com.example:plugin:${requested.version}")
}
}
}
}
// 2. 依赖管理配置 三方库引入的源头配置
dependencyResolutionManagement {
// 仓库模式
// FAIL_ON_PROJECT_REPOS: 禁止在项目中声明仓库(推荐)
// PREFER_PROJECT: 优先使用项目中的仓库
// PREFER_SETTINGS: 优先使用 settings 中的仓库
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
// 配置依赖仓库
repositories {
google()
mavenCentral()
mavenLocal() // 本地 Maven 仓库
maven { url = uri("https://jitpack.io") } // JitPack(GitHub 项目)
// 阿里云镜像(国内加速)
maven { url = uri("https://maven.aliyun.com/repository/public") }
maven { url = uri("https://maven.aliyun.com/repository/google") }
}
// 版本目录
versionCatalogs {
// 自定义版本目录
create("testLibs") {
from(files("gradle/test-libs.versions.toml"))
}
}
}
// 3. 构建缓存配置
buildCache {
local {
isEnabled = true
directory = File(rootDir, "build-cache")
removeUnusedEntriesAfterDays = 30
}
remote<HttpBuildCache> {
url = uri("https://build-cache.example.com/cache/")
isEnabled = false
isPush = false
}
}
// 4. 插件管理(高级)
plugins {
// 在 settings 中应用插件(Gradle 8.0+)
id("com.gradle.enterprise") version "3.15"
}
// 5. 项目配置
// 设置根项目名称
rootProject.name = "GradleY"
// 包含模块
include ':GroovyLibrary'
include ':KtsLibrary'
// 6. Gradle Enterprise / Build Scan
gradleEnterprise {
buildScan {
termsOfServiceUrl = "https://gradle.com/terms-of-service"
termsOfServiceAgree = "yes"
publishAlways()
// 自定义标签
tag("CI")
value("Git Commit", getGitCommit())
}
}
// 辅助函数
fun getGitCommit(): String {
return try {
val process = Runtime.getRuntime().exec("git rev-parse --short HEAD")
process.inputStream.bufferedReader().readText().trim()
} catch (e: Exception) {
"unknown"
}
}
该文件用来配置插件管理,依赖库管理和项目相关配置,具体作用见代码注释中标注
根项目build.gradle.kts
kotlin
// build.gradle.kts (root)
// 1. 插件声明
plugins {
// 使用版本目录(推荐)
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.jvm) apply false
// 或直接声明版本
id("com.android.application") version "8.1.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
// apply false 的含义:
// 声明版本但不应用到根项目,由子项目自己决定是否应用
}
// 为所有项目配置
allprojects {
// 设置项目属性
group = "com.example"
version = "1.0.0"
// 配置任务
tasks.withType<JavaCompile>().configureEach {
options.encoding = "UTF-8"
}
}
// 为所有子项目配置
subprojects {
// 应用通用插件
apply(plugin = "checkstyle")
// 配置通用依赖
dependencies {
// 所有子项目都添加这个依赖
"implementation"("org.jetbrains.kotlin:kotlin-stdlib")
}
}
alias(libs.plugins.android.application) apply false ,kotlin 挺好的一点就是可进行定义跳转,alias后边这里的 定义在 libs.versions.toml文件中,apply false表示不应用到跟项目,子项目可以使用。
这里还需要注意的是allprojects 是包含整个项目的配置, subprojects 不包含跟项目,只包含子项目。
app build.gradle.kts
kotlin
// 1. 插件配置
plugins {
// 应用插件
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.kapt) // Kotlin 注解处理
// 或直接声明
id("com.android.application")
id("org.jetbrains.kotlin.android")
kotlin("kapt") // 等同于 id("org.jetbrains.kotlin.kapt")
}
// 2. Android 基本配置
android {
// 命名空间(AGP 7.0+,替代 manifest 中的 package)
namespace = "com.example.app"
// 编译 SDK 版本
compileSdk = 33
// 构建工具版本(可选,默认使用 AGP 推荐版本)
buildToolsVersion = "33.0.1"
// 默认配置
defaultConfig {
applicationId = "com.example.app" // 应用 ID
minSdk = 24
targetSdk = 33
versionCode = 1 // 版本号
versionName = "1.0.0"
// 测试运行器
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// BuildConfig 字段
buildConfigField("String", "API_BASE_URL", "\"https://api.example.com\"")
buildConfigField("boolean", "ENABLE_LOGGING", "true")
buildConfigField("int", "MAX_RETRY_COUNT", "3")
// Vector Drawable 支持
vectorDrawables {
useSupportLibrary = true
}
ndk {
// NDK 配置 支持的 ABI
abiFilters += setOf("armeabi-v7a", "arm64-v8a")
}
multiDexEnabled = true // 多 Dex 支持
consumerProguardFiles("consumer-rules.pro") // ProGuard 消费者规则
}
// 签名配置
signingConfigs {
getByName("debug") { // Debug 签名
storeFile = file("debug.keystore")
storePassword = "android"
keyAlias = "androiddebugkey"
keyPassword = "android"
}
create("release") { // Release 签名
// 从 local.properties 读取
val keystoreProperties = File(rootDir, "keystore.properties")
if (keystoreProperties.exists()) {
val properties = java.util.Properties()
properties.load(keystoreProperties.inputStream())
storeFile = file(properties["storeFile"] as String)
storePassword = properties["storePassword"] as String
keyAlias = properties["keyAlias"] as String
keyPassword = properties["keyPassword"] as String
}
}
}
// 构建类型
buildTypes {
// Debug 类型
debug {
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
isDebuggable = true
isMinifyEnabled = false
isShrinkResources = false
buildConfigField("String", "API_BASE_URL", "\"https://dev-api.example.com\"")
resValue("string", "app_name", "MyApp Debug")
signingConfig = signingConfigs.getByName("debug")
}
// Release 类型
release {
isDebuggable = false
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signingConfigs.getByName("release")
buildConfigField("String", "API_BASE_URL", "\"https://api.example.com\"")
resValue("string", "app_name", "MyApp")
}
}
// 编译选项
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
// 启用 desugaring
isCoreLibraryDesugaringEnabled = true
}
kotlinOptions {
jvmTarget = "11"
// Kotlin 编译器参数
freeCompilerArgs = listOf(
"-opt-in=kotlin.RequiresOptIn",
"-Xjvm-default=all",
"-Xcontext-receivers"
)
}
// 构建特性
buildFeatures {
viewBinding = true // ViewBinding
dataBinding = false // DataBinding
compose = false // Compose
buildConfig = true // BuildConfig
aidl = false // AIDL
renderScript = false // RenderScript
shaders = false // Shaders
}
// Compose 配置(如果启用)
composeOptions {
kotlinCompilerExtensionVersion = "1.5.3"
}
}
// 3. 依赖配置
dependencies {
// Core
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
// Kotlin
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.coroutines.android)
// Android Components
implementation(libs.androidx.activity.ktx)
implementation(libs.androidx.fragment.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
...
}
主要声明App bundle中使用到的依赖,构建信息设置和应用插件等信息
library build.gradle.kts
kotlin
plugins {
alias(libs.plugins.android.library) // 注意是 library 不是 application
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.example.library"
compileSdk = 33
defaultConfig {
minSdk = 24
// library 没有 applicationId 和 versionCode/versionName
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// 消费者 ProGuard 规则
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
// library 可以发布不同的变体
publishNonDefault = true
}
dependencies {
// api: 透传依赖 给使用此库的模块
api(libs.kotlin.stdlib)
// implementation: 不透传 仅当前模块依赖
implementation(libs.androidx.core.ktx)
testImplementation(libs.junit)
}
gradle libs.versions.toml
ini
[versions]
agp = "8.10.0"
kotlin = "2.0.21"
coreKtx = "1.17.0"
junit = "4.14-SNAPSHOT"
junitVersion = "1.3.0"
espressoCore = "3.7.0"
lifecycleRuntimeKtx = "2.9.4"
activityCompose = "1.11.0"
composeBom = "2024.09.00"
appcompat = "1.7.1"
material = "1.13.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
android-library = { id = "com.android.library", version.ref = "agp" }
传统的依赖方式使用 字符串,容易拼写错误。kts的新版本依赖方式IDE 自动补全,Cmd+点击可跳转,并且版本管理更加集中
gradle.properties
properties
# -Xmx: jvm最大堆内存(根据机器配置调整,8GB 机器建议 4096m,16GB 建议 8192m)
# -XX:MaxMetaspaceSize: 元空间最大大小
# -XX:+HeapDumpOnOutOfMemoryError: OOM 时生成堆转储
# -Dfile.encoding: 文件编码
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# 并行编译(利用多核 CPU)
org.gradle.parallel=true
# 配置缓存(实验性功能,显著提升速度) Gradle 8.0+ 稳定,强烈推荐开启
org.gradle.configuration-cache=true
# 构建缓存(复用之前的构建结果)
org.gradle.caching=true
# 按需配置 大型多模块项目建议开启
org.gradle.configureondemand=true
# 后台守护进程,避免每次构建都启动 JVM
org.gradle.daemon=true
# 文件监听(增量构建的基础)
org.gradle.vfs.watch=true
# Kotlin Daemon JVM 参数
kotlin.daemon.jvmargs=-Xmx2048m
# 增量编译
kotlin.incremental=true
# Kotlin 编译缓存
kotlin.caching.enabled=true
# Kotlin 编译器执行策略
# in-process: 在 Gradle Daemon 进程中编译(推荐)
# daemon: 使用单独的 Kotlin Daemon(默认)
# out-of-process: 每次新建进程
kotlin.compiler.execution.strategy=in-process
# 并行编译 Kotlin 模块
kotlin.parallel.tasks.in.project=true
# 使用 AndroidX
android.useAndroidX=true
# kotlin代码样式
kotlin.code.style=official
# 自动迁移第三方库到 AndroidX(通常关闭)
android.enableJetifier=false
# 使每个库的 R 类能够命名空间,让R 类只包含库本身声明的资源,不包含库依赖资源,缩小该库 R 类的大小
android.nonTransitiveRClass=true
# 使用新的资源处理器(AAPT2)
android.enableResourceOptimizations=true
# 禁用 PNG 优化(Debug 时可禁用)
# android.enablePngCrunchInDebugVariant=false
# 启用 D8 desugaring
android.enableD8.desugaring=true
# 启用 R8
android.enableR8=true
# 构建缓存
android.enableBuildCache=true
# 版本号(可被脚本读取)
VERSION_NAME=1.0.0
VERSION_CODE=1
# 签名配置(从环境变量读取,不提交到代码仓库)
# KEYSTORE_FILE=/path/to/keystore
# KEYSTORE_PASSWORD=password
# KEY_ALIAS=alias
# KEY_PASSWORD=password
# API 配置
# API_BASE_URL=https://api.example.com
# Maven 仓库用户名密码(不要提交到仓库)
# MAVEN_USERNAME=username
# MAVEN_PASSWORD=password
local.properties
properties
# Android SDK 路径(Android Studio 自动生成)
sdk.dir=/Users/username/Library/Android/sdk
# NDK 路径
ndk.dir=/Users/username/Library/Android/sdk/ndk/25.1.8937393
# 签名配置(敏感信息)
KEYSTORE_FILE=../release.keystore
KEYSTORE_PASSWORD=mypassword
KEY_ALIAS=mykey
KEY_PASSWORD=mypassword
# API Keys(敏感信息)
GOOGLE_MAPS_API_KEY=xxx
设置sdk和ndk本地地址,配置打包签名配置等信息
Gradle的Groovy & Kotlin区别
Gradle DSL 的特点
可读性更高,更加简洁 (模版代码少一些)
scss
// Groovy 和 kotlin都要使用到的 DSL格式,不同于java等代码方式
android {
compileSdk = 33
// 可以使用 Kotlin 的条件判断
if (project.hasProperty("useNewApi")) {
defaultConfig {
minSdk = 24
}
}
// 可以使用 Kotlin 的循环
listOf("debug", "release").forEach { buildType ->
println("Processing $buildType")
}
}
// 如果不使用DSL的方式 可能会写成这样 ,稍微复杂了点
val android = project.extensions.getByType(AndroidExtension::class.java)
android.setCompileSdk(33)
val config = DefaultConfig()
config.setMinSdk(24)
android.setDefaultConfig(config)
Gradle 主要使用的内部DSL (简单说下外部DSL:需要专门的代码注解器比如 Html 和 SQL) ,可以使用 Kotlin的一些语言特性,这里还是要提到一下 Groovy的闭包,
scss
// Gradle 的 android {} 块实际上是:调用 android() 方法, 传入一个闭包作为参数
android { // 闭包
compileSdk 33
}
android({
compileSdk 33
})
// 完整形态
android(new Closure() {
void call() {
compileSdk 33
}
})
大概得实现逻辑
class AndroidExtension { // 定义 Android 扩展类
int compileSdk
void defaultConfig(Closure closure) {
def config = new DefaultConfig()
closure.delegate = config // 设置闭包的委托
closure() // 闭包
}
}
// 定义配置方法,接收闭包作为参数
def android(Closure closure) {
def ext = new AndroidExtension()
closure.delegate = ext // 设置委托
closure() // 闭包
return ext
}
// 使用(看起来像 DSL)
android {
compileSdk = 33 // 实际是在 AndroidExtension 上下文中
defaultConfig {
minSdk = 24 // 实际是在 DefaultConfig 上下文中
}
}
Kotlin中使用的则是 Lambda方式(如果参数为最后一个,则可以去掉括号),并且Kotlin是使用 = 号来赋值的,相较于 Groovy ,Kotlin是静态类型语言,部分类型不对在编译期就会提示。
kotlin
android { // Lambda 表达式
compileSdk = 33
defaultConfig { // 嵌套 Lambda
minSdk = 24
}
}
// android { } 大概实现逻辑,可以理解为 ApplicationExtension.compileSdk = 33
public fun org.gradle.api.Project.android(configure: org.gradle.api.Action<com.android.build.gradle.LibraryExtension>): kotlin.Unit { /* compiled code */ }
看Gradle源码,这里是委托给了 LibraryExtension ,所以compileSdk 字段就是 LibraryExtension 中的一个属性

所以 我们可以在Android 大括号里边使用compileSdk等字段的赋值
Groovy vs Kotlin 语法对比
- 字符串
groovy
// ========== Groovy ==========
def str1 = 'Hello world' // 普通字符串
def str3 = "Hello $name" // 字符串插值 可以单引号,也可以双引号
kotlin
// ========== Kotlin DSL ==========
val str1 = "only double quote" // 只能用双引号
val str2 = "Hello $name" // 字符串插值
- 变量
groovy
// ========== Groovy ==========
def name = "ymc" // 动态类型
String name = "ymc" // 显式类型
kotlin
// ========== Kotlin DSL ==========
var name = "ymc" // 可变
val name = "ymc" // 不可变(推荐)
- 方法调用
groovy
// ========== Groovy ==========
println("Hello")
println "Hello" // 可以省略括号
add(1, 2)
add 1, 2 // 可以省略括号和逗号
implementation 'androidx.core:core-ktx:1.9.0'
kotlin
// ========== Kotlin DSL ==========
println("Hello") // 必须有括号
add(1, 2) // 必须有括号
implementation("androidx.core:core-ktx:1.9.0") // 必须有括号
- plugins
groovy
// ========== Groovy ==========
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
// 或
apply plugin: 'com.android.application'
kotlin
// ========== Kotlin DSL ==========
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
kotlin("kapt") // 等价于 id("org.jetbrains.kotlin.kapt")
}
// 或
apply(plugin = "com.android.application")
- dependencies 块
groovy
// ========== Groovy ==========
dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
testImplementation 'junit:junit:4.13.2'
}
kotlin
// ========== Kotlin DSL ==========
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation(group = "com.google.code.gson", name = "gson", version = "2.10.1")
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.12")
testImplementation("junit:junit:4.13.2")
}
- android 块
groovy
// ========== Groovy ==========
android {
namespace 'com.example.app'
compileSdk 33
defaultConfig {
applicationId "com.example.app"
minSdk 24
targetSdk 33
versionCode 1
versionName "1.0"
}
buildTypes {
debug {
applicationIdSuffix '.debug'
debuggable true
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
kotlin
// ========== Kotlin DSL ==========
android {
namespace = "com.example.app"
compileSdk = 33
defaultConfig {
applicationId = "com.example.app"
minSdk = 24
targetSdk = 33
versionCode = 1
versionName = "1.0"
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
isDebuggable = true
}
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}
前边两段代码,比较明显的不同就是 boolean赋值,kotlin 是is开头,等号赋值
- 集合操作
groovy
// ========== Groovy ==========
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
exclude '**/test/**', '**/*.tmp'
kotlin
// ========== Kotlin DSL ==========
ndk {
abiFilters += setOf("armeabi-v7a", "arm64-v8a")
}
exclude("**/test/**", "**/*.tmp")
最后
记得22年新版本As就已经推荐使用kotlin来管理 Gradle ,学完后感觉相比于Groovy,kotlin编译期间更加安全,跳转和代码提示 ,更科学的管理类和版本控制。