文章目录
前言开发环境问题描述问题分析1. 适配Java 212. 适配AGP 8.0 解决方案补充内容最后
前言
Android Studio版本从Koala Feature Drop
升级到Ladybug
,出现了一系列报错。
开发环境
Flutter: 3.24.3Android Studio: 2024.2.1 Patch 1Java: 21.0.3Gradle: 7.4Android Gradle Plugin (AGP): 7.3.1问题描述
升级Android Studio版本后,Flutter项目运行到Android设备出现报错,截取部分日志如下:
Execution failed for task ':gradle:compileGroovy'.> BUG! exception in phase 'semantic analysis' in source unit '/xxx/flutter/packages/flutter_tools/gradle/src/main/groovy/app_plugin_loader.groovy' Unsupported class file major version 65[!] Your project's Gradle version is incompatible with the Java version that Flutter is usingfor Gradle. If you recently upgraded Android Studio, consult the migration guide at https://flutter.dev/to/to/java-gradle-incompatibility.
问题分析
日志中Flutter提供了迁移指南,迁移指南中是升级AGP的版本到7.3~7.6.1
之间。可是现在项目的AGP版本是符合要求的,这说明这个迁移指南的内容过时了。那怎么办呢?
首先这个问题是升级Android Studio版本导致的,这让我想起一年多前的一个问题类似的问题:Android问题记录 - Unable to make field private final java.lang.String java.io.File.path accessible(持续更新)。倒不是我记性好,而是这篇文章我一直在持续更新。
先看看是不是Android Studio升级了Java版本,这是Koala Feature Drop
版本的:
这是Ladybug
版本的:
很明显Java版本从17升到了21,接下来开始尝试适配。
1. 适配Java 21
根据Gradle的兼容性要求:
Java 21版本在Gradle 8.5才开始支持,而当前项目的Gradle版本是7.4
,看来问题的原因找到了,是Android Gradle版本和Java版本不兼容
。
现在开始尝试升级版本解决问题,首先将Gradle版本升级到8.5
,打开Android项目下的gradle/wrapper/gradle-wrapper.properties
文件修改版本:
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
重新运行项目,还是报错:
> Cannot use @TaskAction annotation on method IncrementalTransformTask.transform() because interface org.gradle.api.tasks.incremental.IncrementalTaskInputs is not a valid parameter to an action method.
看来导致这问题的原因不止一个,Android Gradle插件版本和Java版本不兼容
很可能也是其中一个。在这个类似问题中,AGP为了兼容Java 17版本升级到了7.0+
,那这次估计要升级到8.0+
。
打开Android项目下的settings.gradle
文件,先升级到8.0
试试:
id "com.android.application" version "8.0.0" apply false
还是报错,截取部分日志:
> Could not resolve all files for configuration ':xxx:androidJdkImage'. > Failed to transform core-for-system-modules.jar to match attributes {artifactType=_internal_android_jdk_image, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}.
一直升级到8.3
版本才不继续报错。刚好,如果继续升级到8.4
版本,那Gradle版本又要升级了,因为AGP 8.4最低要求Gradle 8.6。
id "com.android.application" version "8.3.0" apply false
如果你还在用旧语法,请参考这样修改:
classpath 'com.android.tools.build:gradle:8.3.0'
到这还没解决全部报错,AGP进行了大版本升级,还需要继续适配。
2. 适配AGP 8.0
以下报错适配只是我遇到的,也许你还遇到了其他的,建议自行查看AGP 8.0的版本说明:Android Gradle Plugin 8.0.0。
当然,你也可以尝试使用AGP Upgrade Assistant完成迁移,只是不太好用,在后续补充内容中有介绍。
BuildConfig
,但是从AGP 8.0开始,默认不生成BuildConfig
,所以需要手动开启 > Product Flavor 'xxx' contains custom BuildConfig fields, but the feature is disabled. To enable the feature, add the following to your module-level build.gradle: `android.buildFeatures.buildConfig true`或者类似这样的报错:/xxx/xxx.java:20: 错误: 找不到符号import com.example.application.BuildConfig;又或者这样的报错:/xxx/MainActivity.kt: (315, 16): Unresolved reference: BuildConfig
按照错误中的提示,在app/build.gradle
中增加以下内容:
android.buildFeatures.buildConfig true
当然,你也可以增加这样的:
android { buildFeatures { buildConfig = true }}
需要在构建脚本中指定命名空间,其实就是将AndroidManifest.xml
中的命名空间迁移到这里 > Could not create an instance of type com.android.build.api.variant.impl.ApplicationVariantImpl. > Namespace not specified. Specify a namespace in the module's build file. See https://d.android.com/r/tools/upgrade-assistant/set-namespace for information about setting the namespace. If you've specified the package attribute in the source AndroidManifest.xml, you can use the AGP Upgrade Assistant to migrate to the namespace value in the build file. Refer to https://d.android.com/r/tools/upgrade-assistant/agp-upgrade-assistant for general information about using the AGP Upgrade Assistant.
在app/build.gradle
中指定命名空间:
android { namespace = "com.example.application"}
同时移除AndroidManifest.xml
文件中过时的package="com.example.application"
。
完成以上操作后,你还是可能会遇到这个报错,但是请仔细看看,那应该是其他子项目(模块)的报错,可以在Android项目根目录下的build.gradle
中增加以下内容解决:
subprojects { afterEvaluate { project -> if (project.plugins.hasPlugin("com.android.application") || project.plugins.hasPlugin("com.android.library")) { if (project.android.namespace == null || project.android.namespace.isEmpty()) { project.android.namespace = project.group println "INFO: Set namespace for ${project.name} to ${project.group}" } } }}
需要升级NDK版本(2024/10/27更新) Your project is configured with Android NDK 25.0.8775105, but the following plugin(s) depend on a different Android NDK version:- xxx requires Android NDK 25.1.8937393...Fix this issue by using the highest Android NDK version (they are backward compatible).Add the following to /xxx/android/app/build.gradle: android { ndkVersion = "25.1.8937393" ... }
这是一个警告提示,不处理也还能构建运行。根据提示升级NDK版本也很简单,但是为什么会有这样的提示?
很明显,是因为项目的NDK版本和库所要求的版本不一致,但是困惑可能更多了。有些人的项目都没指定NDK版本,提示中项目配置的NDK版本哪来的?提示中列出的插件库好像并没有用到NDK,为什么这些库会要求某个NDK版本呢??
以下是个人经验分析总结,希望能帮你理清这些困惑,仅供参考:
首先,如果一个项目(库)不指定NDK版本,那么要求的NDK版本默认就是AGP版本对应的默认NDK版本。每个AGP版本都有一个默认NDK版本,注意不是最低版本,是经过彻底测试的最兼容版本。参考官方文档:
以下是AGP版本和NDK版本的关系:
最后更新日期:2024/10/27
Android Gradle Plugin version | Minimum required NDK version | Default NDK version |
---|---|---|
8.7 | N/A | 27.0.12077973 |
8.6 | N/A | 26.1.10909125 |
8.5 | N/A | 26.1.10909125 |
8.4 | N/A | 26.1.10909125 |
8.3 | N/A | 25.1.8937393 |
8.2 | N/A | 25.1.8937393 |
8.1 | N/A | 25.1.8937393 |
8.0 | N/A | 25.1.8937393 |
7.4 | N/A | 23.1.7779620 |
7.3 | N/A | 23.1.7779620 |
7.2 | N/A | 21.4.7075529 |
7.1 | N/A | 21.4.7075529 |
7.0 | N/A | 21.4.7075529 |
其次,如果库的AGP版本和项目的不一致,那么会以项目的AGP版本为主。这就是为什么警告提示中库要求的NDK版本都一样,有指定NDK版本的库除外。
前面因为适配Java 21,将项目的AGP版本升到了8.3
,对应的默认NDK版本是25.1.8937393
。由于AGP版本以项目为主,如果库没指定NDK版本,25.1.8937393
版本就是库所要求的NDK版本。
又因为项目中的NDK版本指定的是25.0.8775105
,这就导致NDK版本不一致从而出现警告提示。
验证以上内容是否正确很简单,将项目的AGP版本升到8.4
,Gradle版本升到8.6
,这时你会发现警告提示变成这样:
Your project is configured with Android NDK 25.0.8775105, but the following plugin(s) depend on a different Android NDK version:- xxx requires Android NDK 26.1.10909125...Fix this issue by using the highest Android NDK version (they are backward compatible).Add the following to /xxx/android/app/build.gradle: android { ndkVersion = "26.1.10909125" ... }
当然,不是每次版本不一致都会出现这个警告提示,当项目的NDK版本高于库所要求的版本时不会出现,其实警告提示中已经建议你给项目设置所要求的最高NDK版本:
Fix this issue by using the highest Android NDK version (they are backward compatible).
如此也可以推断,如果库的NDK版本和项目的不一致,那么会以项目的NDK版本为主。由于NDK版本是向后兼容的,所以只要项目的NDK版本高于库的NDK版本,那么兼容性就没什么大问题。
那NDK版本越高越好吗?当然不!最好将NDK版本设置成AGP版本对应的默认版本(兼容性最好),换句话说,好像就不应该设置,因为不设置就是使用默认版本。可要是有些库指定了更高版本的NDK怎么办?像这样的警告提示:
Your project is configured with Android NDK 25.1.8937393, but the following plugin(s) depend on a different Android NDK version:- xxx requires Android NDK 26.1.10909125...Fix this issue by using the highest Android NDK version (they are backward compatible).Add the following to /xxx/android/app/build.gradle: android { ndkVersion = "26.1.10909125" ... }
最快的解决办法还是直接设置更高版本的NDK,但是从长远的角度看,库都开始要求更高版本的NDK了,你是不是也该考虑将AGP版本升一升,升到默认NDK版本满足要求达到更好的兼容性。
最后一个疑问,为什么项目用低版本的NDK也能构建运行,只给出警告提示?
首先AGP本身对NDK就没有最低版本要求(全是N/A
),只给了默认版本(推荐版本)。其次Android平台设备多而杂,遗留的老项目老第三方库也很多,如果要求最低版本,那适配就麻烦了。
个人感觉,不要求最低版本,兼容性和灵活性更强。在此提醒一下:如果你升级了NDK版本请记得好好测测,万一有些老项目不兼容呢?不行就保持原样,又不是强制要求升级,能用、够用、又好用才是真的好!
解决方案
完成以下操作解决问题:
升级Gradle版本修改Android项目下的gradle/wrapper/gradle-wrapper.properties
文件,版本至少升级到8.5
:
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
升级AGP版本 修改Android项目下的settings.gradle
文件,版本至少升级到8.3
:
id "com.android.application" version "8.3.0" apply false
如果你还在用旧语法,请参考这样修改:
classpath 'com.android.tools.build:gradle:8.3.0'
适配AGP 8.0 请参考前面问题分析中的适配AGP 8.0
内容。
补充内容
AGP Upgrade Assistant这是官方提供的升级助手,点击Android Studio菜单栏的[Tools] -> [AGP Upgrade Assistant]唤起。从7.3.1
升级到8.0.0
是这样的:
点击Run selected steps
完成迁移,迁移完成后还可以撤销迁移。是不是感觉好像还不错?这里有一个问题,如果你的项目没能被识别为Android项目(例如卡在Gradle sync now
报错),点击升级助手是没反应的,Android Studio的日志是这么说的:
Unable to obtain application's Android Project
这就难受了,项目需要通过AGP升级助手迁移完成后才能识别为Android项目,但是使用升级助手的前提是能被识别为Android项目,所以这升级助手最好提前用提前迁移。至于以上迁移截图是通过新建Android测试项目得到的。
Kotlin / Kotlin Gradle Plugin(KGP)版本需不需要升级通常不需要。具体版本兼容要求请看:兼容性说明。
2024/12/05更新:以上兼容性说明指向的是Gradle内部使用的Kotlin版本(Embedded Kotlin version),它与项目中配置的Kotlin / KGP版本无关。对于项目中的Kotlin / KGP版本是否需要升级,请看这篇文章:Android问题记录 - Inconsistent JVM-target compatibility detected for tasks。
Could not find com.otaliastudios:transcoder:0.9.1由于JCenter
的弃用,transcoder库迁移到了Maven
,需要将版本升级到0.10.0
及以上。这个报错和当前问题没什么关系,只是遇到了顺便记录。
问题可能出在Gradle JDK设置还指向Java 21,可以尝试删除新版本的Android Studio,只保留降级后的版本解决该问题。
最后
如果这篇文章对你有所帮助,点赞?收藏?支持一下吧,谢谢~
本篇文章由@crasowas发布于CSDN。