Gradle 设置全局镜像源

复制 init.gradle.kts 文件到 Windows 的 %USERPROFILE%/.gradle 或者 Linux 的 ~/.gradle 目录下。也可以直接复制文末的代码为 init.gradle.kts


Gradle 不支持镜像源的直接设置,只能通过 maven() 方法设置一个新的 Maven 仓库地址。

在 init.gradle 中调用 maven() 会导致镜像仓库排在上游仓库之后,会导致Gradle 优先使用上游仓库。如果直接删除上游仓库又会出现新的问题。Maven 镜像源和上游仓库并不是完全实时同步的,可能会缺失某些文件,特别是一些刚发布的包。所以上游仓库必须保留并且需要排在镜像仓库之后。

在使用过程中发现阿里云的 Maven 镜像源仍然会出现找不到文件的错误。排查之后发现阿里云镜像源的某个包竟然只有 POM 文件而没有 JAR 文件。在这种情况下 Gradle 找到了 POM 文件就会仅使用阿里云镜像源,然后找不到 JAR 文件报错,而不会继续使用上游仓库。查阅 Gradle 文档之后,发现有个 artifactUrls() 方法可以设置 Maven 仓库的除 POM 文件之外的其他文件下载地址。这样就可以通过在镜像仓库中将上游仓库地址设置为Artifact URL解决这个问题。

普通的 Java 或 Kotlin 项目默认是在 build.gradle 里设置 Maven 仓库地址,所以在 init.gradle 里需要在 allprojects 代码块中设置镜像源。而 Android 项目默认都是在 settings.gradle 的 pluginManagementdependencyResolutionManagement 代码块中设置 Maven 仓库地址。仅在 allprojects 中设置镜像源没有用。所以还需要在 settingsEvaluated 代码块中进行设置。

一些旧的项目在添加 Google Maven 仓库时,直接使用 maven("https://maven.google.com") 而不使用 google() 方法。构建项目时会一直卡在 Building 的状态,并且没有任何提示。maven.google.com 这个域名在国内是 ping 不通的。而如果使用 google() 方法,Gradle 会使用 https://dl.google.com/dl/android/maven2,这个链接在国内可以直连。所以需要将上游 Google 仓库的 "https://maven.google.com" 替换为 "https://dl.google.com/dl/android/maven2"。

解决一系列问题之后,最终的 init.gradle 完成了。Gradle 同时支持 Groovy DSL(.gradle) 和 Kotlin DSL(.gradle.kts)。我选择后者编写 init.gradle.kts。由于 Gradle 直接两种 DSL 语言的混用,所以如果之后构建 Groovy DSL 形式的 Gradle 项目,也不需要额外再编写 init.gradle。


kotlin 复制代码
// https://gist.github.com/mkckr0/97ec5b0d99feede4c19ee6f905d5e722

val repoMirrorMap = mapOf(
    "https://repo.maven.apache.org/maven2" to "https://maven.aliyun.com/repository/central",
    "https://dl.google.com/dl/android/maven2" to "https://maven.aliyun.com/repository/google",
    "https://plugins.gradle.org/m2" to "https://maven.aliyun.com/repository/gradle-plugin",
    "https://jcenter.bintray.com" to "https://maven.aliyun.com/repository/jcenter",
)
val repoReplaceMap = mapOf(
    "https://maven.google.com" to "https://dl.google.com/dl/android/maven2"
)

fun RepositoryHandler.setMirrors() {
    all {
        if (this is MavenArtifactRepository && !name.endsWith("Origin")) {
            val originName = name
            var originUrl = url.toString().trimEnd('/')

            // do replace
            repoReplaceMap[originUrl]?.let { newUrl ->
                originUrl = newUrl
                setUrl(originUrl)
            }

            // do mirror
            repoMirrorMap[originUrl]?.let { newUrl ->
                // replace into mirror repo
                setUrl(newUrl)
                // add origin repo to find missing jars
                artifactUrls(originUrl)
                // keep origin repo to find missing POM
                maven(originUrl) { name = "$originName Origin" }
            }
        }
    }
    printRepos()
}

fun RepositoryHandler.printRepos() {
    all {
        if (this is MavenArtifactRepository) {
            println("Maven Repo: name=\"$name\", url=$url, artifacts=${artifactUrls}")
        }
    }
}

settingsEvaluated {
    pluginManagement {
        repositories {
            setMirrors()
        }
    }
    dependencyResolutionManagement {
        @Suppress("UnstableApiUsage")
        repositories {
            setMirrors()
        }
    }
}

allprojects {
    buildscript {
        repositories {
            setMirrors()
        }
    }
    repositories {
        setMirrors()
    }
}
相关推荐
爱笑鱼3 小时前
JNI(二):Java 里的一个 long,为什么能找到 C++ 对象?
android
爱笑鱼3 小时前
JNI(一):nativePollOnce() 到底去了哪里?
android
hqk5 小时前
玩Android×AI Coding:从产品到代码,完整跑通一套 AI 软件研发工作流
android·ai编程·vibecoding
安卓修改大师6 小时前
安卓修改大师实战:深入解析Android主题Theme修改与沉浸式界面实现
android
齊家治國平天下7 小时前
CarService 深度解析 —— 基于 Android 14
android·车载系统·aaos·carservice·电源管理·android 14·vhal
stevenzqzq8 小时前
app性能日志工具
android
DB哥讲数据库8 小时前
【最新】MySQL9.7安装教程:图文详解(附MySQL安装包)
android·mysql·adb
IT乐手9 小时前
Android 写本地日志工具类
android·java
非典型Android程序员10 小时前
Launcher学习总结
android
Coffeeee10 小时前
Android功耗优化,哪些代码会让你的机子发热又耗电
android·架构·kotlin