新建Android项目开发过程中,我们经常gradle项目配置的问题
原因
解决办法,相信大家都知道,要么通过手动替换项目中的仓库地址为阿里云(仓库服务 (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.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插件版本关系
通常情况下我们的AS各个版本都有一个内置的kotlin版本插件(一般在IDE的偏好面板中找到settings > plugin > kotlin
),这使得我们能够使用kotlin编写代码。
Jetpack compose可能是个好东西,不过由于配件比较多,版本多,可能第一次开始使用会有些迷惑。官方给了一个关系图。
- Compose 与 Kotlin 的兼容性对应关系
- Compose Compiler & Kotlin versions