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

您所在的位置:网站首页 如何获取低版本shsh 为你理清Android项目Gradle配置,解决常见编译问题

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

2023-04-25 01:13| 来源: 网络整理| 查看: 265

一、遇到的问题

新建Android项目开发过程中,我们经常gradle项目配置的问题

打一个开源仓库或者自建项目,同步项目时候获取不到依赖库,或者下载依赖库的时候非常缓慢 不知道项目中(AGP)android gradle plugin版本、gradle版本、Android Studio版本关系,同步一段时间后失败。 koltin版本和Android Studio的关系 用到Jetpack Compose的时候,Compose Compiler与koltin版本对应的关系 二、原因及解决方案 问题一原因与解决

原因

很多库服务器在国外,通过国内网络访问慢甚至访问不到 项目配置的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 复制代码

额外注意的是高版本如Android Studio Flamingo将新建工程,默认的仓库地址设置放在了settings.gradle文件下,需要小改一下RepositoriesMode模式,注释掉或改下模式。

pluginManagement { repositories { google() mavenCentral() gradlePluginPortal() } } dependencyResolutionManagement { //RepositoriesMode,包含三个取值: //1. PREFER_PROJECT:表示优先使用当前项目中指定的仓库。 //2. PREFER_SETTINGS:表示优先使用在 Gradle 设置文件 (settings.gradle) 中指定的仓库。 //3. FAIL_ON_PROJECT_REPOS:表示只使用明确声明的仓库,不允许使用当前项目的仓库。 // 这个枚举类型被标记为 @Incubating,表示这是一个孵化阶段的功能,在将来版本中可能会有所变化。 // repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } } rootProject.name = "My Application" include ':app' 复制代码 问题二解决

如果AGP版本、Gradle版本、Android Studio版本关系没有搭配好,可能也导致项目编译不通过。

AGP版本是指在项目根目录的build.gradle中的版本,如classpath 'com.android.tools.build:gradle:4.2.0' 代表AGP使用4.2.0的版本,需要注意的是:

高版本AS中,不再需要在 build.gradle 文件中添加上面的声明,因为插件已经默认预装在 Android Studio 中。在“File”->“Project Structure”->“Android Gradle Plugin Version”显示的版本是当前 Android Studio 预装的 Gradle 插件版本.

也可以手动更改版本,在 build.gradle或settings.gradle中加上dependencies { classpath "com.android.tools.build:gradle:4.2.0" }

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

这两个的匹配关系有个表格,还有一些版本改动说明:

官方地址是:gradle与Android gradle plugin匹配关系 此外还有关于AGP与JDK11的适用关系说明

下面是一些AGP插件版本与Gradle版本的关系

AGP插件版本所需最低Gradle版本8.18.08.08.07.47.57.37.47.27.3.37.17.27.07.04.2.0+6.7.1

Android Studio与AGP插件版本关系

image.png

问题三解惑

通常情况下我们的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版本相联系,看是否兼容。 三、 总结 低入侵方式提供了一种可随意将项目仓库切换阿里仓库的方法 说明AGP、Gradle、AS、Kotlin、Jectpack Compose之间的关系,提供了一些它们之间版本对应的关系资料. 欢迎交流。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3