我想作为一个Android开发者,应该对JDK和Gradle有一定的了解。但是,有时,还是会被jdk和gradle的版本所坑到。今天我们就来聊聊这个话题。
我们先来看看JDK和Gradle版本的对应关系。为什么是Gradle去适配JDK?我想不用多说,先有JDK,而后有Gradle,Gradle作为构建脚本,肯定是基于JDK的。
| JDK版本 | 支持该JDK的最低Gradle版本 |
|---|---|
| 8 | 2.0 |
| 9 | 4.3 |
| 10 | 4.7 |
| 11 | 5.0 |
| 12 | 5.4 |
| 13 | 6.0 |
| 14 | 6.3 |
| 15 | 6.7 |
| 16 | 7.0 |
| 17 | 7.3 |
| 18 | 7.5 |
| 19 | 7.6 |
| 20 | 8.1 |
然后我们就确定了Gradle版本,确定了Gradle版本,我们再使用对应的kotlin插件版本,需要注意的是,这里仅是kotlin插件的版本,和kotlin语言的版本并非完全一一对应。我们通常关注的是kotlin插件的版本,很少去关注kotlin语言的版本。
| Gradle版本 | kotlin插件版本 | kotlin语言版本 |
|---|---|---|
| 5.0 | 1.3.10 | 1.3 |
| 5.1 | 1.3.11 | 1.3 |
| 5.2 | 1.3.20 | 1.3 |
| 5.3 | 1.3.21 | 1.3 |
| 5.5 | 1.3.31 | 1.3 |
| 5.6 | 1.3.41 | 1.3 |
| 6.0 | 1.3.50 | 1.3 |
| 6.1 | 1.3.61 | 1.3 |
| 6.3 | 1.3.70 | 1.3 |
| 6.4 | 1.3.71 | 1.3 |
| 6.5 | 1.3.72 | 1.3 |
| 6.8 | 1.4.20 | 1.3 |
| 7.0 | 1.4.31 | 1.4 |
| 7.2 | 1.5.21 | 1.4 |
| 7.3 | 1.5.31 | 1.4 |
| 7.5 | 1.6.21 | 1.4 |
| 7.6 | 1.7.10 | 1.4 |
| 8.0 | 1.8.10 | 1.8 |
| 8.2 | 1.8.20 | 1.8 |
我不知道为什么kotlin插件的开发者对版本号的尾数0和1这么热衷,有谁来告诉我?难道是为了敬畏0和1吗?
我们来举几个🌰(栗子)
例子1: 这是一个很明显的Gradle编译错误。
Class 'kotlin.Unit' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.7.1, expected version is 1.5.1.
解决方案: 按照要求升级kotlin插件版本从1.5.1到1.7.1,即可解决。比如我给它升级到1.7.10。
ext.kotlin_version = '1.7.10'
例子2: 另外也是一个升级kotlin插件版本的编译错误,发生在Gradle8.x。
Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.
解决方案: 在settings.gradle.kts加入以下代码。
pluginManagement {
resolutionStrategy {
if (requested.id.namespace == "org.jetbrains.kotlin") {
def kotlin_version = "1.8.10"
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
}
}
}
并在app模块的build.gradle.kts加入以下代码。
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.10")
例子3: 如果项目比较古老,也可能发生这个编译错误。
A problem was found with the configuration of task ':app:createReleaseApkListingFileRedirect' (type 'ListingFileRedirectTask').
- In plugin 'com.android.internal.version-check' type 'com.android.build.gradle.internal.tasks.ListingFileRedirectTask' property 'listingFile' specifies file '/Users/dora/Desktop/DoraSample/app/release/output-metadata.json' which doesn't exist.
解决方案: 去掉以下代码,使用新的gradle生成apk文件名规则的配置。
android.applicationVariants.all {
variant ->
if (variant.buildType.name == "release") {
variant.getPackageApplication().outputDirectory = new File(project.rootDir
.absolutePath + "/apk/")
variant.outputs.all {
outputFileName = "doramusic_${defaultConfig.versionName}_${defaultConfig.versionCode}.apk"
}
}
}
例子4:
JDK从8升到11,报以下编译错误
Unable to load class 'javax.xml.bind.JAXBException'.
解决方案:
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
}
例子5:
'compileAlphaDebugJavaWithJavac' task (current target is 11) and 'kaptGenerateStubsAlphaDebugKotlin' task (current target is 19) jvm target compatibility should be set to the same Java version.
解决方案:
compileOptions {
sourceCompatibility(JavaVersion.VERSION_19)
targetCompatibility(JavaVersion.VERSION_19)
}
总结
编译环境导致的问题远不止这些,所以说Gradle的坑很多。所以就导致很多的初学者,被这样的坑所劝退。但我想告诉大家,其实Gradle的坑并不可怕,可怕的是你并不知道要去看官方文档。我这里强烈推荐使用kts编写gradle的编译脚本。这样做的好处是有代码提示,而且方便我们研究相关类。我们可以研究它的一些Scope类以及与编译相关的配置类,这样有助于我们更好地驾驭Gradle脚本,让Android编译畅通无阻。掌握好Gradle,同时也可以让我们在编译的时候做更多事情,让我们的构建过程更加灵活和自动化。最后祝你好运,再也不担心Gradle的坑!另外附上官方文档地址,docs.gradle.org/current/use… ,有空一定记得去看。