一、遇到的问题

新建Android项目开发过程中,咱们经常gradle项目装备的问题

  1. 打一个开源库房或者自建项目,同步项目时分获取不到依靠库,或者下载依靠库的时分非常缓慢
  2. 不知道项目中(AGP)android gradle plugin版别、gradle版别、Android Studio版别联系,同步一段时间后失利。
  3. koltin版别和Android Studio的联系
  4. 用到Jetpack Compose的时分,Compose Compiler与koltin版别对应的联系

二、原因及处理方案

问题一原因与处理

原因

  1. 很多库服务器在国外,经过国内网络拜访慢甚至拜访不到
  2. 项目装备的AGP和Gradle版别不匹配,及AndroidStudio版别不匹配

处理办法,相信咱们都知道,要么经过手动替换项目中的库房地址为阿里云(库房服务 (aliyun.com)),要么换一个能拜访国外服务器的网络。

但是,能不能有更好的办法。

  • 我不必换网络,也不必每次手动替换库房服务器。
  • 还能支撑一键切换回原有的库房地址。

最近参考了一些他人的处理办法,然后优化了一下。这种办法是:

在电脑的用户环境.gradle文件夹下增加库房替代的装备文件init.gradle,比如可以在 C:\Users\Administrator.gradle\init.gradle 文件中定义大局的 Gradle 装备,在 Android Studio 中翻开工程时,Gradle 会主动加载 init.gradle 文件,并将其应用到所有的项目中。然后为了能动态操控是否运用init.gradle文件装备,咱们可以在 init.gradle 中依据项目的 gradle.properties 文件中的装备来决定是否履行一些操作。

需求留意的是,在 init.gradle 履行之前,Gradle 会先加载项目的 gradle.properties 文件,并将其存储在 project 目标中,因此咱们可以在 init.gradle 中运用 project.findProperty() 办法来获取这些特点的值。

我的 init.gradle文件内容:

// 处理已知库房类型信息,或许有不知道的
static String InfoOfArtifact(ArtifactRepository artifact) {
    if (artifact instanceof MavenArtifactRepository) {
        return "[name] = $artifact.name, [type] = MavenArtifactRepository, [url]=${artifact.url}"
    } else if (artifact instanceof IvyArtifactRepository) {
        return "[name] = $artifact.name, [type] = IvyArtifactRepository, [url]=${artifact.url}"
    } else {
        return "[name] = $artifact.name, not handle [type] = ${artifact.class.simpleName}"
    }
}
gradle.projectsLoaded {
    // 默认开启,可以默认封闭,再在项目的gradle.properties中装备enabled_aliyun_repo
    def enable_ali = true
    def find_aliyun = rootProject.findProperty('enabled_aliyun_repo')
    def find_property = false
    //找到阿里云特点
    if (find_aliyun != null) {
        find_property = true
        enable_ali = find_aliyun.toBoolean()
    }
    if (find_property) {
        println("[$rootProject.name] Find gradle property and [enabled_aliyun_repo=$enable_ali]")
    } else {
        println("[$rootProject.name] Not find gradle property but defualt use [enabled_aliyun_repo=$enable_ali]")
    }
    if (enable_ali) {
        def CENTRAL_ALI = "https://maven.aliyun.com/repository/central"
        def CENTRAL_ORIGIN = "https://repo1.maven.org/maven2/"
        def PUBLIC_ALI = "https://maven.aliyun.com/repository/public"//central仓和jcenter仓的聚合仓
        def JCENTER_ORIGIN = "https://jcenter.bintray.com/"
        def GOOGLE_ALI = "https://maven.aliyun.com/repository/google"
        def GOOGLE_ORIGIN_1 = "https://maven.google.com/" //google源
        def GOOGLE_ORIGIN_2 = "https://dl.google.com/dl/android/maven2/" //google源
        def GRADLE_PLUGIN_ALI = "https://maven.aliyun.com/repository"//
        def GRADLE_PLUGIN_ORIGIN = "https://plugins.gradle.org/m2/" //gradle plugins
        rootProject.allprojects {
            def currentProject_name = project.name
            rootProject.logger.lifecycle "> Custom Configure Repository :${currentProject_name}"
            repositories {
                def prefix = "[ repositories{} closure ]"
                rootProject.logger.lifecycle "for ${prefix}"
                all { ArtifactRepository repo ->
                    rootProject.logger.lifecycle "find artifact repo ${InfoOfArtifact(repo)}"
                    if (repo instanceof MavenArtifactRepository) {
                        def url = repo.url.toString()
                        if (url.startsWith(GOOGLE_ORIGIN_2) || url.startsWith(GOOGLE_ORIGIN_1)) {
                            rootProject.logger.lifecycle "\tRepository ${repo.url} replaced by $GOOGLE_ALI."
                            remove repo
                        } else if (url.startsWith(CENTRAL_ORIGIN)) {
                            rootProject.logger.lifecycle "\tRepository ${repo.url} replaced by $CENTRAL_ALI."
                            remove repo
                        } else if (url.startsWith(GRADLE_PLUGIN_ORIGIN)) {
                            rootProject.logger.lifecycle "\tRepository ${repo.url} replaced by $GRADLE_PLUGIN_ALI."
                            remove repo
                        } else if (url.startsWith(JCENTER_ORIGIN)) {
                            rootProject.logger.lifecycle "\tRepository ${repo.url} replaced by $PUBLIC_ALI."
                            remove repo
                        }
                    }
                    println()
                }
                google { url GOOGLE_ALI }
                maven { url PUBLIC_ALI }
                maven { url CENTRAL_ALI }
            }
            def prefix = "[ buildscript{} closure ]"
            rootProject.logger.lifecycle "for ${prefix}"
            buildscript {
                repositories {
                    all { ArtifactRepository repo ->
                        rootProject.logger.lifecycle "find artifact repo ${InfoOfArtifact(repo)}"
                        if (repo instanceof MavenArtifactRepository) {
                            def url = repo.url.toString()
                            if (url.startsWith(GOOGLE_ORIGIN_2) || url.startsWith(GOOGLE_ORIGIN_1)) {
                                rootProject.logger.lifecycle "\tRepository ${prefix} ${repo.url} replaced by $GOOGLE_ALI."
                                remove repo
                            } else if (url.startsWith(CENTRAL_ORIGIN)) {
                                rootProject.logger.lifecycle "\tRepository ${prefix} ${repo.url} replaced by $CENTRAL_ALI."
                                remove repo
                            } else if (url.startsWith(GRADLE_PLUGIN_ORIGIN)) {
                                rootProject.logger.lifecycle "\tRepository ${prefix} ${repo.url} replaced by $GRADLE_PLUGIN_ALI."
                                remove repo
                            } else if (url.startsWith(JCENTER_ORIGIN)) {
                                rootProject.logger.lifecycle "\tRepository ${prefix} ${repo.url} replaced by $PUBLIC_ALI."
                                remove repo
                            }
                        }
                        println()
                    }
                    google { url GOOGLE_ALI }
                    maven { url PUBLIC_ALI }
                    maven { url CENTRAL_ALI }
                }
            }
            println()
        }
    }
}

