Appearance
Gradle配置
基础配置
在工程项目中,Gradle 不仅承担构建任务,也负责:
- 依赖管理
- 构建变体
- 打包流程
- 版本控制
- CI/CD 集成
合理的 Gradle 配置能够降低维护成本,并提升项目的可扩展性与构建稳定性。
Git 版本信息管理
推荐引入 org.ajoberstar.grgit 《插件地址》插件,用于读取 Git 仓库信息。
例如:
- commit id
- tag
- 分支信息
- 版本描述
这些信息可用于:
- APK 命名
- 自动版本管理
- CI 打包
- 版本追踪
插件配置
kotlin
maven {
// jitpack仓库
setUrl("https://jitpack.io")
}groovy
maven {
// jitpack仓库
url 'https://jitpack.io'
}根据官方文档描述:
从 5.0.0 开始,Grgit 仅发布到 Maven Central 仓库,无需再配置 jitpack 仓库。
在项目根目录的 build.gradle 文件中引入插件,将以 5.0.0 版本作为示例。
kotlin
plugins {
// grgit插件
id("org.ajoberstar.grgit") version "5.0.0" apply false
}groovy
plugins {
// grgit插件
id 'org.ajoberstar.grgit' version '5.0.0' apply false
}Gradle 低版本兼容
Gradle 低版本适配
在 Grgit 4.1.1 以上版本是不支持 Gradle 7.0 以下版本的。
Gradle 7 以下项目,可使用:
groovy
buildscript {
repositories {
// 从 Maven 中央仓库获取插件和依赖
mavenCentral()
}
dependencies {
classpath 'org.ajoberstar.grgit:grgit-gradle:4.1.1'
}
}App 模块引用插件
在项目的 app 主模块的 build.gradle 文件,引用插件。
groovy
plugins {
id 'org.ajoberstar.grgit'
}版本信息配置
kotlin
/**
* 获取当前时间戳 -> 单位秒
*
* 版本号采用时间戳,每次打包不用操心更改版本号
*/
fun versionTimestamp(): Int {
return (System.currentTimeMillis() / 1000).toInt()
}
// 是否 debug
val isDebug = gradle.startParameter.taskNames.any { it.lowercase().contains("debug") }
// 获取 Git 提交短链 commit 值,此值可追踪源码
val gitAbbreviatedId: String = grgit.head().abbreviatedId
// 获取最新的 TAG 标识
val tags = grgit.tag.list().filter { it.commit == grgit.head() }
// 获取版本 TAG
var gitVersionTag: String? = if (tags.isNotEmpty()) tags.first().name else "snapshot"
// 获取当前分支名称
val gitBranchName = grgit.branch.current().name // 可以根据需要,替换文本 .replace("pre_main_", "")
// 最终版本名
val finalVersionName = run {
if (isDebug) {
"debug-base_on-$gitVersionTag-$gitAbbreviatedId"
} else {
gitVersionTag
}
}
android {
defaultConfig {
versionCode = versionTimestamp()
versionName = finalVersionName
}
}groovy
/**
* 获取当前时间戳 -> 单位秒
*
* <p> 版本号采用时间戳,每次打包不用操心更改版本号 </p>
*/
static def versionTimestamp() {
return (System.currentTimeMillis() / 1000) as int
}
// 是否 debug
def isDebug = gradle.startParameter.taskNames.any { it.toLowerCase().contains('debug') }
// 获取 Git 提交短链 commit 值,此值可追踪源码
def gitAbbreviatedId = grgit.head().abbreviatedId
// 获取 Git 版本描述信息
def gitVersionName = grgit.describe()
// 获取最新的 TAG 标识
def tags = grgit.tag.list().findAll { it.commit == grgit.head() }
// 获取版本TAG
def gitVersionTag = tags ? tags[0].name : (gitVersionName ?: "snapshot")
// 获取当前分支名称
def gitBranchName = grgit.branch.current().name // .replace("pre_main_", "")
// 最终版本名
def finalVersionName = {
if (isDebug) {
return "debug-base_on-$gitVersionTag-$gitAbbreviatedId"
} else {
return "$gitVersionTag"
}
}
android {
defaultConfig {
versionCode versionTimestamp()
versionName finalVersionName()
}
}签名配置
推荐统一管理应用签名配置,避免:
- 手动选择签名
- 密码输入错误
- 多环境配置混乱
1. 签名文件目录
在项目根目录创建一个 signatures 目录,把签名文件放进去。
signatures/
└──key.jks # 签名文件2. gradle.properties 配置
properties
# 应用签名配置
signFile=../signatures/key.jks
signAlias=签名别名
signPassword=签名密码
signKeyPassword=签名密钥密码3. build.gradle 配置
kotlin
android {
// 签名配置
signingConfigs {
create("release") {
storeFile = file(project.property("signFile") as String)
keyAlias = project.property("signAlias") as String
storePassword = project.property("signPassword") as String
keyPassword = project.property("signKeyPassword") as String
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}
}groovy
android {
// 签名配置
signingConfigs {
release {
storeFile file(project.property("signFile"))
storePassword project.property("signPassword")
keyAlias project.property("signAlias")
keyPassword project.property("signKeyPassword")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}多版本构建
通过 buildTypes 可以区分:
- debug
- trial
- release
等不同构建版本。
kotlin
android {
buildTypes {
// 开发版
debug {
isMinifyEnabled = false
signingConfig = signingConfigs.getByName("release")
}
// 体验版
create("trial") {
isMinifyEnabled = false
// 构建时匹配资源和依赖项,缺失配置时回退到 debug
matchingFallbacks.add("debug")
signingConfig = signingConfigs.getByName("release")
}
// 发布版
release {
isMinifyEnabled = false
signingConfig = signingConfigs.getByName("release")
// 混淆配置
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
}groovy
android {
buildTypes {
// 开发版
debug {
minifyEnabled false
signingConfig signingConfigs.release
}
// 体验版
trial {
minifyEnabled false
// 构建时匹配资源和依赖项,缺失配置时回退到 debug
matchingFallbacks = ['debug']
signingConfig signingConfigs.release
}
// 发布版
release {
minifyEnabled false
signingConfig signingConfigs.release
// 混淆配置
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}
}Product Flavor 变体配置
通过 productFlavors 可以构建:
- 免费版
- 付费版
- 渠道版
- 海外版
- 定制版
- 等...
Flavor 配置
kotlin
android {
// 添加一个维度
flavorDimensions.add("version")
productFlavors {
// 免费版变体
create("free") {
// 指定这个变体的维度
dimension = "version"
// 可指定不同的应用名称
resValue("string", "app_name", "MyApp Free")
}
// 付费版变体
create("paid") {
dimension = "version"
resValue("string", "app_name", "MyApp Paid")
}
}
}groovy
android {
// 添加一个维度
flavorDimensions 'version'
productFlavors {
// 免费版变体
free {
dimension 'version'
resValue 'string', 'app_name', 'MyApp Free'
}
// 付费版变体
paid {
dimension 'version'
resValue 'string', 'app_name', 'MyApp Paid'
}
}
}生成的变体组合
- freeDebug:免费版,调试版本
- freeTrial:免费版,体验版本
- freeRelease:免费版,发布版本
- paidDebug:付费版,调试版本
- paidTrial:付费版,体验版本
- paidRelease:付费版,发布版本
多维 Flavor
当项目复杂度较高时,可增加多个维度。
例如:
- version
- device
- market
- environment
- 等...
kotlin
android {
// 定义多个维度
flavorDimensions.add("version")
flavorDimensions.add("device")
productFlavors {
create("free") {
dimension = "version"
}
create("paid") {
dimension = "version"
}
// 手机设备版本变体
create("phone") {
dimension = "device"
resValue("string", "device_type", "Phone")
}
// 平板设备版本变体
create("tablet") {
dimension = "device"
resValue("string", "device_type", "Tablet")
}
}
}groovy
android {
// 定义多个维度
flavorDimensions 'version', 'device'
productFlavors {
free {
dimension 'version'
}
paid {
dimension 'version'
}
// 手机设备版本变体
phone {
dimension 'device'
resValue 'string', 'device_type', 'Phone'
}
// 平板设备版本变体
tablet {
dimension 'device'
resValue 'string', 'device_type', 'Tablet'
}
}
}生成的变体组合
- freePhoneDebug:免费版,手机设备,调试版本
- freePhoneTrial:免费版,手机设备,体验版本
- freePhoneRelease:免费版,手机设备,发布版本
- freeTabletDebug:免费版,平板设备,调试版本
- freeTabletTrial:免费版,平板设备,体验版本
- freeTabletRelease:免费版,平板设备,发布版本
- paidPhoneDebug:付费版,手机设备,调试版本
- paidTabletTrial:付费版,手机设备,体验版本
- paidPhoneRelease:付费版,手机设备,发布版本
- paidTabletDebug:付费版,平板设备,调试版本
- paidTabletTrial:付费版,平板设备,体验版本
- paidTabletRelease:付费版,平板设备,发布版本
APK 命名配置
推荐统一 APK 输出命名规则:变体名称_版本标识_打包标识_commit.apk
1. 定义打包标识
在 gradle.properties 配置文件中定义:
properties
# 打包标识
PACKAGE_KEY=app_name2. APK 输出配置
在 build.gradle 配置文件中定义:
kotlin
android {
// 配置 APK 的打包文件命名规则
applicationVariants.all {
outputs.map {
it as com.android.build.gradle.internal.api.ApkVariantOutputImpl
}.forEach { output ->
// 获取变体名称,可能包含 '-',去掉 '-' 符号改为 '_'
val variantName = output.name.replace("-", "_")
val appName = if (buildType.name == "release") {
// 只有在发布版的时候才拼接版本号 TAG 标识
"${variantName}_${gitVersionTag}_${project.property("PACKAGE_KEY")}_${gitAbbreviatedId}.apk"
} else {
"${variantName}_${gitBranchName}_${project.property("PACKAGE_KEY")}_${gitAbbreviatedId}.apk"
}
output.outputFileName = appName
}
}
}kotlin
android {
// 配置 APK 的打包文件命名规则
androidComponents.onVariants { variant ->
variant.outputs.forEach { output ->
// 获取变体名称,可能包含 '-',去掉 '-' 符号改为 '_'
val variantName = variant.name.replace("-", "_")
val appName = if (variant.buildType == "release") {
// 只有在发布版的时候才拼接版本号 TAG 标识
"${variantName}_${gitVersionTag}_${project.property("PACKAGE_KEY")}_${gitAbbreviatedId}.apk"
} else {
"${variantName}_${gitBranchName}_${project.property("PACKAGE_KEY")}_${gitAbbreviatedId}.apk"
}
output.outputFileName.set(appName)
}
}
}groovy
android {
// 配置 APK 的打包文件命名规则
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
if (output instanceof com.android.build.gradle.internal.api.ApkVariantOutputImpl) {
// 获取变体名称,可能包含 '-',去掉 '-' 符号改为 '_'
def variantName = output.name.replace('-', '_')
def appName
if (variant.buildType.name == "release") {
// 只有在发布版的时候才拼接版本号 TAG 标识
appName = "${variantName}_${gitVersionTag}_${project.property('PACKAGE_KEY')}_${gitAbbreviatedId}.apk"
} else {
appName = "${variantName}_${gitBranchName}_${project.property('PACKAGE_KEY')}_${gitAbbreviatedId}.apk"
}
output.outputFileName = appName
}
}
}
}依赖管理
⚠️ 谨慎引入大型依赖
在正式引用第三方库前,应评估:
- 方法数
- 包体积
- 初始化成本
- 维护活跃度
避免“为了一个小功能引入整个框架”。
统一版本管理
推荐使用:
libs.versions.toml统一管理依赖版本。
避免版本散落在多个模块中。
第三方依赖引用规范
引用一些第三方框架,必须注明框架的作用及出处,以便出现问题时能够快速升级、排查问题、风险评估。
示例:
groovy
dependencies {
// 图片加载框架
// 开源地址:https://github.com/bumptech/glide
// 官方文档:https://github.com/Muyangmin/glide-docs-cn
implementation(libs.glide)
// 数据库存储
// 开源地址: https://github.com/androidx/androidx/tree/androidx-main/room
// 官方文档: https://developer.android.com/jetpack/androidx/releases/room
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)
annotationProcessor(libs.androidx.room.compiler)
}总结
Gradle 配置的目标,不只是“能够成功构建”。
更重要的是随着项目规模扩大,Gradle 也应逐步演进、
最终形成稳定、可持续扩展的工程体系。