简体   繁体   English

从 Java React Native 调用 JavaScript 方法

[英]Call JavaScript method from Java React Native

I am new to React Native but would like to know if it is possible to call React Native JavaScript method from Java?我是 React Native 的新手,但想知道是否可以从 Java 调用 React Native JavaScript 方法? 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.我已经看到以下插件https://github.com/artemyarulin/react-native-eval,但 Android 实现似乎已过时。

I have googled around but all the examples I can find reference calling Java methods from React Native not the other way around.我已经用谷歌搜索过,但我能找到的所有示例都是从 React Native 调用 Java 方法的参考,而不是相反。

Many thanks in advance.提前谢谢了。

EDIT编辑

I have tried to implement a solution using the method suggested by @ide below.我尝试使用下面@ide 建议的方法来实现一个解决方案。 Here's my attempt so far:到目前为止,这是我的尝试:

In my MainActivity I have:在我的 MainActivity 我有:

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在我的自定义 React Native 模块中

@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.此方法获取该值并将其公开给 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:这是有效的,我可以读取该值,但我需要在用户按下按钮时触发一个方法,所以这里是我的 React Native 模块,因为它现在完整地存在:

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:在 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.使用上面的代码,我可以在没有 Java/build 错误的情况下构建项目,也没有看到 JS 错误,但我无法触发事件。 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.您想要做的是从 Java 发出一个发送到 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.您将编写一个自定义本机模块,从 JavaScript 订阅其事件,然后在您的本机代码中发出该事件。 See this guide: http://facebook.github.io/react-native/docs/native-modules-android.html#sending-events-to-javascript请参阅本指南: 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主活动.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:这有效我可以通过在我的 JS 中使用以下内容来触发 React 方法:

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 ?是因为我尝试在@ReactMethod发出事件吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM