Android ButterKnife Android 35情况下 适配 Gradle 8.+

Google play 最新上线要求 必须适配 targetSdk 35 七八年的老项目噩梦开始了

老项目升级开始

....

文档地址(官方)
developer.android.google.cn/google/play...

Google 的要求实际上是"连环硬性升级":

markdown 复制代码
targetSdk 35
    ↓
AGP 8.0+
    ↓
Gradle 8.0+
    ↓
JDK 17+

意味着你无法再用 JDK8,也无法继续沿用旧的 Annotation Processor 黑魔法,包括 ButterKnife。


2️⃣ 原项目与升级目标

当前老项目环境

  • targetSdk:33
  • Gradle:7.3.1
  • Kotlin:1.9.20
  • JDK:8

Google Play 适配目标

  • targetSdk:35
  • Gradle:8.2.0
  • Kotlin:1.9.20
  • JDK:17

升级带来的所有问题都来自下面两个:

❌ JDK 从 8 → 17

❌ Gradle 7 → 8(DSL 改动很大)


3️⃣ 升级后必做的配置调整

下面是升级 target35 + Gradle8 后所有必须改的点。

🔵 1. 必须声明 namespace(否则直接 build error)

Gradle 8 强制要求 module 中显式设置 namespace:

arduino 复制代码
android {
    namespace 'com.xxx.yyy'
}

如果不写,直接报错:

vbnet 复制代码
The namespace not specified. Please specify a namespace in the module's build.gradle file.

🔵 2. 必须显式开启 BuildConfig(否则找不到 BuildConfig)

Gradle 8 默认关闭 BuildConfig 生成。

arduino 复制代码
buildFeatures {
    viewBinding true
    buildConfig true
}

否则会出现经典报错:

arduino 复制代码
error: cannot find symbol class BuildConfig

🔵 3. 必须使用 JDK17(且全局一致)

你可能遇到这样一种"精神分裂"错误:

kotlin 复制代码
Unsupported class file major version 61

或:

makefile 复制代码
java.lang.NoSuchFieldException: classFile

原因是:

IDE 设置 JDK17,但系统 PATH 是 JDK8 → Gradle 还是调用 JDK8 → 直接炸。

必须保证:

  • Android Studio Gradle JDK = 17
  • 系统环境 JAVA_HOME = 17
  • 命令行 java -version = 17

不然各种奇怪报错乱飞。


4️⃣ 最致命部分:ButterKnife 在 JDK17 下完全炸裂

ButterKnife 是基于 Javac 内部 API 的 annotationProcessor,

而 JDK9+ 开始把这些内部 API 封死,JDK17 更是完全锁死。

于是你会看到这个大杀器报错:

ini 复制代码
Invalid argument: --add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED

或者:

makefile 复制代码
java.lang.ClassNotFoundException: com.sun.tools.javac.tree.JCTree

或更常见的:

vbnet 复制代码
warning: unknown enum constant ElementType.MODULE
error: cannot access com.sun.tools.javac.tree.JCTree

这些都是 JDK17 和 ButterKnife 的天然冲突。


5️⃣ ButterKnife 在 Gradle 8 + JDK17 的最终可用修复方案

官方已经不维护,但还能"强行续命"。

你需要加:


🔸 1. 老版本(最后一个)ButterKnife

去掉 项目目录中 build.gradle中的

classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'

perl 复制代码
buildscript {
    dependencies {
        // classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
                }
        }

module 目录下保留

arduino 复制代码
implementation 'com.jakewharton:butterknife:10.2.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'

🔸 2. 必须关闭 nonFinalResIds

ButterKnife 编译依赖 final R.id.xxx

而 Gradle 8 默认是 non-final

强制设置: 在 gradle.properties 文件中添加

ini 复制代码
 nonFinalResIds = false

不然出现:

python 复制代码
error: id cannot be resolved or is not a field

🔸 3. 添加 Javac 打开模块的参数(核心 patch)

在模块 build.gradle 顶部/或尾部加入:

scss 复制代码
tasks.withType(JavaCompile).configureEach {
    options.fork = true
    options.forkOptions.jvmArgs += [            '--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED',            '--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED'    ]
}

这一段的意思就是:

强行撬开 JDK17 的封印,让 ButterKnife 能继续访问内部 API。


6️⃣ 实际出现的报错总结(可加到博客)

升级过程中出现这些错误很正常:

① JDK8/17 混用导致

kotlin 复制代码
Unsupported class file major version 61

② namespace 未声明

arduino 复制代码
The namespace not specified. Please specify a namespace...

③ BuildConfig 未生成

arduino 复制代码
cannot find symbol class BuildConfig

④ ButterKnife 访问 Javac 内部 API 失败

ini 复制代码
Invalid argument: --add-opens=jdk.compiler/...
go 复制代码
error: cannot access com.sun.tools.javac.tree.JCTree

R.id 变 non-final 导致 ButterKnife 编译失败

python 复制代码
id cannot be resolved or is not a field

7️⃣ 最终总结:老项目升级 target 35 的通关地图

要想在不迁移到 ViewBinding 的情况下继续保留 ButterKnife,一个可行方案是:

  • AGP 8 + JDK17 是强制升级
  • ButterKnife 虽然官方不维护,但仍可通过 add-opens 暴力续命
  • Gradle 配置必须补齐 namespace、BuildConfig、nonFinalResIds
  • 全局 JDK17 一致性非常关键
  • kotlin 版本 1.7.20

相关推荐
_李小白5 小时前
【Android FrameWork】延伸阅读:SurfaceFlinger线程
android
csdn12259873366 小时前
JetPack Compose 入门先搞清楚
android·compose·jetpack
liang_jy6 小时前
Android LaunchMode
android·面试
阿里云云原生7 小时前
Android App 崩溃排查实战:如何利用 RUM 完整数据与符号化技术定位问题?
android·阿里云·云原生·rum
过期动态8 小时前
JDBC高级篇:优化、封装与事务全流程指南
android·java·开发语言·数据库·python·mysql
没有了遇见10 小时前
Android 音乐播放器之MotionLayout实现View流畅变换
android
TheNextByte110 小时前
在 PC 和Android之间同步音乐的 4 种方法
android
君莫啸ོ11 小时前
Android基础-Activity属性 android:configChanges
android
TimeFine11 小时前
Android AI解放生产力(七):更丰富的AI运用前瞻
android
保持低旋律节奏11 小时前
linux——进程状态
android·linux·php