After shipping v2.1.0 of Beautiful HD Wallpapers on Android, Firebase Crashlytics started filling up with a peculiar error:
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/function/Supplier;
Every crash was coming from Android 6.0.1 devices. Nothing on Android 9 or newer. My first instinct was "old devices, nothing we can do" — but the real cause was something fixable in about two minutes.
Rork Max generates code that relies on Glide 5.x, AGP 9.x, and other modern libraries that use Java 8 APIs internally. Devices running Android 8.0 (API 26) and below can't handle those APIs natively without a process called desugaring. Without it, a segment of your users simply can't open the app.
This is what that fix looks like in practice.
Why "Only Old OS Versions" Crash
Android's Java API support varies by version. Classes like Stream, Optional, and Supplier — added in Java 8 — are only natively available on Android 8.0 (API 26) and above.
Rork Max targets modern Android environments, so the generated code and its dependencies freely use these Java 8 APIs. On older devices, the JVM can't resolve these classes at runtime, causing an immediate crash on launch.
In the 28 days after the v2.0.0 release, 50+ NoClassDefFoundError reports piled up and the Crash-free users rate slid to 99.4%. Not catastrophic on paper, but enough to drag Play Store ratings down if left alone — and none of it reproduced on my own test devices.
Knowing which classes sit right on the boundary makes the stack trace readable at a glance:
| API | Native support | How it usually sneaks in |
|---|---|---|
java.util.function.Supplier / Consumer | API 24+ | Glide 5.x internals |
java.util.stream.Stream | API 24+ | Utility libraries |
java.util.Optional | API 24+ | Parts of the Firebase SDK |
java.time.* (LocalDate etc.) | API 26+ | Hand-rolled date handling |
java.nio.file.* | Not covered by default | Generated file I/O code |
If the class after Failed resolution of: appears in that table, this is a missing build setting — not a broken device.
Step 1: Pinpoint the Crash in Firebase Crashlytics
Open the Crashlytics dashboard and look at the Issues tab. Click into the NoClassDefFoundError issue and check the "Session details" for device OS distribution.
If you see a clear pattern — "mostly Android 6.x, 7.x, 8.x" — the Java 8 desugaring problem is almost certainly your culprit.
Signals that point to desugaring issues:
- OS version: concentrated below Android 8.0 (API 26)
- Error type: NoClassDefFoundError, ClassNotFoundException
- Library involvement: Glide, Firebase SDK, OkHttp in the stack trace
For Rork Max projects, navigate to android/app/build.gradle after ejecting from the Expo managed workflow.
Step 2: Add Desugaring to app/build.gradle
Open android/app/build.gradle. You'll likely already see this:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}Setting sourceCompatibility to VERSION_1_8 tells the compiler to accept Java 8 syntax — but it does not make Java 8 runtime APIs available on older devices. That requires explicitly enabling core library desugaring:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
// Enable desugaring for Android 8.0 (API 26) and below
coreLibraryDesugaringEnabled true
}
}
dependencies {
// Add the desugaring library
coreLibraryDesugaring 'com.android.tools.desugar_jdk_libs:2.0.4'
// ... existing dependencies
}After adding these two lines and rebuilding, the crashes on Android 6.0.1 vanished entirely. We shipped this fix in v2.1.0 before the Play Store's staged rollout reached 25%, which kept our ratings from taking a hit.
Step 3: How to Ask Rork's AI to Apply This Fix
When asking Rork to make this change, give it the exact file, the exact lines, and the exact error from Crashlytics. Vague requests like "fix the crash" tend to trigger broader rewrites you don't want.
[Prompt for Rork]
In android/app/build.gradle, please:
1. Add coreLibraryDesugaringEnabled true inside compileOptions
2. Add this to the dependencies block:
coreLibraryDesugaring 'com.android.tools.desugar_jdk_libs:2.0.4'
Firebase Crashlytics is reporting this error on Android 8.0 and below:
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/function/Supplier;
Do not modify any other files.
The "do not modify any other files" instruction is worth adding. Rork's AI is helpful but sometimes broadens its scope when you leave the boundary open.
Two Cases Where Desugaring Alone Did Not Fix It
Twice the crashes survived the fix. Both times the cause sat outside compileOptions.
R8 shrinking. With minifyEnabled true, the desugared classes were obfuscated and reflective lookups stopped resolving. Desugared classes land under a j$ prefix, so any keep rule written against java.* misses them entirely.
-keep class j$.util.** { *; }
-keep class j$.time.** { *; }
-dontwarn java.lang.invoke.**Stale build cache. The build right after the change reused old dex output, so the crash reproduced on a build that should have been fixed. Always force a clean rebuild after touching desugaring:
cd android && ./gradlew clean
./gradlew assembleRelease --rerun-tasksRaising minSdkVersion is the other option, and it is tempting. Check the Android version distribution in Google Play Console first — as an indie developer shipping wallpaper apps, devices below API 24 were 1.8% of my base, which made one build setting a far better trade than cutting them loose.
Step 4: Watch for AGP and Glide Version Combinations
AGP 9.x paired with Glide 5.0.x is a particularly common trigger for this problem. If you're using AGP 9.x, make sure desugar_jdk_libs is at version 2.0.4 or later — older versions miss some Java 8 APIs.
// android/build.gradle (project-level)
// When using AGP 9.x, specify a recent desugar_jdk_libs
dependencies {
coreLibraryDesugaring 'com.android.tools.desugar_jdk_libs:2.0.4'
}If you're using Glide's Kotlin-based API or Coroutines integration, these also pull in Java 8 types. The desugaring setting covers all of them once enabled.
Start with Crashlytics
If your Rork Max Android app is crashing after release, the first move is checking Crashlytics for OS version distribution. An "under Android 8.0" pattern combined with NoClassDefFoundError is the clearest possible signal.
coreLibraryDesugaringEnabled true plus the desugar_jdk_libs dependency is a two-line fix that unblocks your entire pre-Android-8 user base.
For anyone managing multiple apps with a staged rollout strategy: monitor Crash-free users against the 99.7% threshold before expanding each rollout phase. Catching this class of bug at 5% rollout is far less damaging than finding it at 100%.
Setting up Firebase Crashlytics in your Rork Max project is the right first step.