Cordoba: How to write native plugins that can repeatedly reference a Javascript callback?

When developing Cordoba plugins, all the tutorials I found look something like this:

File: AwesomePlugin.js

var AwesomePlugin = { kungfuGripAction = function(target, successCallback, failureCallback) { return cordova.exec( successCallback, failureCallback, 'AwesomePluginClass', 'kungfuGripAction', [target] ); } }; module.exports = AwesomePlugin; 

File: AwesomePluginClass.java

 @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { if (ACTION_KUNGFU_GRIP.equals(action)) { JSONObject target = args.getJSONObject(0); if (gripTarget(target)) { callbackContext.success("Target successfully gripped."); return true; } else { callbackContext.error("Could not grip target."); return false; } } Log.d(LOG_TAG, "INVALID ACTION! " + action); callbackContext.error("Invalid action: " + action); return false; } 

File: clientCode.js

 AwesomePlugin.kungfuGripAction(cobraEnemy, function(ok) { }, function(err) { }); 

In the above code, callbacks can only be called once and then deleted. If you try to call the .success() or .error() method of the .success() context object, this will not work, and you will receive a log message:

 Attempted to send a second callback for ID: AwesomePlugin2982699494<BR>W/CordovaPlugin(976) Result was: "Target successfully gripped." 

It seems that it is impossible to write a method with a callback that can be called multiple times, since .success() and .error() are the only documented ways to call a callback from the plugin's own code. While this is basically what we want, there are times when we want the plugin to rerun the callback. For instance:

 AwesomePlugin.kungfuGripAction(cobraEnemy, function(ok) { // After successful grip, punch repeatedly and update life meter. AwesomePlugin.punchRepeatedly(cobraEnemy, function(hits) { updateLifeMeter(cobraEnemy, hits); }, function(err) { }); }, function(err) { }); 

AwesomePlugin.punchRepeatedly() above will be executed repeatedly (possibly in a separate thread) and will call function(hits) with each successful execution. If this is done de facto (using one-time callbacks), you need to either use a loop (which is bad because it is not asynchronous) or the tail call AwesomePlugin.punchRepeatedly() in the callback (error prone).

What would be the correct way to implement punchRepeatedly() in native code so that it can register the callback once and then execute it again?

+6
source share
2 answers

I think you can use pluginResult with the keepCallback property set to true .

 PluginResult result = new PluginResult(PluginResult.Status.OK, "YOUR_MESSAGE"); // PluginResult result = new PluginResult(PluginResult.Status.ERROR, "YOUR_ERROR_MESSAGE"); result.setKeepCallback(true); callbackContext.sendPluginResult(result); 

You should be able to call the callback several times this way.

+15
source

In the answer above, every time you submit the result of the plugin, it is always the same. So I changed the PluginResult class to add a method like this:

  public void setStrMessage(String strMessage){ this.strMessage = strMessage;} 

This way I can set the message that I really want to send JS. If there are any side effects, please let me know 3x!

0
source

Source: https://habr.com/ru/post/974298/


All Articles