From 37a93076819ca6af950aae36b5510f23e9267177 Mon Sep 17 00:00:00 2001 From: Bryce Curtis Date: Wed, 27 Oct 2010 07:16:13 +0800 Subject: [PATCH 1/2] Enable JS callbacks to be kept around for multiple callbacks from Java. --- framework/assets/js/phonegap.js.base | 53 ++++++++++++------- framework/src/com/phonegap/Notification.java | 8 ++- .../src/com/phonegap/api/PluginManager.java | 21 ++++---- .../src/com/phonegap/api/PluginResult.java | 25 +++++---- 4 files changed, 64 insertions(+), 43 deletions(-) diff --git a/framework/assets/js/phonegap.js.base b/framework/assets/js/phonegap.js.base index 0ebc8383..f5b32133 100755 --- a/framework/assets/js/phonegap.js.base +++ b/framework/assets/js/phonegap.js.base @@ -383,18 +383,16 @@ PhoneGap.clone = function(obj) { PhoneGap.callbackId = 0; PhoneGap.callbacks = {}; PhoneGap.callbackStatus = { - OK: 0, - CLASS_NOT_FOUND_EXCEPTION: 1, - ILLEGAL_ACCESS_EXCEPTION: 2, - INSTANTIATION_EXCEPTION: 3, - MALFORMED_URL_EXCEPTION: 4, - IO_EXCEPTION: 5, - INVALID_ACTION: 6, - JSON_EXCEPTION: 7, - ERROR: 8, - RESULT_TO_BE_SENT: 9, - NEXT_RESULT: 10, - NO_MORE_RESULTS: 11 + NO_RESULT: 0, + OK: 1, + CLASS_NOT_FOUND_EXCEPTION: 2, + ILLEGAL_ACCESS_EXCEPTION: 3, + INSTANTIATION_EXCEPTION: 4, + MALFORMED_URL_EXCEPTION: 5, + IO_EXCEPTION: 6, + INVALID_ACTION: 7, + JSON_EXCEPTION: 8, + ERROR: 9 }; @@ -427,7 +425,7 @@ PhoneGap.exec = function(success, fail, service, action, args) { eval("var v="+r+";"); // If status is OK, then return value back to caller - if ((v.status == PhoneGap.callbackStatus.OK) || (v.status == PhoneGap.callbackStatus.NEXT_RESULT)) { + if (v.status == PhoneGap.callbackStatus.OK) { // If there is a success callback, then call it now with returned value if (success) { @@ -439,15 +437,24 @@ PhoneGap.exec = function(success, fail, service, action, args) { } // Clear callback if not expecting any more results - if ((v.status == PhoneGap.callbackStatus.OK) || (v.status == PhoneGap.callbackStatus.NO_MORE_RESULTS)) { + if (!v.keepCallback) { delete PhoneGap.callbacks[callbackId]; } } return v.message; } + // If no result + else if (v.status == PhoneGap.callbackStatus.NO_RESULT) { + + // Clear callback if not expecting any more results + if (!v.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } + // If error, then display error - else if (v.status != PhoneGap.callbackStatus.RESULT_TO_BE_SENT) { + else { console.log("Error: Status="+r.status+" Message="+v.message); // If there is a fail callback, then call it now with returned value @@ -458,7 +465,11 @@ PhoneGap.exec = function(success, fail, service, action, args) { catch (e) { console.log("Error in error callback: "+callbackId+" = "+e); } - delete PhoneGap.callbacks[callbackId]; + + // Clear callback if not expecting any more results + if (!v.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } } return null; } @@ -478,7 +489,7 @@ PhoneGap.callbackSuccess = function(callbackId, args) { if (PhoneGap.callbacks[callbackId]) { // If result is to be sent to callback - if ((args.status == PhoneGap.callbackStatus.OK) || (args.status == PhoneGap.callbackStatus.NEXT_RESULT)) { + if (args.status == PhoneGap.callbackStatus.OK) { try { if (PhoneGap.callbacks[callbackId].success) { PhoneGap.callbacks[callbackId].success(args.message); @@ -490,7 +501,7 @@ PhoneGap.callbackSuccess = function(callbackId, args) { } // Clear callback if not expecting any more results - if ((args.status == PhoneGap.callbackStatus.OK) || (args.status == PhoneGap.callbackStatus.NO_MORE_RESULTS)) { + if (!args.keepCallback) { delete PhoneGap.callbacks[callbackId]; } } @@ -512,7 +523,11 @@ PhoneGap.callbackError = function(callbackId, args) { catch (e) { console.log("Error in error callback: "+callbackId+" = "+e); } - delete PhoneGap.callbacks[callbackId]; + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } } }; diff --git a/framework/src/com/phonegap/Notification.java b/framework/src/com/phonegap/Notification.java index 08334668..ed5786d5 100755 --- a/framework/src/com/phonegap/Notification.java +++ b/framework/src/com/phonegap/Notification.java @@ -56,11 +56,15 @@ public class Notification extends Plugin { } else if (action.equals("alert")) { this.alert(args.getString(0),args.getString(1),args.getString(2), callbackId); - return new PluginResult(PluginResult.Status.RESULT_TO_BE_SENT); + PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT); + r.setKeepCallback(true); + return r; } else if (action.equals("confirm")) { this.confirm(args.getString(0),args.getString(1),args.getString(2), callbackId); - return new PluginResult(PluginResult.Status.RESULT_TO_BE_SENT); + PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT); + r.setKeepCallback(true); + return r; } else if (action.equals("activityStart")) { this.activityStart(args.getString(0),args.getString(1)); diff --git a/framework/src/com/phonegap/api/PluginManager.java b/framework/src/com/phonegap/api/PluginManager.java index 5d03e0f5..905d04cd 100755 --- a/framework/src/com/phonegap/api/PluginManager.java +++ b/framework/src/com/phonegap/api/PluginManager.java @@ -88,19 +88,16 @@ public final class PluginManager { // Call execute on the plugin so that it can do it's thing PluginResult cr = plugin.execute(action, args, callbackId); int status = cr.getStatus(); - - // Check the success (OK, NEXT_RESULT, NO_MORE_RESULTS) - if ((status == PluginResult.Status.OK.ordinal()) || - (status == PluginResult.Status.NEXT_RESULT.ordinal()) || - (status == PluginResult.Status.NO_MORE_RESULTS.ordinal()) - ) { + + // If no result to be sent and keeping callback, then no need to sent back to JavaScript + if ((status == PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) { + } + + // Check the success (OK, NO_RESULT & !KEEP_CALLBACK) + else if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) { ctx.sendJavascript(cr.toSuccessCallbackString(callbackId)); } - // If return result will be sent later, no need to sent back to JavaScript - else if (status == PluginResult.Status.RESULT_TO_BE_SENT.ordinal()) { - } - // If error else { ctx.sendJavascript(cr.toErrorCallbackString(callbackId)); @@ -117,8 +114,8 @@ public final class PluginManager { // Call execute on the plugin so that it can do it's thing cr = plugin.execute(action, args, callbackId); - // If return result will be sent later - if (cr.getStatus() == PluginResult.Status.RESULT_TO_BE_SENT.ordinal()) { + // If no result to be sent and keeping callback, then no need to sent back to JavaScript + if ((cr.getStatus() == PluginResult.Status.NO_RESULT.ordinal()) && cr.getKeepCallback()) { return ""; } } diff --git a/framework/src/com/phonegap/api/PluginResult.java b/framework/src/com/phonegap/api/PluginResult.java index 38dfa43b..1a4250cf 100755 --- a/framework/src/com/phonegap/api/PluginResult.java +++ b/framework/src/com/phonegap/api/PluginResult.java @@ -13,6 +13,7 @@ import org.json.JSONObject; public class PluginResult { private final int status; private final String message; + private boolean keepCallback = false; public PluginResult(Status status) { this.status = status.ordinal(); @@ -49,6 +50,10 @@ public class PluginResult { this.message = ""+b; } + public void setKeepCallback(boolean b) { + this.keepCallback = b; + } + public int getStatus() { return status; } @@ -56,9 +61,13 @@ public class PluginResult { public String getMessage() { return message; } - + + public boolean getKeepCallback() { + return this.keepCallback; + } + public String getJSONString() { - return "{ status: " + this.getStatus() + ", message: " + this.getMessage() + " }"; + return "{status:" + this.status + ",message:" + this.message + ",keepCallback:" + this.keepCallback + "}"; } public String toSuccessCallbackString(String callbackId) { @@ -70,6 +79,7 @@ public class PluginResult { } public static String[] StatusMessages = new String[] { + "No result", "OK", "Class not found", "Illegal access", @@ -78,13 +88,11 @@ public class PluginResult { "IO error", "Invalid action", "JSON error", - "Error", - "Result to be sent later", - "Next result", - "No more results" + "Error" }; public enum Status { + NO_RESULT, OK, CLASS_NOT_FOUND_EXCEPTION, ILLEGAL_ACCESS_EXCEPTION, @@ -93,9 +101,6 @@ public class PluginResult { IO_EXCEPTION, INVALID_ACTION, JSON_EXCEPTION, - ERROR, - RESULT_TO_BE_SENT, - NEXT_RESULT, - NO_MORE_RESULTS + ERROR } } From 831670e4aeb01f678d8a99fd6cabc6ddc85f4d85 Mon Sep 17 00:00:00 2001 From: Bryce Curtis Date: Wed, 27 Oct 2010 07:56:50 +0800 Subject: [PATCH 2/2] Modify camera to use NO_RESULT, thus eliminating extra JS callback methods. --- framework/assets/js/camera.js | 37 +------------------ .../src/com/phonegap/CameraLauncher.java | 13 +++++-- 2 files changed, 10 insertions(+), 40 deletions(-) diff --git a/framework/assets/js/camera.js b/framework/assets/js/camera.js index e49777aa..0d9cf761 100755 --- a/framework/assets/js/camera.js +++ b/framework/assets/js/camera.js @@ -70,8 +70,6 @@ Camera.prototype.getPicture = function(successCallback, errorCallback, options) return; } - this.successCallback = successCallback; - this.errorCallback = errorCallback; this.options = options; var quality = 80; if (options.quality) { @@ -85,40 +83,7 @@ Camera.prototype.getPicture = function(successCallback, errorCallback, options) if (typeof this.options.sourceType == "number") { sourceType = this.options.sourceType; } - PhoneGap.exec(null, null, "Camera", "takePicture", [quality, destinationType, sourceType]); -}; - -/** - * Callback function from native code that is called when image has been captured. - * - * @param picture The base64 encoded string of the image - */ -Camera.prototype.success = function(picture) { - if (this.successCallback) { - try { - this.successCallback(picture); - } - catch (e) { - console.log("Camera error calling user's success callback: " + e); - } - } -}; - -/** - * Callback function from native code that is called when there is an error - * capturing an image, or the capture is cancelled. - * - * @param err The error message - */ -Camera.prototype.error = function(err) { - if (this.errorCallback) { - try { - this.errorCallback(err); - } - catch (e) { - console.log("Camera error calling user's error callback: " + e); - } - } + PhoneGap.exec(successCallback, errorCallback, "Camera", "takePicture", [quality, destinationType, sourceType]); }; PhoneGap.addConstructor(function() { diff --git a/framework/src/com/phonegap/CameraLauncher.java b/framework/src/com/phonegap/CameraLauncher.java index 9c8638a7..50ad55ae 100755 --- a/framework/src/com/phonegap/CameraLauncher.java +++ b/framework/src/com/phonegap/CameraLauncher.java @@ -45,6 +45,7 @@ public class CameraLauncher extends Plugin { private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality) private Uri imageUri; // Uri of captured image + public String callbackId; /** * Constructor. @@ -63,6 +64,7 @@ public class CameraLauncher extends Plugin { public PluginResult execute(String action, JSONArray args, String callbackId) { PluginResult.Status status = PluginResult.Status.OK; String result = ""; + this.callbackId = callbackId; try { if (action.equals("takePicture")) { @@ -80,6 +82,9 @@ public class CameraLauncher extends Plugin { else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) { this.getImage(srcType, destType); } + PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT); + r.setKeepCallback(true); + return r; } return new PluginResult(status, result); } catch (JSONException e) { @@ -190,7 +195,7 @@ public class CameraLauncher extends Plugin { os.close(); // Send Uri back to JavaScript for viewing image - this.sendJavascript("navigator.camera.success('" + uri.toString() + "');"); + this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); } } catch (IOException e) { e.printStackTrace(); @@ -227,7 +232,7 @@ public class CameraLauncher extends Plugin { // If sending filename back else if (destType == FILE_URI) { - this.sendJavascript("navigator.camera.success('" + uri + "');"); + this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); } } else if (resultCode == Activity.RESULT_CANCELED) { @@ -251,7 +256,7 @@ public class CameraLauncher extends Plugin { byte[] code = jpeg_data.toByteArray(); byte[] output = Base64.encodeBase64(code); String js_out = new String(output); - this.sendJavascript("navigator.camera.success('" + js_out + "');"); + this.success(new PluginResult(PluginResult.Status.OK, js_out), this.callbackId); } } catch(Exception e) { @@ -265,6 +270,6 @@ public class CameraLauncher extends Plugin { * @param err */ public void failPicture(String err) { - this.sendJavascript("navigator.camera.error('" + err + "');"); + this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId); } }