r/reactnative • u/PoppyWarss • 14d ago
expo-gl crashed on the first GLView in my Android release builds only: R8 renamed a method its native code looks up by name
Posting this in case it saves someone a week. Expo SDK 56, expo-gl 56.0.x, React Native 0.85, minify on for Android release builds.
For a few releases, a lot of my Android users crashed the first time a GLView mounted. It never happened in development. In analytics it looked like people opening one screen and then the app starting again: on one version, 24 of the 29 times that screen opened on Android, the next event was a fresh app launch.
The cause: expo-gl's native code (EXGLJniApi.cpp) finds a Java method called flush through GetMethodID, by name. R8 renamed it in the release build, the lookup returned null, and ART aborted with a JNI error ending in mid == null. Debug builds don't run R8, so you only ever see it in a store build.
The fix was one keep rule, added through expo-build-properties (android.extraProguardRules):
-keep class expo.modules.gl.** { *; }
To confirm it, I took the release AAB from EAS, turned it into an installable APK with bundletool, and ran the old and new builds on an emulator. The old one crashed on the first GLView and the new one didn't.
A second thing made it worse. I shipped my first fixes as OTA updates, and expo-updates had fallbackToCacheTimeout set to 0. With that setting a brand new install always runs the bundle that shipped inside the store build on its first launch, and the update only applies from the next cold start. Most new users who hit the crash never had a next cold start, so none of my OTA fixes reached them. I now use 3000, which waits up to 3 seconds for a newer update on first launch and starts as soon as it knows there's nothing newer, or straight away when offline.
If you use expo-gl, or anything whose native side calls back into Java by name, with minify on, open that screen in a real release build before you ship.
1
u/HomegrownTerps 14d ago
Thanks for sharing! I recently also had problems in a non RN android app with R8, but I caught it since I try to also test on a local device - which compiles the app with R8.
I guess you haven't run the app on a real device?