Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native: sending events from android to javascript

there is documentation available on how to communicate from RN javascript parts with native parts in android and ios over the RN bridge. What is kind of unclear is the lifecycle for bridge communication.

(source medium)

I have a background service in android and need to send events to my RN application. This is how I send events from my android Service:

private RCTDeviceEventEmitter emitter() {
    return mReactContext.getJSModule(RCTDeviceEventEmitter.class);
}
private void pushPayload(String event, WritableMap payload) {
    emitter().emit(event, payload);
}
public void sendTimerEvent(long remaining) {
    WritableMap data = Arguments.createMap();
    data.putInt("remaining", (int) remaining);
    pushPayload("timeoutEvent", data);
}

On the javascript side, I use the following static code (not in a component, just code imported to my index.android.js file:

const subscribeForNativeEvents = (eventID, callback) => {
  const Emitter = Platform.OS === 'android' ? DeviceEventEmitter : NativeAppEventEmitter;
  Emitter.addListener(eventID, callback);
};

subscribeForNativeEvents('timeoutEvent', (event) => {
// work with event.remaining
});

My service runs even when the app is in the background. But I want to make sure that I only try to communicate with the javascript side when it is safe to do so.

I sometimes get errors such as React: Calling JS function after bridge has been destroyed. Is there a way to find out on the native (android) side wether the bridge is available or not?

This is not about how to keep background code alive but rather about to make sure that as long as my native (android) code is running, I can ensure that events are not lost.

like image 715
oliver Avatar asked Mar 21 '18 15:03

oliver


1 Answers

The issue occurs when the corresponding ReactContext/CatalystInstance has already been destroyed, and you are trying to do some JS stuff from native side (like sending events, doing callbacks etc).

I guess your best bet is to use lifecycle callbacks, i.e. onHostResume, onHostDestroy (https://facebook.github.io/react-native/docs/native-modules-android.html#listening-to-lifecycle-events) or use another callback onCatalystInstanceDestroy(https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeModule.java#L51)

Send events only when you know it is not destroyed.

The core idea is that usually the react context is bound to a given Activity/Context in your app, and you can know that lifecycle via callbacks in NativeModule.

You could find more details probably at (https://github.com/facebook/react-native/blob/b531612b2c917e1f2bd6bb37bf854fe51e658b36/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java#L104)

like image 136
jay shah Avatar answered Oct 20 '22 05:10

jay shah