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()
    }
}
相关推荐
还鮟1 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡2 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi003 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil4 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你4 小时前
Android View的绘制原理详解
android
移动开发者1号7 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号7 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best12 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk12 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭17 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin