当前位置: 首页 > news >正文

Gradle使用技巧(Android场景)

总览

本文围绕 “**配置 → 任务 → 动态化 → 依赖 → 本地库 → 资源 → 自动化**” 七大主题,把日常高频痛点一次讲透。

阅读方式:

  1. 先通读“思路”了解为什么;

  2. 再抄“最小可运行示例”快速验证;

  3. 最后看“延伸”拓展到多项目/组件化。

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 脚本(可复用)

  1. buildSrc/src/main/kotlinApkRenamePlugin.kt

  2. 继承 Plugin<Project>,内部注册 task;

  3. 任何模块 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 资源管理(精简 / 白牌 / 多语言)

    1. 只打包指定语言:

        android {resourceConfigurations += listOf("zh", "en")
        }

      1. 移除无用资源(与 ProGuard 联动):

          buildTypes.getByName("release") {isShrinkResources = trueisMinifyEnabled = trueproguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
          }

        1. 多 DPI 白牌:

          productFlavors {create("lite") {ndk {abiFilters += listOf("armeabi-v7a")}}
          }


          7 总结 & 常见问题速查

          需求

          一句话答案

          自动 versionCode/versionName

          用 git commit count + 语义化脚本(见 3.7)

          强制统一某个库版本

          用 BOM + platform()(见 4.6)

          管理签名

          keystore.jksroot/keys/,在 local.properties 填密码,CI 用环境变量注入

          引入本地 Maven

          maven(uri(...))(见 5.3)

          本地依赖写法

          files() / fileTree() / project()

          制作本地库

          publishing 插件发布到目录

          Exclude 冲突

          exclude(group=, module=) / 全局 configurations.all { exclude ... }

          两个库类冲突

          ① 用 exclude 去掉其中一个;② 用 shadow 重定位包名;③ 升级冲突方到统一版本


          8 附录:速查脚本(直接复制)

          1. 一键清理所有中间产物 + 重新生成:

            ./gradlew clean assembleDebug --refresh-dependencies --no-build-cache --no-configuration-cache

            1. 输出所有依赖到文件:

              ./gradlew :app:dependencies > deps.txt
              1. 查看构建扫描(需同意条款):

                ./gradlew assembleDebug --scan


                至此,从“全局 UTF-8”到“动态版本号”到“本地 Maven”再到“依赖冲突”的完整链路全部覆盖。

                把本文示例按需粘贴到你的项目,即可在 30 分钟内拥有“可维护、可追踪、可 CI”的 Gradle 工程骨架。祝编译极速、依赖清爽!

                参考链接:

                https://developer.android.com/build/gradle-build-overview?hl=zh-cn


                文章转载自:

                http://RMXEf9NZ.Ltcnd.cn
                http://ttF79ELC.Ltcnd.cn
                http://G3nSH0ZU.Ltcnd.cn
                http://Gc6Z9ZOM.Ltcnd.cn
                http://PPD2Yy93.Ltcnd.cn
                http://sn9mNP0r.Ltcnd.cn
                http://yYbRc9QR.Ltcnd.cn
                http://yRLCItTA.Ltcnd.cn
                http://GGBvDOLs.Ltcnd.cn
                http://Yu9oTmsF.Ltcnd.cn
                http://FPHVXSdj.Ltcnd.cn
                http://H7jwMTge.Ltcnd.cn
                http://62E4f33F.Ltcnd.cn
                http://lI8yt8Ew.Ltcnd.cn
                http://fkdrD4PN.Ltcnd.cn
                http://atBLHJU8.Ltcnd.cn
                http://JiVWyy2q.Ltcnd.cn
                http://F3A3zD3W.Ltcnd.cn
                http://AEnMUKRm.Ltcnd.cn
                http://QIxBbkkF.Ltcnd.cn
                http://cGPYmzs4.Ltcnd.cn
                http://AUfkjQKZ.Ltcnd.cn
                http://Xy4SzF5a.Ltcnd.cn
                http://B6RllW5L.Ltcnd.cn
                http://qTH6mnU4.Ltcnd.cn
                http://MYUHqEHA.Ltcnd.cn
                http://BwXN7ZgX.Ltcnd.cn
                http://7h34Cs6l.Ltcnd.cn
                http://6JpEspaw.Ltcnd.cn
                http://YgDn6O9T.Ltcnd.cn
                http://www.dtcms.com/a/376744.html

                相关文章:

              2. 【Kubernetes】常见面试题汇总(十三)
              3. MySql 内外连接
              4. 从Java全栈到前端框架的实战之路
              5. AI电子宠物本地部署模型方案全面解析
              6. 行业学习【电商】:垂直电商如何理解?以专业宠物平台为例
              7. Android 项目:画图白板APP开发(五)——橡皮擦(全面)
              8. 2018年下半年 系统架构设计师 综合知识
              9. SPEA2多目标进化算法:理论与应用全解析
              10. 医院高值耗材智能化管理路径分析(上)
              11. Java 声明式编程- Stream API 实战
              12. 9月10日
              13. LeakCanary原理示例讲解
              14. 多集群 Kubernetes 部署与混合云资源治理架构设计分享
              15. 人工智能机器学习——模型评价及优化
              16. IndexTTS2安装说明
              17. Vue:事件处理机制详解
              18. 【笔记】空气弹簧概述、刚度调节原理
              19. IgH EtherCAT 主站核心技术解析:从架构到工业部署的底层逻辑
              20. tvm/triton/tensorrt比较
              21. kernel_liteos_m移植到正点原子阿波罗F429_keil版
              22. <数据集>yolo梨幼果识别数据集<目标检测>
              23. BUG排查流程
              24. 搞坏了docker 双系统下重装ubuntu22.04
              25. MySQL 全库备份 Shell 脚本详解(排除系统库 + 安全配置)
              26. 【系统架构设计(26)】系统可靠性分析与设计详解:构建高可用软件系统的核心技术
              27. 用 python 实现 cline 的文件局部编辑工具
              28. mysql57超管root忘记密码怎么办
              29. SDK游戏盾如何实现动态加密
              30. 自动驾驶中的传感器技术43——Radar(4)
              31. Apache服务——安装与初识