Gradle详解
介绍Gradle配置中常用的属性信息,具体以配置文件注释形式展现
项目setting.gradle.kts
- 负责配置和定义项目模块结构,位于项目根目录
// Composing builds插件,引入自定义的插件
includeBuild("plugin_version")
// 配置Gradle插件的仓库源,plugins块中引用插件时,从这些仓库地址下载插件,对所有项目有效
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
// 非google和maven仓在此添加
maven { setUrl("https://jitpack.io") }
// maven(url = "https://jitpack.io")
}
}
// 配置项目依赖的仓库源,dependencies块中声明的依赖,从这些仓库地址下载依赖,统一管理多项目仓库配置
dependencyResolutionManagement {
// 控制仓库行为
// FAIL_ON_PROJECT_REPOS:项目中不允许其他的仓库配置项,有则构建时会报错
// PREFER_PROJECT:项目中若有其他的仓库配置项,这些仓库会被加到解析依赖时使用的仓库列表中
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// 非google和maven仓在此添加
maven { setUrl("https://jitpack.io") }
// maven(url = "https://jitpack.io")
}
}
rootProject.name = "X"
include(":app")
项目build.gradle.kts
- 负责管理插件,通过id和版本号指定插件,位于项目根目录
plugins {
// 包含构建Android应用所有必要功能的插件:编译代码、打包资源、签名apk等
id("com.android.application") version "8.2.1" apply false
// 用于支持kotlin的插件,包含编译kotlin代码、kotlin语言的特性支持等
id("org.jetbrains.kotlin.android") version "1.9.20" apply false
// 构建Android Lib的插件,不会生成apk,而是生成aar,包含编译代码和资源的库文件
id("com.android.library") version "8.2.1" apply false
// 一种比kapt更高效的注解,启用KSP:1.9.22-1.0.16
id("com.google.devtools.ksp") version "1.9.20-1.0.14" apply false
}
模块build.gradle.kts
- 负责配置特定模块的构建配置,位于模块根目录
// 导入plugin_version依赖类(自定义依赖管理插件)
import com.android.build.gradle.internal.api.BaseVariantOutputImpl
import com.dcxing.plugin.version.*
import java.text.SimpleDateFormat
import java.util.Date
// 依赖其他gradle值
// apply(from = rootProject.file("config.gradle"))
// apply plugin
//apply(plugin = "com.android.application")
// 额外变量定义
// extra["test_version"] = "1.0.0"
// val test_version by extra("1.0.0")
/* --------------- 主体配置 --------------- */
// 模块依赖插件配置
plugins {
// 标识该模块为应用模块,区别于library模块
id("com.android.application")
// 支持kotlin的插件
id("org.jetbrains.kotlin.android")
// 导入plugin_version插件
id("com.dcxing.plugin.version")
// kapt
// id("kotlin-kapt")
// 启用KSP
id("com.google.devtools.ksp")
// 序列化插件
id("kotlin-parcelize")
}
// 属性定义
val buildTime: String = SimpleDateFormat("yyMMdd").format(Date().time)
// 构建过程中,所添加的依赖Gradle会先从本地检索,找不到才会去远程仓库查找,找到后会缓存至本地,默认缓存24小时,可加快下次构建速度,避免非必要网络下载
configurations.all {
// 动态版本缓存时效
resolutionStrategy.cacheDynamicVersionsFor(120, "minutes")
// 快照版本缓存时效
resolutionStrategy.cacheChangingModulesFor(24, "hours")
}
val resDirs = arrayOf(
"ui/toolbar",
"ui/home"
)
android {
// 命名空间,一般与包名一致
namespace = AndroidConfig.namespace_x
// sdk编译版本
compileSdk = AndroidConfig.compileSdkVersion
defaultConfig {
// 包名
applicationId = AndroidConfig.applicationId
// 最小适配机型,例26,最小适配至Android 8.0
minSdk = AndroidConfig.minSdkVersion
// 最大适配机型,例35,最大适配至Android 15.0
targetSdk = AndroidConfig.targetSdkVersion
// 版本号,一般应用于升级场景,升级+1,或按修改次数调整大小
versionCode = AndroidConfig.versionCode
// 版本名,会展示在设置 - 应用列表 - 应用信息中
versionName = AndroidConfig.versionName
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
// ARouter
ksp {
arg("AROUTER_MODULE_NAME", project.name)
}
// kapt {
// arguments {
// arg("AROUTER_MODULE_NAME", project.name)
// }
// }
// javaCompileOptions {
// annotationProcessorOptions {
// argument("AROUTER_MODULE_NAME", project.name)
// }
// }
// 统一依赖配置信息,例强制okhttp版本
configurations.all {
// com.squareup.okhttp3:okhttp:4.12.0
// 方式1
// resolutionStrategy {
// force("com.squareup.okhttp3:okhttp:4.12.0")
// }
// 方式2
// resolutionStrategy.force(
// "com.squareup.okhttp3:okhttp:4.12.0"
// )
// 方式3
// resolutionStrategy.eachDependency {
// 遍历Configuration下所有依赖,匹配修改最终依赖版本号
// if (requested.group == "com.squareup.okhttp3"
// && requested.name == "okhttp") {
// useVersion("4.12.0")
// }
// }
// resolutionStrategy {
// 开启版本冲突报错模式,可直接查看冲突日志
// failOnVersionConflict()
// }
}
}
// 定义构建类型,debug或release
buildTypes {
release {
// 构建时禁用用res/drawable自动压缩,提高编译速度
// isCrunchPngs = false
// 开启混淆,代码压缩
isMinifyEnabled = true
// 移除无用资源
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
// 获取release buildTypes
signingConfig = signingConfigs.getByName("release")
// 定义BuildConfig变量,可配置基础url
buildConfigField("Int", "BUILD_TIME", buildTime)
buildConfigField("Boolean", "IS_RELEASE", "true")
buildConfigField("String", "BASE_URL", "https://xxx.api")
// 可配置apk生成文件名
android.applicationVariants.all {
outputs.all {
val output: BaseVariantOutputImpl = this as BaseVariantOutputImpl
// output.outputFileName = "${name}-${versionName}-${versionCode}-(${buildTime}).aab"
output.outputFileName = "${name}-${versionName}-${versionCode}-(${buildTime}).apk"
}
}
}
// create("dev") {
// // 复制buildTypes为release的配置
// initWith(getByName("release"))
//
// // 清占位符
// manifestPlaceholders["hostName"] = "com.dcxing.x.dev"
//
// // 包名加后缀
// applicationIdSuffix = ".dev"
// }
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
// 启用ViewBinding
viewBinding = true
// 默认不生成BuildConfig,修改如下即可
buildConfig = true
// 创建aidl文件,默认是置灰的
aidl = true
}
// 配置额外资源目录,便于管理资源,实现资源分包目的
sourceSets["main"].apply {
resDirs.forEach {
res.srcDirs("src/main/java/com/dcxing/draw/$it/res")
}
// 配置资源目录,在main目录下新建特性资源文件夹便于管理维护资源,实现资源分包目的
/*res.srcDirs(
"src/main/res",
"src/main/res_core",
"src/main/res_home"
)*/
}
// app风味,可打不不同渠道的apk
flavorDimensions.add("app")
productFlavors {
create("dev") {
dimension = "app"
// 指定资源
resourceConfigurations.add("en")
resourceConfigurations.add("xxxhdpi")
// buildConfigField("Boolean", "IS_DEBUG", "true")
// buildConfigField("String", "BASE_URL", "https://api.xxxserver.com")
}
create("version") {
dimension = "app"
// 引用base模块定义的flavorDimensions.add("base"),dev渠道配置
missingDimensionStrategy("base", "dev")
}
}
// 签名配置
signingConfigs {
create("dev") {
storeFile = File(Signing.devStoreFile)
// storeFile = file("../dev.jks")
storePassword = Signing.devStorePassword
// storePassword = System.getenv("KEY_ALIAS")
keyAlias = Signing.devKeyAlias
keyPassword = Signing.devKeyPassword
}
create("version") {
keyAlias = Signing.keyAlias
keyPassword = Signing.keyPassword
storeFile = File(Signing.storeFile)
storePassword = Signing.storePassword
}
}
// 禁用名称包含dev的task
// gradle.taskGraph.whenReady {
// tasks.forEach { task ->
// if (task.name.contains("dev")) {
// task.enabled = false
// }
// }
// }
// 打包时排除选项
// packagingOptions.resources.excludes.add("META-INF/LICENSE.txt")
// packagingOptions.resources.excludes.add("META-INF/LICENSE.txt")
// packagingOptions {
// resources {
// excludes += setOf("META-INF/LICENSE.txt", "META-INF/LICENSE.txt")
// }
// }
// 单元测试配置
// testOptions {
// unitTests {
// isIncludeAndroidResources = true
// }
// }
}
dependencies {
// 本地jar或aar依赖
implementation fileTree(includes: ['*.?ar'], dir: 'libs')
// 依赖本地库
implementation(project(":base"))
// 依赖远程库
implementation(Lib.core_ktx)
implementation(Lib.appcompat)
...
implementation(Lib.arouter) {
// 排除依赖包中的传递项,true or false
// isTransitive = false
// 排除依赖,可解决依赖冲突问题
// 可使用如下命令查看依赖树:./gradlew app:dependencies > dependencies.txt
exclude(group = "com.android.support", module = "support-v4")
}
// ksp 注解
ksp(Lib.arouter_compiler_lib)
...
}
// kts创建新任务,删除项目build目录
tasks.register("clean", Delete::class) {
delete(rootProject.buildDir)
}
dependencies小解
依赖项配置参数
- 默认情况下,Gradle会使用各模块中最高版本号依赖
1. 在同一模块下依赖不同版本,Gradle会选择版本号最高的一个
app模块 --依赖--> retrofit2(2.9.0) --依赖--> okhttp3(4.12.0)
app模块 --依赖--> glide(4.16.0) --依赖--> okhttp3(4.13.0)
app模块 --依赖--> okhttp3(4.12.0)
则最终app依赖的okhttp3版本为`4.13.0`
2. 在不同模块下依赖不同版本,Gradle会选择版本号最高的一个
app模块 --依赖--> retrofit2(2.9.0) --依赖--> okhttp3(4.12.0)
app模块 --依赖--> glide(4.16.0) --依赖--> okhttp3(4.13.0)
app模块 --依赖--> okhttp3(4.12.0)
app模块 --依赖--> network模块 --依赖--> okhttp3(4.14.0)
则最终app依赖的okhttp3版本为`4.14.0`
- 解决依赖冲突可使用
exclude排除依赖(只对当前依赖有效),以消除传递依赖的影响 - 可使用
strictly强制依赖版本,存在强制依赖时,若app和其他模块都有强制依赖,以app模块为准,但app强制依赖的版本不能大于模块强制依赖的版本
implementation 或 xxxImplementation(多渠道打包时使用)
- 此种方式添加依赖,在编译时不会将该模块的依赖泄露给其依赖者
- 具有隐藏依赖的效果,防止依赖传递,减少不必要的依赖检查和处理,提高编译速度和改善构建性能
- 此方式替代api依赖可缩短构建时间(减少了构建模块数,使用api依赖时关联此模块的其他模块也会参与编译)
A -> B -> C,则A不能引用C中代码
// 依赖jar or aar
implementation(files("libs/xxx.jar"))
implementation(fileTree(baseDir = "libs") { "*.jar" })
implementation(fileTree(baseDir = "libs") { "*.?ar" })
// 依赖module
// 需在setting.gradle.kts中声明 -> include(":app")
implementation(project(":base"))
// 依赖远程库,两种方式
// 1. implementation("com.google.code.gson:gson:2.10.1")
// 2. implementation(group = "com.google.code.gson", name = "gson", version = "2.10.1")
implementation(Lib.arouter) {
// 排除依赖
exclude(group = "com.android.support", module = "support-v4")
}
// 强制指定依赖版本,两种方式
implementation("com.google.code.gson:gson:2.10.1!!")
implementation(com.google.code.gson:gson) {
version {
strictly("2.10.1")
}
}
api
- 此种方式添加依赖,在编译时会将该模块的依赖不仅模块内部可用,依赖其的其他模块也可引用
- 使用api添加依赖会增加构建时间
A -> B -> C,则A可以直接引用C中代码
api(Lib.gson)
小结
- setting.gradle.kts负责配置和定义项目模块结构
- 项目build.gradle.kts负责管理插件,通过id和版本号指定插件包括plugins块
- 模块build.gradle.kts负责配置特定模块的构建配置,包括plugins块、android块、dependencies块