Skip to content

Commit

Permalink
fix(android): preserve new-arch classnames used in backwards-compat l…
Browse files Browse the repository at this point in the history
…ogic

We use dynamic class-loading via reflection to determine if we are in new
architecture mode or not and load the ReactContext

If we don't correctly preserve those names in minimization, we will crash
in a new architecture context on release builds as the class names will have
moved during the minimization
  • Loading branch information
mikehardy committed Nov 25, 2024
1 parent ae2953b commit 997b719
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 7 deletions.
10 changes: 9 additions & 1 deletion packages/react-native/android/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
-keep class io.invertase.notifee.NotifeeEventSubscriber
-keep class io.invertase.notifee.NotifeeInitProvider
-keepnames class com.facebook.react.ReactActivity
-keepnames class io.invertase.notifee.NotifeePackage
-keepnames class io.invertase.notifee.NotifeeApiModule

# We depend on certain classes to exist under their names for dynamic
# class-loading to work. We use this to handle new arch / old arch backwards
# compatibility despite the class names moving around
-keep class com.facebook.react.defaults.DefaultNewArchitectureEntryPoint { *; }
-keep class com.facebook.react.ReactApplication { *; }
-keep class com.facebook.react.ReactHost { *; }
-keep class * extends com.facebook.react.ReactHost { *; }
-keepnames class com.facebook.react.ReactActivity

# Preserve all annotations.
-keepattributes *Annotation*

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,30 +118,30 @@ static void promiseResolver(Promise promise, Exception e) {
Method bridgelessEnabled = entryPoint.getMethod("getBridgelessEnabled");
Object result = bridgelessEnabled.invoke(null);
if (result == Boolean.TRUE) {
Log.d("getReactContext", "We are in bridgeless new architecture mode");
Log.d("Notifee::getReactContext", "We are in bridgeless new architecture mode");
Object reactApplication = EventSubscriber.getContext();
Method getReactHost = reactApplication.getClass().getMethod("getReactHost");
Object reactHostInstance = getReactHost.invoke(reactApplication);
Method getCurrentReactContext =
reactHostInstance.getClass().getMethod("getCurrentReactContext");
return (ReactContext) getCurrentReactContext.invoke(reactHostInstance);
} else {
Log.d("getReactContext", "we are NOT in bridgeless new architecture mode");
Log.d("Notifee::getReactContext", "we are NOT in bridgeless new architecture mode");
}
} catch (Exception e) {
Log.d("getReactContext", "New Architecture class load failed. Using fallback.");
Log.d("Notifee::getReactContext", "New Architecture class load failed. Using fallback.");
}

Log.d("getReactContext", "Determining ReactContext using fallback method");
Log.d("Notifee::getReactContext", "Determining ReactContext using fallback method");
ReactNativeHost reactNativeHost =
((ReactApplication) EventSubscriber.getContext()).getReactNativeHost();
ReactInstanceManager reactInstanceManager = reactNativeHost.getReactInstanceManager();
return reactInstanceManager.getCurrentReactContext();
} catch (Exception e) {
Log.w("getReactContext", "ReactHost unexpectedly null", e);
Log.w("Notifee::getReactContext", "ReactHost unexpectedly null", e);
}

Log.w("getReactContext", "Unable to determine ReactContext");
Log.w("Notifee::getReactContext", "Unable to determine ReactContext");
return null;
}

Expand Down

0 comments on commit 997b719

Please sign in to comment.