[英]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核心中的網絡插件。 這是源的鏈接:
所以你應該將你的代碼更新為:
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行找到:
因此 - 引發警告是因為您的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;
...
正確的事件順序:
初始調用插件。
插件保存對傳入的CallbackContext對象的引用。
保持CallbackContext對象引用,同時使用setKeepCallback返回結果(true)。
序列完成后,返回setKeepCallback(false)(默認值)
然后......
再次調用插件。
插件覆蓋保存的CallbackContext引用,替換為傳入的對象。
然后步驟3-4與上述相同。
希望有幫助:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.