diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index bdffdf261..e8793d241 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -19,6 +19,7 @@ import android.app.Application; import android.content.Intent; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.bridge.NativeModuleCallExceptionHandler; import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContext; @@ -159,6 +160,7 @@ public abstract class ReactInstanceManager { protected boolean mUseDeveloperSupport; protected @Nullable LifecycleState mInitialLifecycleState; protected @Nullable UIImplementationProvider mUIImplementationProvider; + protected @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; protected Builder() { } @@ -242,6 +244,16 @@ public abstract class ReactInstanceManager { return this; } + /** + * Set the exception handler for all native module calls. If not set, the default + * {@link DevSupportManager} will be used, which shows a redbox in dev mode and rethrows + * (crashes the app) in prod mode. + */ + public Builder setNativeModuleCallExceptionHandler(NativeModuleCallExceptionHandler handler) { + mNativeModuleCallExceptionHandler = handler; + return this; + } + /** * Instantiates a new {@link ReactInstanceManagerImpl}. * Before calling {@code build}, the following must be called: @@ -274,7 +286,8 @@ public abstract class ReactInstanceManager { mUseDeveloperSupport, mBridgeIdleDebugListener, Assertions.assertNotNull(mInitialLifecycleState, "Initial lifecycle state was not set"), - mUIImplementationProvider); + mUIImplementationProvider, + mNativeModuleCallExceptionHandler); } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java index 7953691c0..e0ce3c97e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java @@ -35,6 +35,7 @@ import com.facebook.react.bridge.JavaScriptExecutor; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.JavaScriptModulesConfig; import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.NativeModuleCallExceptionHandler; import com.facebook.react.bridge.NativeModuleRegistry; import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener; import com.facebook.react.bridge.ProxyJavaScriptExecutor; @@ -100,6 +101,7 @@ import com.facebook.systrace.Systrace; private volatile boolean mHasStartedCreatingInitialContext = false; private final UIImplementationProvider mUIImplementationProvider; private final MemoryPressureRouter mMemoryPressureRouter; + private final @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler; private final ReactInstanceDevCommandsHandler mDevInterface = new ReactInstanceDevCommandsHandler() { @@ -195,7 +197,8 @@ import com.facebook.systrace.Systrace; boolean useDeveloperSupport, @Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener, LifecycleState initialLifecycleState, - UIImplementationProvider uiImplementationProvider) { + UIImplementationProvider uiImplementationProvider, + NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) { initializeSoLoaderIfNecessary(applicationContext); mApplicationContext = applicationContext; @@ -216,6 +219,7 @@ import com.facebook.systrace.Systrace; mLifecycleState = initialLifecycleState; mUIImplementationProvider = uiImplementationProvider; mMemoryPressureRouter = new MemoryPressureRouter(applicationContext); + mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler; } @Override @@ -652,13 +656,16 @@ import com.facebook.systrace.Systrace; Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } + NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null + ? mNativeModuleCallExceptionHandler + : mDevSupportManager; CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder() .setCatalystQueueConfigurationSpec(CatalystQueueConfigurationSpec.createDefault()) .setJSExecutor(jsExecutor) .setRegistry(nativeModuleRegistry) .setJSModulesConfig(javaScriptModulesConfig) .setJSBundleLoader(jsBundleLoader) - .setNativeModuleCallExceptionHandler(mDevSupportManager); + .setNativeModuleCallExceptionHandler(exceptionHandler); Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstance"); CatalystInstance catalystInstance;