3

I am new to React Native but would like to know if it is possible to call React Native JavaScript method from Java? I have a niche device that has a physical button that I would like to use to trigger a method when pressed.

I have seen the following plugin https://github.com/artemyarulin/react-native-eval but the Android implementation appears to be out of date.

I have googled around but all the examples I can find reference calling Java methods from React Native not the other way around.

Many thanks in advance.

EDIT

I have tried to implement a solution using the method suggested by @ide below. Here's my attempt so far:

In my MainActivity I have:

private String latestBarcode = "";

...

public String getLastestBarcode() {
  return this.latestBarcode;
}

public void setLatestBarcode(String barcode) {
  this.latestBarcode = barcode;
}

@Override
public void onBarcodeEvent(final BarcodeReadEvent event) {
  runOnUiThread(new Runnable(){
    @Override
    public void run() {
      String barcodeData = event.getBarcodeData();
      String tstp = event.getTimestamp();
      setLatestBarcode(barcodeData);
      Log.d("MainActivity", " TEST - barcodeData "+ barcodeData + " tstp : "+ tstp);
    }
  });
}
...

This code gets a barcode value from the device when a user presses the physical hardware button.

In my custom React Native module

@ReactMethod
public void latestBarcode(Callback callback) {
  final Activity activity = getCurrentActivity();

  if(activity != null && activity instanceof MainActivity){
    callback.invoke(((MainActivity) activity).getLastestBarcode());
  }
  else {
    callback.invoke("");
  }
}

This method takes the value and exposes it to React Native. This works I can read the value but I need to trigger a method when the user presses the button so here is my React Native module as it stands now in all its entirety:

import android.app.Activity;
import android.util.Log;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;

import javax.annotation.Nullable;

// Import MainActivity
import com.myapp.MainActivity;

public class HoneywellCT50Module extends ReactContextBaseJavaModule {
  private ReactContext reactContext;

  public HoneywellCT50Module(ReactApplicationContext reactContext) {
    super(reactContext);
    this.reactContext = reactContext;
  }


  @ReactMethod
  public void latestBarcode(Callback callback) {
    final Activity activity = getCurrentActivity();

    if(activity != null && activity instanceof MainActivity){
      WritableMap params = Arguments.createMap(); // <--- Added WritableMap
      sendEvent("BarcodeRecieved", params); // <--- Added sendEvent

      callback.invoke(((MainActivity) activity).getLastestBarcode());
    }
    else {
      callback.invoke("");
    }
  }

  // Added sendEvent
  private void sendEvent(
    String eventName,
    @Nullable WritableMap params
  ) {
    this.reactContext
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(eventName, params);
  }


  @Override
  public String getName() {
    return "HoneywellCT50";
  }
}

In React Native:

// I import DeviceEventEmitter
import { DeviceEventEmitter } from 'react-native'

componentDidMount () {
  // Listen for Honeywell Scans
  DeviceEventEmitter.addListener('BarcodeRecieved', this.getBarcodeValue)
}

// I want to trigger this method
getBarcodeValue () {
  console.log('Event Received')
  // This gets the barcode value, works ok
  HoneywellCT50.latestBarcode((value) => {
    this.setState({ barcode: value })
  })
}

With the above code I can build the project with no Java/build errors and I see no JS errors but I cannot trigger the event. Can anyone help point me in the right direction from here?

2 Answers 2

3

What you want to do is emit an event from Java that is sent to JavaScript. You'd write a custom native module, subscribe to its events from JavaScript, and then in your native code you'd emit the event. See this guide: http://facebook.github.io/react-native/docs/native-modules-android.html#sending-events-to-javascript

Sign up to request clarification or add additional context in comments.

2 Comments

@ide I have tried to implement a solution based on your answer and I've added the code above. Do you have any suggestions as to where I'm going wrong?
Sending events from Java to JavaScript seems gone in the docs for the latest RN versions (at least 44 and 45)
2

Ok, so I got some code working. I'm not sure if this is the best solution but right now I am the limit of my understanding and would welcome any feedback on the following:

MainActivity.java

@Override
public void onBarcodeEvent(final BarcodeReadEvent event) {
  runOnUiThread(new Runnable(){
    @Override
    public void run() {
      String barcodeData = event.getBarcodeData();
      String tstp = event.getTimestamp();
      setLatestBarcode(barcodeData);
      Log.d("MainActivity", " TEST - barcodeData "+ barcodeData + " tstp : "+ tstp);
    }
  });

  WritableMap params = Arguments.createMap(); // <--- added

  getReactInstanceManager().getCurrentReactContext() // <--- added
    .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) // <--- added
    .emit("BarcodeReceived", params); // <--- added
}

This works I can trigger a React Method by using the following in my JS:

componentWillUnmount () {
  this._barcodeListener.remove()
}

componentWillMount () {
  // Listen for Honeywell Scans
  this.getBarcodeValue = DeviceEventEmitter.addListener('BarcodeReceived', this.getBarcodeValue)
}

...

getBarcodeValue () {
  console.log('Event Received')

  HoneywellCT50.latestBarcode((value) => {
    this.setState({ barcode: value }, () => {
      console.log(this.state.barcode)
    })
  })
}

If anyone with experience reads this I would love to know why the code posted in my EDIT above didn't work. Is it because I tried emitting the event in a @ReactMethod ?

1 Comment

As @Guillermo Grau pointed out it has been removed from docs. Link to the old docs: facebook.github.io/react-native/releases/0.43/docs/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.