Reputation: 2678
I built a very simple PhoneGap
Plugin to start testing the way I'm going to build some native actions on Android.
JavaScript:
function callNativePlugin() {
cordova.exec(nativePluginResultHandler, nativePluginErrorHandler, "Database", "saveAdvertencia", [ 1, "TesteAdv" ]);
}
function nativePluginResultHandler(result) {
alert("SUCCESS: \r\n" + result);
}
function nativePluginErrorHandler(error) {
alert("ERROR: \r\n" + error);
}
Java:
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("saveAdvertencia")) {
advertenciaDS = new AdvertenciaDS(cordova.getActivity());
callbackContext.sendPluginResult(new PluginResult(Status.OK, new JSONArray("test")));
return true;
}
return false;
}
What I need is a way to retrieve the result from the action in the same method. It's very complicated to always deal with 3 methods(1 to execute the action. 1 to define what will be the success action. 1 to define what will be the error action.) when you don't really control when they are called, since PhoneGap
calls them after the action is completed.
If I need to retrieve some data from the Android Native database:
Upvotes: 6
Views: 6885
Reputation: 1838
If you're asking for a way to turn cordova.exec()
from an asynchronous call into a synchronous call that returns a value, the short answer is that you can't. (The long answer is you can fake it using a loop or timeout but you shouldn't.)
As Vlad explains, you can create your own interface so you only have one function to call, but I use something like this simpler version (in http://htmlpresenter.com/api.html):
var Database = {
saveAdvertencia: function(args, callback) {
cordova.exec(callback,
function(error) { console.log("Error calling Database.saveAdvertencia: " + error); },
"Database", "saveAdvertencia", args)
}
}
Then call it like this providing the callback inline if you need the result:
Database.Advertencia([1, "TesteAdv"], function(result) { alert(result); });
Of course if (as seems to be the case) you don't need the result at all, you can just use this version:
function saveAdvertencia() {
log = function(message) { console.log(message) };
cordova.exec(log, log, "Database", "saveAdvertencia", arguments);
}
saveAdvertencia(1, "TesteAdv");
(Edit:) Also, this challenge may be related to this, better question:
Upvotes: 2
Reputation: 2678
Within JavaScript, I was able to retrieve the PhoneGap plugin value with only one easily controllable recursive method:
function callNativePlugin(result, error, service, action, json) {
if (result != null) {
//alert("SUCCESS: \r\n" + result);
return result;
} else if (error != null) {
//alert("ERROR: \r\n" + error);
return error;
}
return cordova.exec(function(result) {callNativePlugin(result, null, null, null);}, function(error) {callNativePlugin(null, error, null, null);}, service, action, json);
}
Upvotes: 0
Reputation: 1792
I use this pattern to have only one callback for the functions provided by the plugin:
function callNativePlugin(callback) {
cordova.exec(function(result) {
callback(null, result);
}, function(result) {
callback("myerror");
}, "Database", "saveAdvertencia", [ 1, "TesteAdv" ])
};
This way you get node.js style callbacks in which the first argument is the error and second is the result:
//define the callback function
var callbackFunction = function(err, result) {
if (err) {
console.log("there was an error");
} else {
console.log("success", result);
}
};
//call the plugin
callNativePlugin(callbackFunction);
You cannot avoid having two callbacks in your plugin, as this is mandated by the cordova API, but you don't have to expose that to your plugin users.
Upvotes: 5