Gradle使用技巧(Android场景)
总览
本文围绕 “**配置 → 任务 → 动态化 → 依赖 → 本地库 → 资源 → 自动化**” 七大主题,把日常高频痛点一次讲透。
阅读方式:
先通读“思路”了解为什么;
再抄“最小可运行示例”快速验证;
最后看“延伸”拓展到多项目/组件化。
1 全局配置(Root Project)
目标:一次声明、所有子模块(application / library / test
)全部生效,避免每个 build.gradle
反复复制。
1.1 统一 UTF-8(编译期 + 控制台)
// root/gradle.properties
file.encoding=UTF-8
org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
org.gradle.console=rich // 彩色输出
// root/build.gradle.kts
allprojects {tasks.withType<JavaCompile>().configureEach {options.encoding = "UTF-8"}tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {kotlinOptions {jvmTarget = "17"// 统一 Kotlin 编码freeCompilerArgs += listOf("-Xjsr305=strict", "-Xemit-jvm-type-annotations")}}
}
1.2 依赖 Google/MavenCentral 仓库(一次声明)
// root/settings.gradle.kts
dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) // 强制收敛repositories {google()mavenCentral()// 公司私有仓库maven("https://nexus.xxx.com/repository/android-public/")}
}
1.3 支持 Groovy(混合遗留脚本)
// root/buildSrc/build.gradle.kts
plugins {`groovy-gradle-plugin` // 预编译 Groovy 脚本插件
}
把旧 Groovy 脚本放到 root/buildSrc/src/main/groovy
即可被 Kotlin 引用。
1.4 定义全局变量(版本号、SDK、编译参数)
推荐 **Version Catalogs**(Gradle 7.0+ 官方方案):
# root/gradle/libs.versions.toml
[versions]
compileSdk = "34"
minSdk = "24"
targetSdk = "34"
agp = "8.3.0"
kotlin = "1.9.20"
retrofit = "2.9.0"[libraries]
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }[bundles]
network = ["retrofit"]
任何模块:
android {compileSdk = libs.versions.compileSdk.get().toInt()
}
dependencies {implementation(libs.bundles.network)
}
旧项目可用
buildSrc/src/main/kotlin/Config.kt
单文件枚举,但维护成本高,不推荐。
1.5 配置 Lint(全局选项 + 自定义规则)
// root/build.gradle.kts
subprojects {afterEvaluate {extensions.findByType<com.android.build.api.dsl.CommonExtension<*, *, *, *, *>>()?.apply {lint {abortOnError = false //有lint错误也不停止构建checkReleaseBuilds = false //禁用在发布构建时进行lint检查disable += "InvalidPackage" // 忽略跨平台 RN 警告baseline = file("lint-baseline.xml") //lint检查的基准文件}}}
}
2 操控 Task(AGP 生成的标准任务)
所有 Android 任务继承自
Task
,名字/类型/顺序均可改。
2.1 更改输出 APK 名字(含版本、渠道、时间)
android.applicationVariants.all {val variant = thisvariant.outputs.all {val apkName = "App-${variant.flavorName}-${variant.buildType.name}-${variant.versionName}-${gitCommitShort()}.apk"(this as com.android.build.gradle.internal.api.BaseVariantOutputImpl).outputFileName = apkName}
}
gitCommitShort()
为自定义函数,返回当前 commit 前 7 位。
2.2 更改 AAR 输出目录(方便 CI 收集)
android.libraryVariants.all {val variant = thisvariant.packageLibraryProvider.configure {val dest = rootProject.layout.buildDirectory.dir("outputs/aar/${variant.name}")destinationDirectory.set(dest)}
}
2.3 跳过 AndroidTest(CI 加速)
android.libraryVariants.all {val variant = thisvariant.packageLibraryProvider.configure {val dest = rootProject.layout.buildDirectory.dir("outputs/aar/${variant.name}")destinationDirectory.set(dest)}
}
或在命令行:
./gradlew assembleDebug -x testDebugUnitTest -x connectedDebugAndroidTest
2.4 找出耗时的 Task(构建速度分析)
./gradlew assembleDebug --profile --scan
Gradle 会生成 build/reports/profile/...
火焰图;
或配置 buildSrc
插件:
gradle.taskGraph.afterTask {if (this is TaskExecutionListener) {val cost = endTime - startTimeif (cost > 1000) println("Slow task: $path took ${cost}ms")}
}
2.5 抽离 Task 脚本(可复用)
在
buildSrc/src/main/kotlin
建ApkRenamePlugin.kt
继承
Plugin<Project>
,内部注册 task;任何模块
plugins { id("apk-rename") }
即可。
3 动态化(Build-Time 黑科技)
3.1 动态设置 BuildConfig
android.defaultConfig {buildConfigField("String", "API_URL", "\"${findProperty("API_URL") ?: "https://api.example.com"}\"")buildConfigField("long", "BUILD_TIMESTAMP", "${System.currentTimeMillis()}L")
}
通过
gradle.properties
或 CI 环境变量注入,无需改代码。
3.2 填充 Manifest 占位符
android.defaultConfig {manifestPlaceholders["UMENG_CHANNEL"] = "default"
}
productFlavors {create("xiaomi") { manifestPlaceholders["UMENG_CHANNEL"] = "xiaomi" }
}
Manifest:
<meta-data android:name="UMENG_CHANNEL"android:value="${UMENG_CHANNEL}" />
3.3 让 buildType 支持继承(减少重复)
android.buildTypes {create("staging") {initWith(getByName("debug"))isDebuggable = falseapplicationIdSuffix = ".stg"}
}
3.4 让 Flavor 支持继承(使用 dimension
+ fallback
)
flavorDimensions += listOf("api")
productFlavors {create("api19") { dimension = "api" }create("api21") { dimension = "api" }create("free") { dimension = "tier" }create("paid") { dimension = "tier" }
}
android.variantFilter {if (flavors.any { it.name == "api19" } && flavors.any { it.name == "paid" }) {ignore = true // 屏蔽 api19+paid 组合}
}
3.5 内测版本用特定 Icon
sourceSets {getByName("debug") {res.srcDirs("src/debug/res")}
}
src/debug/res/mipmap-xxxhdpi/ic_launcher.png
放内测图标即可。
3.6 不同渠道不同包名
productFlavors {create("huawei") { applicationId = "com.xxx.huawei" }create("xiaomi") { applicationId = "com.xxx.xiaomi" }
}
3.7 自动填充版本信息(语义化 + 自增)
// buildSrc/src/main/kotlin/Versioning.kt
object Versioning {val major = 3val minor = 2val patch = gitCommitCount() // git rev-list --count HEADval versionName = "$major.$minor.$patch"val versionCode = major * 10000 + minor * 100 + patch
}
android.defaultConfig {versionCode = Versioning.versionCodeversionName = Versioning.versionName
}
4 远程依赖(Maven)
4.1 配置私有 Maven
repositories {maven {url = uri("https://nexus.xxx.com/repository/maven-releases/")credentials {username = findProperty("NEXUS_USER") as String? ?: System.getenv("NEXUS_USER")password = findProperty("NEXUS_PASS") as String? ?: System.getenv("NEXUS_PASS")}}
}
4.2 依赖相关 API 速查
配置名 | 含义 |
implementation | 编译 & 运行期都参与打包,但不传递 |
api | 编译 & 运行期都参与,且传递 |
compileOnly | 仅编译,不打包(如 Provided) |
runtimeOnly | 仅运行期 |
testImplementation | 单测 |
androidTestImplementation | 插桩测 |
4.3 组合依赖(Bundles)
见 1.4 Version Catalogs 的 bundles.network
。
4.4 依赖传递 & 禁用
implementation(libs.okhttp) {isTransitive = false // 关闭传递
}
4.5 动态版本号(慎用)
implementation("com.facebook.soloader:soLoader:0.10.+")
每次构建都可能变,CI 必须
--refresh-dependencies
才能复现,建议锁住版本。
4.6 强制版本号(统一 BOM)
// 先导入 BOM
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.12.0"))
// 再写依赖,无需版本
implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:logging-interceptor")
4.7 exclude 关键字(解决冲突)
implementation(libs.facebook.react) {exclude(group = "com.android.support", module = "support-annotations")
}
4.8 依赖管理(锁版本)
./gradlew dependencies --write-locks // 生成 gradle.lockfile
CI 开启:
// root/gradle.properties
dependency.verification=strict
5 本地依赖(非 Maven 网络)
5.1 引用 AAR(单文件)
把 xxx.aar
放到 libs/
目录:
dependencies {implementation(files("libs/xxx.aar"))
}
多 AAR 循环:
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
5.2 依赖 Module / Jar
implementation(project(":base-lib"))
implementation(files("libs/legacy.jar"))
5.3 自建本地 Maven 仓库(发布到目录)
// library/build.gradle.kts
plugins {`maven-publish`
}
publishing {repositories {maven {url = uri("${rootProject.projectDir}/repo")}}publications {create<MavenPublication>("release") {from(components["release"])groupId = "com.xxx"artifactId = "base-lib"version = "1.0.0"}}
}
其他工程:
repositories {maven(uri("${rootProject.projectDir}/repo"))
}
implementation("com.xxx:base-lib:1.0.0")
5.4 本地依赖 React Native(源码集成)
// settings.gradle.kts
include(":react-native")
project(":react-native").projectDir = file("../node_modules/react-native/android")
dependencies {implementation(project(":react-native"))
}
5.5 重新打包第三方 Jar(改名 / 移类 / shade)
// buildSrc 插件,使用 Shadow 插件
plugins {id("com.github.johnrengelman.shadow") version "8.1.1"
}
tasks.shadowJar {archiveClassifier.set("")relocate("com.google.gson", "com.xxx.shaded.gson")
}
6 资源管理(精简 / 白牌 / 多语言)
只打包指定语言:
android {resourceConfigurations += listOf("zh", "en") }
移除无用资源(与 ProGuard 联动):
buildTypes.getByName("release") {isShrinkResources = trueisMinifyEnabled = trueproguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") }
多 DPI 白牌:
productFlavors {create("lite") {ndk {abiFilters += listOf("armeabi-v7a")}} }
7 总结 & 常见问题速查
需求 | 一句话答案 |
自动 versionCode/versionName | 用 git commit count + 语义化脚本(见 3.7) |
强制统一某个库版本 | 用 BOM + |
管理签名 | 把 |
引入本地 Maven |
|
本地依赖写法 |
|
制作本地库 |
|
Exclude 冲突 |
|
两个库类冲突 | ① 用 |
8 附录:速查脚本(直接复制)
一键清理所有中间产物 + 重新生成:
./gradlew clean assembleDebug --refresh-dependencies --no-build-cache --no-configuration-cache
输出所有依赖到文件:
./gradlew :app:dependencies > deps.txt
查看构建扫描(需同意条款):
./gradlew assembleDebug --scan
至此,从“全局 UTF-8”到“动态版本号”到“本地 Maven”再到“依赖冲突”的完整链路全部覆盖。
把本文示例按需粘贴到你的项目,即可在 30 分钟内拥有“可维护、可追踪、可 CI”的 Gradle 工程骨架。祝编译极速、依赖清爽!
参考链接:
https://developer.android.com/build/gradle-build-overview?hl=zh-cn