Javascript和Phonegap插件之间的异步通信

2022-09-02 01:18:43

所以,每个人都知道我们做了一个类扩展和覆盖,然后在JS和原生Java(用于Android)之间创建了一个桥梁。此外,我们用于将结果返回给 JS。CordovaPluginexecute()PluginResult

因此,当有一个请求从JS触发到Java插件时,所有这些都会发生。我的问题是,如何将结果异步发送回JS(因此发送到HTML)?

我不知道异步这个词是否在这里。问题是我想突然将一些东西发送回JS(例如,当wifi变为启用/禁用时)。

我已经对此进行了研究,但还没有找到适合我的情况。

我尝试过的事情是 -

  • 使用该类创建了侦听事件。BroadcastReceiverWiFiWifiManager
  • 已注册接收器。
  • 最后,启用/禁用何时弹出,并使用
    和断开连接发送结果
    ,并发送不同的消息。ToastWiFiCallbackContextcallbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, "Wifi Connected"))

MyPlugin.java

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;

...

public class MyPlugin extends CordovaPlugin {
private WifiReceiver wifiBroadcastReceiver = null;
private CallbackContext callbackContext = null;

...

    public MyPlugin() {     
        wifiBroadcastReceiver = new WifiReceiver();
    ...
    }
    ...
    public boolean execute(String action, final JSONArray args,
            final CallbackContext callbackId) throws JSONException {
        IntentFilter wifiFilter = new IntentFilter(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
        cordova.getActivity().registerReceiver(wifiBroadcastReceiver, wifiFilter);
        this.callbackContext = callbackId;

    ...
    }
    public class WifiReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
                if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) {
                    Toast.makeText(cordova.getActivity(), "Wifi Connected", Toast.LENGTH_SHORT).show();
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, "Wifi Connected"));
                } else {
                    Toast.makeText(cordova.getActivity(), "Wifi Disconnected", Toast.LENGTH_SHORT).show();
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "Wifi Disconnected"));
                }
            }           
        }

}

弹出,但不会发送到JS。ToastPluginResult


附言 :监听WiFi事件不是我的实际问题,我想在Phonegap中复制该应用程序。因此,它本质上必须是异步的。Android Bluetooth Chat


答案 1

您几乎就在那里,但您需要在您的插件结果上将KeepCallback设置为true。如果不这样做,Java 端的后续结果在 JavaScript 端将不会有回调。这种类型的编码的最好例子是Cordova核心中的网络插件。以下是指向源的链接:

https://git-wip-us.apache.org/repos/asf?p=cordova-plugin-network-information.git;a=blob;f=src/android/NetworkManager.java;h=e2ac500ccc885db641d5df6dab8eae23026a5828;hb=HEAD

因此,您应该将代码更新为:

public boolean execute(String action, final JSONArray args,
        final CallbackContext callbackId) throws JSONException {
    IntentFilter wifiFilter = new IntentFilter(
            WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
    cordova.getActivity().registerReceiver(wifiBroadcastReceiver,
            wifiFilter);
    this.callbackContext = callbackId;
    PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
    result.setKeepCallback(true);
    this.callbackContext.sendPluginResult(result);
    return true;
}

public class WifiReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
            PluginResult result;
            if (intent.getBooleanExtra(
                    WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) {
                Toast.makeText(cordova.getActivity(), "Wifi Connected",
                        Toast.LENGTH_SHORT).show();
                result = new PluginResult(PluginResult.Status.OK,
                        "Wifi Connected");
            } else {
                Toast.makeText(cordova.getActivity(), "Wifi Disconnected",
                        Toast.LENGTH_SHORT).show();
                result = new PluginResult(PluginResult.Status.ERROR,
                        "Wifi Disconnected");
            }

            result.setKeepCallback(false);
            if (callbackContext != null) {
                callbackContext.sendPluginResult(result);
                callbackContext = null;
            }
        }
    }
}

答案 2

回答“第二次回拨”警告...

触发此警告的 Cordova 源代码可以在此处的第 57 行找到:

https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CallbackContext.java

因此 - 警告是由于您的回调上下文对象具有“完成=true”而引起的。

最有可能的原因是您称之为:callbackContext.sendPluginResult(pluginResult);

无需先打电话:pluginResult.setKeepCallback(true);

如果没有...最有可能的是,您无意中缓存了 CallbackContext 对象。

您的 execute() 函数应该在每次调用时分配 CallbackContext。请参阅代码 Simon 中的第 125-127 行,该代码链接到

public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {

if (action.equals("getConnectionInfo")) {`

this.connectionCallbackContext = callbackContext;

...

事件的完整正确顺序:

  1. 对插件进行初始调用。

  2. 插件保存对在回调文本中传递的引用对象。

  3. 保留回调上下文对象引用,同时使用 setKeepCallback(true) 返回结果。

  4. 序列完成后,返回 setKeepCallback(false)(默认值)

然后后来...

  1. 再次调用插件。

  2. 插件覆盖保存的回调上下文引用,替换为传入的对象。

然后步骤3-4与上面相同。

希望对:)有所帮助


推荐