Asynchronous communication between Javascript and the Phonegap plugin

So, everyone knows that we create a class that extends CordovaPlugin and redefine execute() , and then create a bridge between JS and native Java (for Android). Next, we use PluginResult to return the result to JS.

So, all this happens when there is a request running from JS to the Java plugin. My question is: how to send the result back to JS (and therefore in HTML) asynchronously?

I don't know if the word will be asynchronous right here. The thing is, I want to send something back to JS from blue (let's say when wifi becomes on / off).

I have already researched this, but have not received anything that suits my case.

What I tried is

  • Created BroadcastReceiver , listening to WiFi events using the WifiManager class.
  • Register the receiver.
  • And finally, when you click Toast when WiFi on / off, and sends the result using CallbackContext

    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, "Wifi Connected")) and to disconnect with another message.

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 ports, but PluginResult not sent to JS.




PS: Listening to WiFi events is not my real problem, I want to replicate the Android Bluetooth Chat application in Phonegap. Therefore, it must be asynchronous in nature.

+17
java android cordova phonegap-plugins
04 Oct '13 at 9:37
source share
2 answers

You almost have it, but you need setKeepCallback to be true on your PluginResult. Unless you get subsequent results from the Java side, it will not have a JavaScript callback. The best example of this type of encoding is the network plugin in the Cordova core. Here is the link to the source:

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

So you should update your code to:

 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; } } } } 
+13
Oct 05 '13 at 14:27
source share

Responding to a second callback warning ...

The source code for Cordoba that triggers this warning can be found on line 57 here:

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

Thus, the warning is caused by the fact that your CallbackContext object has the value "finished = true".

Most likely, you name the reason for this: callbackContext.sendPluginResult(pluginResult);

Without the first call: pluginResult.setKeepCallback(true);

If not ... most likely you are inadvertently caching a CallbackContext object.

The execute () function must assign a CallbackContext every time it is called. See Lines 125-127 in the Simon code associated with :

 public boolean execute(String action, JSONArray args, CallbackContext callbackContext) { if (action.equals("getConnectionInfo")) {` this.connectionCallbackContext = callbackContext; ... 

Own sequence of events in full:

  • Make the initial call to the plugin.

  • The plugin maintains a reference to the passed CallbackContext object.

  • Keep a reference to the CallbackContext object, returning results using setKeepCallback (true).

  • When the sequence is finished, return using setKeepCallback (false) (default)

Then later ...

  • Make another plugin call.

  • The plugin overwrites the saved CallbackContext link, replaces the passed object.

Then steps 3-4, as described above.

Hope that helps :)

+10
Jan 05 '14 at 20:41
source share



All Articles