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?
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
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 ?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With