From bc1e039ea1b28287b51327df6f61ccdb8a977d5c Mon Sep 17 00:00:00 2001 From: Bryce Curtis Date: Tue, 26 Oct 2010 15:09:54 -0500 Subject: [PATCH] Use polling instead of XHR for callbacks from Java to JavaScript when device has a proxy set. --- framework/assets/js/phonegap.js.base | 40 ++++++++++++++++++- .../src/com/phonegap/CallbackServer.java | 37 +++++++++++++++-- framework/src/com/phonegap/api/Plugin.java | 6 +-- 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/framework/assets/js/phonegap.js.base b/framework/assets/js/phonegap.js.base index 4345e2f1..0ebc8383 100755 --- a/framework/assets/js/phonegap.js.base +++ b/framework/assets/js/phonegap.js.base @@ -238,7 +238,14 @@ PhoneGap.onDeviceReady = new PhoneGap.Channel('onDeviceReady'); PhoneGap.Channel.join(function() { // Start listening for XHR callbacks - PhoneGap.JSCallback(); + setTimeout(function() { + if (CallbackServer.usePolling()) { + PhoneGap.JSCallbackPolling(); + } + else { + PhoneGap.JSCallback(); + } + }, 1); // Run PhoneGap constructors PhoneGap.onPhoneGapInit.fire(); @@ -603,6 +610,37 @@ PhoneGap.JSCallback = function() { xmlhttp.send(); }; +/** + * The polling period to use with JSCallbackPolling. + * This can be changed by the application. The default is 50ms. + */ +PhoneGap.JSCallbackPollingPeriod = 50; + +/** + * This is only for Android. + * + * Internal function that uses polling to call into PhoneGap Java code and retrieve + * any JavaScript code that needs to be run. This is used for callbacks from + * Java to JavaScript. + */ +PhoneGap.JSCallbackPolling = function() { + var msg = CallbackServer.getJavascript(); + if (msg) { + setTimeout(function() { + try { + var t = eval(""+msg); + } + catch (e) { + console.log("JSCallbackPolling Error: "+e); + } + }, 1); + setTimeout(PhoneGap.JSCallbackPolling, 1); + } + else { + setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod); + } +}; + /** * Create a UUID * diff --git a/framework/src/com/phonegap/CallbackServer.java b/framework/src/com/phonegap/CallbackServer.java index 154c7b2f..6bf74c52 100755 --- a/framework/src/com/phonegap/CallbackServer.java +++ b/framework/src/com/phonegap/CallbackServer.java @@ -17,10 +17,10 @@ import java.util.LinkedList; /** * This class provides a way for Java to run JavaScript in the web page that has loaded PhoneGap. - * The CallbackServer class implements an XHR server and a list of JavaScript statements - * that are to be executed on the web page. + * The CallbackServer class implements an XHR server and a polling server with a list of JavaScript + * statements that are to be executed on the web page. * - * The process flow is: + * The process flow for XHR is: * 1. JavaScript makes an async XHR call. * 2. The server holds the connection open until data is available. * 3. The server writes the data to the client and closes the connection. @@ -30,6 +30,14 @@ import java.util.LinkedList; * * The CallbackServer class requires the following permission in Android manifest file * + * + * If the device has a proxy set, then XHR cannot be used, so polling must be used instead. + * This can be determined by the client by calling CallbackServer.usePolling(). + * + * The process flow for polling is: + * 1. The client calls CallbackServer.getJavascript() to retrieve next statement. + * 2. If statement available, then client processes it. + * 3. The client repeats #1 in loop. */ public class CallbackServer implements Runnable { @@ -58,6 +66,11 @@ public class CallbackServer implements Runnable { */ private boolean empty; + /** + * Indicates that polling should be used instead of XHR. + */ + private boolean usePolling; + /** * Constructor. */ @@ -67,7 +80,23 @@ public class CallbackServer implements Runnable { this.empty = true; this.port = 0; this.javascript = new LinkedList(); - this.startServer(); + + if (android.net.Proxy.getDefaultHost() != null) { + this.usePolling = true; + } + else { + this.usePolling = false; + this.startServer(); + } + } + + /** + * Determine if polling should be used instead of XHR. + * + * @return + */ + public boolean usePolling() { + return this.usePolling; } /** diff --git a/framework/src/com/phonegap/api/Plugin.java b/framework/src/com/phonegap/api/Plugin.java index c16c6960..f22e4972 100755 --- a/framework/src/com/phonegap/api/Plugin.java +++ b/framework/src/com/phonegap/api/Plugin.java @@ -99,7 +99,7 @@ public abstract class Plugin implements IPlugin { * @param statement */ public void sendJavascript(String statement) { - this.ctx.callbackServer.sendJavascript(statement); + this.ctx.sendJavascript(statement); } /** @@ -113,7 +113,7 @@ public abstract class Plugin implements IPlugin { * @param callbackId The callback id used when calling back into JavaScript. */ public void success(PluginResult pluginResult, String callbackId) { - this.ctx.callbackServer.sendJavascript(pluginResult.toSuccessCallbackString(callbackId)); + this.ctx.sendJavascript(pluginResult.toSuccessCallbackString(callbackId)); } /** @@ -123,6 +123,6 @@ public abstract class Plugin implements IPlugin { * @param callbackId The callback id used when calling back into JavaScript. */ public void error(PluginResult pluginResult, String callbackId) { - this.ctx.callbackServer.sendJavascript(pluginResult.toErrorCallbackString(callbackId)); + this.ctx.sendJavascript(pluginResult.toErrorCallbackString(callbackId)); } }