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()
    }
}
相关推荐
用户091 小时前
MVI架构如何改变Android开发模式
android·面试·kotlin
梦终剧1 小时前
【Android之路】.sp和界面层次结构
android
2501_916008892 小时前
iOS 26 软件性能测试全流程,启动渲染资源压力对比与优化策略
android·macos·ios·小程序·uni-app·cocoa·iphone
zh_xuan2 小时前
Android Handler源码阅读
android
雪饼android之路2 小时前
【Android】 android suspend/resume总结(3)
android·linux
00后程序员张2 小时前
iOS 26 兼容测试实战,机型兼容、SwiftUI 兼容性改动
android·ios·小程序·uni-app·swiftui·cocoa·iphone
molong9313 小时前
Android 应用配置跳转微信小程序
android·微信小程序·小程序
2501_915106323 小时前
iOS 可分发是已经上架了吗?深入解析应用分发状态、ipa 文件上传、TestFlight 测试与 App Store 审核流程
android·ios·小程序·https·uni-app·iphone·webview
安东尼肉店11 小时前
Android compose屏幕适配终极解决方案
android
2501_9160074712 小时前
HTTPS 抓包乱码怎么办?原因剖析、排查步骤与实战工具对策(HTTPS 抓包乱码、gzipbrotli、TLS 解密、iOS 抓包)
android·ios·小程序·https·uni-app·iphone·webview