簡體   English   中英

Javascript和Phonegap插件之間的異步通信

[英]Asynchronous communication between Javascript and Phonegap Plugin

所以,每個人都知道我們創建一個類擴展CordovaPlugin並覆蓋execute() ,然后在JS和本機Java(用於Android)之間創建一個橋梁。 此外,我們使用PluginResult將結果返回給JS。

因此,當JS向Java插件發出請求時,所有這些都會發生。 我的問題是, 如何 異步 地將結果發送回JS (以及HTML)

我不知道異步這個詞是不是就在這里。 問題是我想要發送一些東西回到JS(比如,當wifi變為啟用/禁用時)。

我已經研究過這個,但沒有任何適合我的情況。

我試過的是 -

  • 使用WifiManager類創建了一個BroadcastReceiver監聽WiFi事件。
  • 注冊接收者。
  • 最后,在啟用/禁用WiFi時彈出Toast ,並使用CallbackContext發送結果

    callbackContext.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"));
                }
            }           
        }

}

Toast彈出,但PluginResult不會發送給JS。


PS:聽取WiFi事件不是我的實際問題,我想復制Phonegap中的Android Bluetooth Chat應用程序。 因此,它必須是異步的。

你幾乎就在那里,但你需要在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;
            }
        }
    }
}

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

觸發此警告的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與上述相同。

希望有幫助:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM