22

因此,每个人都知道我们创建了一个类扩展CordovaPlugin并覆盖 execute(),然后在 JS 和本机 Java(对于 Android)之间建立了一座桥梁。此外,我们使用PluginResult将结果返回给 JS。

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

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

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

我试过的事情是 -

  • 使用该类 创建了一个BroadcastReceiver监听WiFi事件。WifiManager
  • 注册了接收者。
  • 最后,弹出一个何时启用Toast/WiFi禁用,并使用 CallbackContext

    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, "Wifi Connected"))and for disconnected 和不同的消息发送结果。

我的插件.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"));
                }
            }           
        }

}

Toastpops 但不会PluginResult发送到 JS。


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

4

2 回答 2

19

您快到了,但您需要在 PluginResult 上将 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=头

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

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;
            }
        }
    }
}
于 2013-10-05T14:27:49.970 回答
13

回答“第二次回调”警告..​​.

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

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

因此 - 警告是因为您的 CallbackContext 对象具有“finished=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. 插件保存对传入 CallbackContext 对象的引用。

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

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

然后后来...

  1. 再次调用插件。

  2. 插件覆盖保存的 CallbackContext 引用,替换为传入的对象。

然后步骤 3-4 同上。

希望有帮助:)

于 2014-01-05T20:41:32.767 回答