How to Upgrade Legacy Android Projects to Target SDK 35 with Gradle 8 and JDK 17

Upgrading an old Android project to meet Google Play's new targetSdk 35 requirement involves moving to AGP 8, Gradle 8, and JDK 17, updating namespace, enabling BuildConfig, fixing non‑final resource IDs, and applying JVM arguments to keep ButterKnife functional despite its deprecation.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
How to Upgrade Legacy Android Projects to Target SDK 35 with Gradle 8 and JDK 17

Background

Google Play now mandates that new app submissions target targetSdk 35. For projects that have been using targetSdk 33, JDK 8, and Gradle 7.x for many years, this creates a cascade of mandatory upgrades: AGP 8+, Gradle 8+, and JDK 17+.

image.png
image.png

Current (old) project configuration

targetSdk : 33

Gradle : 7.3.1

Kotlin : 1.9.20

JDK : 8

Target configuration for Google Play

targetSdk : 35

Gradle : 8.2.0

Kotlin : 1.9.20

JDK : 17

Key upgrade pain points

❌ JDK 8 → 17

Gradle 8 and AGP 8 require JDK 17. Continuing to use JDK 8 leads to compilation failures such as Unsupported class file major version 61 or NoSuchFieldException: classFile. All Java toolchains, IDE settings, JAVA_HOME, and command‑line java -version must report JDK 17.

❌ Gradle 7 → 8 (DSL changes)

Gradle 8 introduces breaking DSL changes, notably the mandatory namespace declaration and the default disabling of BuildConfig generation.

Required configuration adjustments after upgrade

🔵 1. Declare namespace

android {
    namespace 'com.xxx.yyy'
}

If omitted, the build fails with

The namespace not specified. Please specify a namespace in the module's build.gradle file.

🔵 2. Enable BuildConfig generation

buildFeatures {
    viewBinding true
    buildConfig true
}

Without this, you encounter error: cannot find symbol class BuildConfig.

🔵 3. Use JDK 17 consistently

Android Studio →

Gradle JDK = 17
JAVA_HOME

environment variable set to JDK 17

Command line java -version returns 17

🔵 4. Disable nonFinalResIds

ButterKnife expects final R.id.xxx, but Gradle 8 makes resource IDs non‑final by default. Add the following line to gradle.properties:

nonFinalResIds = false

🔵 5. Add JVM arguments to open internal JDK modules (core ButterKnife patch)

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'
    ]
}

This forces JDK 17 to expose internal compiler APIs so ButterKnife can continue to operate.

ButterKnife specific steps

🔸 1. Keep the last released ButterKnife version

Remove the ButterKnife Gradle plugin from the root build.gradle:

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

In each module, keep the library and annotation processor dependencies:

implementation 'com.jakewharton:butterknife:10.2.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'

🔸 2. Ensure resource IDs are final

Set nonFinalResIds = false in gradle.properties to avoid errors like error: id cannot be resolved or is not a field.

🔸 3. Apply the add-opens JVM arguments shown above

This resolves errors such as

Invalid argument: --add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED

and cannot access com.sun.tools.javac.tree.JCTree.

Common error summary (useful for debugging)

JDK8/17 mix‑up : Unsupported class file major version 61 Missing namespace : The namespace not specified... BuildConfig missing : cannot find symbol class BuildConfig ButterKnife internal API access : Invalid argument: --add-opens=… or cannot access com.sun.tools.javac.tree.JCTree Non‑final R.id :

error: id cannot be resolved or is not a field

Final checklist for migrating an old Android project to targetSdk 35

Upgrade AGP to 8.x and set JDK 17 globally.

Upgrade Gradle to 8.x and declare namespace in every module.

Enable buildConfig true in buildFeatures.

Set nonFinalResIds = false in gradle.properties.

Add the required --add-opens JVM arguments to the JavaCompile task.

Keep ButterKnife 10.2.3 dependencies and remove the deprecated Gradle plugin.

Verify that Kotlin version is at least 1.7.20.

AndroidGradleButterKnifeJDK17AGP8targetSdk35
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.