然后可以保持项目什么都不需求改,我默认设置是收效上面的装备,可以自行更改。其次可以在项目的gradle.properties中增加特点操控装备收效或封闭

enabled_aliyun_repo=true

问题二处理

如果AGP版别、Gradle版别、Android Studio版别联系没有调配好,或许也导致项目编译不经过。

AGP版别是指在项目根目录的build.gradle中的版别,如classpath 'com.android.tools.build:gradle:7.0.2' 代表运用7.0.2的版别

Gradle版别指的是gradle wrapper目录下的gradle-wrapper.properties中的特点如distributionUrl=https://services.gradle.org/distributions/gradle-7.0.2-all.zip代表gradle wrapper的版别为7.0.2

这两个的匹配联系有个表格,还有一些版别改动说明,官方地址是:gradle与gradle plugin匹配联系 此外还有关于AGP与JDK11的适用联系说明

AGP插件版别 所需最低Gradle版别
8.1 8.0
8.0 8.0
7.4 7.5
7.3 7.4
7.2 7.3.3
7.1 7.2
7.0 7.0
4.2.0+ 6.7.1

Android Studio与AGP插件版别联系

为你理清Android项目Gradle配置,解决常见编译问题

问题三解惑

通常情况下咱们的AS各个版别都有一个内置的kotlin版别插件(一般在IDE的偏好面板中找到settings > plugin > kotlin),这使得咱们可以运用kotlin编写代码。

  • 这些版别或许有所不同,按道理讲是可以手动升级或降级内置Kotlin 插件版别,而不受 Android Studio 版别限制(现在尝试失利)。
  • 一般情况下项目中build.gradle中设置的kotlin插件版别只需低于内置的kolin插件版别,或版别大号相同(如kotlin 1.6.0与1.6.20),一般都能兼容编译。高于内置或许会有提示或编译不经过。

问题四解惑

Jetpack compose或许是个好东西,不过由于配件比较多,版别多,或许第一次开始运用会有些利诱。官方给了一个联系图。

  • Compose 与 Kotlin 的兼容性对应联系
  • Compose Compiler & Kotlin versions
  • 此外,由于配件和版别斑驳,官方现在还有经过bom办法集成,不需求针对每个库分别指定版别号,由于 BOM 将主动管理这些依靠项之间的版别兼容性。
  • 最好也需求知道与kotlin版别兼容联系便利扫除编译问题。 比如在Maven库查看Compose Bom所管理的依靠项版别 compose-bom:2023.04.00-alpha02 里面的POM文件指定了依靠项的版别。然后与项目设定的kotlin版别相联系,看是否兼容。

三、 总结

  1. 低入侵办法供给了一种可随意将项目库房切换阿里库房的办法
  2. 说明AGP、Gradle、AS、Kotlin、Jectpack Compose之间的联系,供给了一些它们之间版别对应的联系资料.
  3. 欢迎交流。