Skip to content

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 以下版本的。

《Grgit版本发行说明》

《Grgit文档站点》

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_name

2. 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 也应逐步演进、

最终形成稳定、可持续扩展的工程体系。

基于 MIT 许可发布