Improve handling of timeout error when loading URL, and enable WebViewClient to be overridden by app, so developer can intercept webview events.

This commit is contained in:
Bryce Curtis 2010-11-21 16:42:00 -06:00
parent 44761f87d2
commit e3ebfea064

View File

@ -94,11 +94,14 @@ public class DroidGap extends PhonegapActivity {
// The webview for our app // The webview for our app
protected WebView appView; protected WebView appView;
protected WebViewClient webViewClient;
private LinearLayout root; private LinearLayout root;
private BrowserKey mKey; private BrowserKey mKey;
public CallbackServer callbackServer; public CallbackServer callbackServer;
protected PluginManager pluginManager; protected PluginManager pluginManager;
protected boolean cancelLoadUrl = false;
protected boolean clearHistory = false;
// The initial URL for our app // The initial URL for our app
private String url; private String url;
@ -113,7 +116,7 @@ public class DroidGap extends PhonegapActivity {
private String splashScreenShowing = null; private String splashScreenShowing = null;
// Flag indicates that a loadUrl timeout occurred // Flag indicates that a loadUrl timeout occurred
private boolean loadUrlTimeout = false; private int loadUrlTimeout = 0;
/* /*
* The variables below are used to cache some of the activity properties. * The variables below are used to cache some of the activity properties.
@ -190,7 +193,7 @@ public class DroidGap extends PhonegapActivity {
this.appView.setWebChromeClient(new GapClient(DroidGap.this)); this.appView.setWebChromeClient(new GapClient(DroidGap.this));
} }
this.appView.setWebViewClient(new GapViewClient(this)); this.setWebViewClient(this.appView, new GapViewClient(this));
this.appView.setInitialScale(100); this.appView.setInitialScale(100);
this.appView.setVerticalScrollBarEnabled(false); this.appView.setVerticalScrollBarEnabled(false);
@ -220,8 +223,26 @@ public class DroidGap extends PhonegapActivity {
root.addView(this.appView); root.addView(this.appView);
setContentView(root); setContentView(root);
// Handle activity parameters // Clear cancel flag
this.handleActivityParameters(); this.cancelLoadUrl = false;
// If url specified, then load it
String url = this.getStringProperty("url", null);
if (url != null) {
System.out.println("Loading initial URL="+url);
this.loadUrl(url);
}
}
/**
* Set the WebViewClient.
*
* @param appView
* @param client
*/
protected void setWebViewClient(WebView appView, WebViewClient client) {
this.webViewClient = client;
appView.setWebViewClient(client);
} }
/** /**
@ -257,37 +278,36 @@ public class DroidGap extends PhonegapActivity {
/** /**
* Look at activity parameters and process them. * Look at activity parameters and process them.
* This must be called from the main UI thread.
*/ */
private void handleActivityParameters() { private void handleActivityParameters() {
// Init web view if not already done
if (this.appView == null) {
this.init();
}
// If spashscreen // If spashscreen
this.splashscreen = this.getProperty("splashscreen", 0); this.splashscreen = this.getIntegerProperty("splashscreen", 0);
if (this.splashscreen != 0) { if (this.splashscreen != 0) {
appView.setBackgroundColor(0); this.appView.setBackgroundColor(0);
appView.setBackgroundResource(splashscreen); this.appView.setBackgroundResource(splashscreen);
} }
// If hideLoadingDialogOnPageLoad // If hideLoadingDialogOnPageLoad
this.hideLoadingDialogOnPageLoad = this.getProperty("hideLoadingDialogOnPageLoad", false); this.hideLoadingDialogOnPageLoad = this.getBooleanProperty("hideLoadingDialogOnPageLoad", false);
// If loadInWebView // If loadInWebView
this.loadInWebView = this.getProperty("loadInWebView", false); this.loadInWebView = this.getBooleanProperty("loadInWebView", false);
// If loadUrlTimeoutValue // If loadUrlTimeoutValue
int timeout = this.getProperty("loadUrlTimeoutValue", 0); int timeout = this.getIntegerProperty("loadUrlTimeoutValue", 0);
if (timeout > 0) { if (timeout > 0) {
this.loadUrlTimeoutValue = timeout; this.loadUrlTimeoutValue = timeout;
} }
// If keepRunning // If keepRunning
this.keepRunning = this.getProperty("keepRunning", true); this.keepRunning = this.getBooleanProperty("keepRunning", true);
// If url specified, then load it
String url = this.getProperty("url", null);
if (url != null) {
System.out.println("Loading initial URL="+url);
this.loadUrl(url);
}
} }
/** /**
@ -307,65 +327,62 @@ public class DroidGap extends PhonegapActivity {
} }
System.out.println("url="+url+" baseUrl="+baseUrl); System.out.println("url="+url+" baseUrl="+baseUrl);
// Init web view if not already done
if (this.appView == null) {
this.init();
}
// Initialize callback server
this.callbackServer.init(url);
// If loadingDialog, then show the App loading dialog
String loading = this.getProperty("loadingDialog", null);
if (loading != null) {
String title = "";
String message = "Loading Application...";
if (loading.length() > 0) {
int comma = loading.indexOf(',');
if (comma > 0) {
title = loading.substring(0, comma);
message = loading.substring(comma+1);
}
else {
title = "";
message = loading;
}
}
JSONArray parm = new JSONArray();
parm.put(title);
parm.put(message);
this.pluginManager.exec("Notification", "activityStart", null, parm.toString(), false);
}
final DroidGap me = this;
// Create a timeout timer for loadUrl
Runnable runnable = new Runnable() {
public void run() {
me.loadUrlTimeout = true;
try {
synchronized(this) {
wait(me.loadUrlTimeoutValue);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// If timeout, then stop loading and handle error
if (me.loadUrlTimeout) {
me.appView.stopLoading();
me.onReceivedError(-6, "The connection to the server was unsuccessful.", url);
}
}
};
Thread thread = new Thread(runnable);
thread.start();
// Load URL on UI thread // Load URL on UI thread
final DroidGap me = this;
this.runOnUiThread(new Runnable() { this.runOnUiThread(new Runnable() {
public void run() { public void run() {
// Handle activity parameters
me.handleActivityParameters();
// Initialize callback server
me.callbackServer.init(url);
// If loadingDialog, then show the App loading dialog
String loading = me.getStringProperty("loadingDialog", null);
if (loading != null) {
String title = "";
String message = "Loading Application...";
if (loading.length() > 0) {
int comma = loading.indexOf(',');
if (comma > 0) {
title = loading.substring(0, comma);
message = loading.substring(comma+1);
}
else {
title = "";
message = loading;
}
}
JSONArray parm = new JSONArray();
parm.put(title);
parm.put(message);
me.pluginManager.exec("Notification", "activityStart", null, parm.toString(), false);
}
// Create a timeout timer for loadUrl
final int currentLoadUrlTimeout = me.loadUrlTimeout;
Runnable runnable = new Runnable() {
public void run() {
try {
synchronized(this) {
wait(me.loadUrlTimeoutValue);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// If timeout, then stop loading and handle error
if (me.loadUrlTimeout == currentLoadUrlTimeout) {
me.appView.stopLoading();
me.webViewClient.onReceivedError(me.appView, -6, "The connection to the server was unsuccessful.", url);
}
}
};
Thread thread = new Thread(runnable);
thread.start();
me.appView.loadUrl(url); me.appView.loadUrl(url);
} }
}); });
@ -381,6 +398,14 @@ public class DroidGap extends PhonegapActivity {
public void loadUrl(final String url, final int time) { public void loadUrl(final String url, final int time) {
System.out.println("loadUrl("+url+","+time+")"); System.out.println("loadUrl("+url+","+time+")");
final DroidGap me = this; final DroidGap me = this;
// Handle activity parameters
this.runOnUiThread(new Runnable() {
public void run() {
me.handleActivityParameters();
}
});
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
public void run() { public void run() {
try { try {
@ -390,14 +415,46 @@ public class DroidGap extends PhonegapActivity {
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
me.loadUrl(url); if (!me.cancelLoadUrl) {
me.loadUrl(url);
}
else{
me.cancelLoadUrl = false;
System.out.println("Aborting loadUrl("+url+"): Another URL was loaded before timer expired.");
}
} }
}; };
Thread thread = new Thread(runnable); Thread thread = new Thread(runnable);
thread.start(); thread.start();
} }
/**
* Cancel loadUrl before it has been loaded.
*/
public void cancelLoadUrl() {
this.cancelLoadUrl = true;
}
/**
* Clear the resource cache.
*/
public void clearCache() {
if (this.appView == null) {
this.init();
}
this.appView.clearCache(true);
}
/** /**
* Clear web history in this web view.
*/
public void clearHistory() {
this.clearHistory = true;
if (this.appView != null) {
this.appView.clearHistory();
}
}
* Load the url into the webview. * Load the url into the webview.
* *
* @param url * @param url
@ -439,7 +496,7 @@ public class DroidGap extends PhonegapActivity {
* @param defaultValue * @param defaultValue
* @return * @return
*/ */
protected boolean getProperty(String name, boolean defaultValue) { public boolean getBooleanProperty(String name, boolean defaultValue) {
Bundle bundle = this.getIntent().getExtras(); Bundle bundle = this.getIntent().getExtras();
if (bundle == null) { if (bundle == null) {
return defaultValue; return defaultValue;
@ -458,7 +515,7 @@ public class DroidGap extends PhonegapActivity {
* @param defaultValue * @param defaultValue
* @return * @return
*/ */
protected int getProperty(String name, int defaultValue) { public int getIntegerProperty(String name, int defaultValue) {
Bundle bundle = this.getIntent().getExtras(); Bundle bundle = this.getIntent().getExtras();
if (bundle == null) { if (bundle == null) {
return defaultValue; return defaultValue;
@ -477,7 +534,7 @@ public class DroidGap extends PhonegapActivity {
* @param defaultValue * @param defaultValue
* @return * @return
*/ */
protected String getProperty(String name, String defaultValue) { public String getStringProperty(String name, String defaultValue) {
Bundle bundle = this.getIntent().getExtras(); Bundle bundle = this.getIntent().getExtras();
if (bundle == null) { if (bundle == null) {
return defaultValue; return defaultValue;
@ -496,7 +553,7 @@ public class DroidGap extends PhonegapActivity {
* @param defaultValue * @param defaultValue
* @return * @return
*/ */
protected double getProperty(String name, double defaultValue) { public double getDoubleProperty(String name, double defaultValue) {
Bundle bundle = this.getIntent().getExtras(); Bundle bundle = this.getIntent().getExtras();
if (bundle == null) { if (bundle == null) {
return defaultValue; return defaultValue;
@ -514,10 +571,7 @@ public class DroidGap extends PhonegapActivity {
* @param name * @param name
* @param value * @param value
*/ */
protected void setProperty(String name, boolean value) { public void setBooleanProperty(String name, boolean value) {
if (this.appView != null) {
System.out.println("Setting property after webview is already initialized - no effect.");
}
this.getIntent().putExtra(name, value); this.getIntent().putExtra(name, value);
} }
@ -527,10 +581,7 @@ public class DroidGap extends PhonegapActivity {
* @param name * @param name
* @param value * @param value
*/ */
protected void setProperty(String name, int value) { public void setIntegerProperty(String name, int value) {
if (this.appView != null) {
System.out.println("Setting property after webview is already initialized - no effect.");
}
this.getIntent().putExtra(name, value); this.getIntent().putExtra(name, value);
} }
@ -540,10 +591,7 @@ public class DroidGap extends PhonegapActivity {
* @param name * @param name
* @param value * @param value
*/ */
protected void setProperty(String name, String value) { public void setStringProperty(String name, String value) {
if (this.appView != null) {
System.out.println("Setting property after webview is already initialized - no effect.");
}
this.getIntent().putExtra(name, value); this.getIntent().putExtra(name, value);
} }
@ -553,10 +601,7 @@ public class DroidGap extends PhonegapActivity {
* @param name * @param name
* @param value * @param value
*/ */
protected void setProperty(String name, double value) { public void setDoubleProperty(String name, double value) {
if (this.appView != null) {
System.out.println("Setting property after webview is already initialized - no effect.");
}
this.getIntent().putExtra(name, value); this.getIntent().putExtra(name, value);
} }
@ -904,7 +949,7 @@ public class DroidGap extends PhonegapActivity {
super.onPageFinished(view, url); super.onPageFinished(view, url);
// Clear timeout flag // Clear timeout flag
this.ctx.loadUrlTimeout = false; this.ctx.loadUrlTimeout++;
// Try firing the onNativeReady event in JS. If it fails because the JS is // Try firing the onNativeReady event in JS. If it fails because the JS is
// not loaded yet then just set a flag so that the onNativeReady can be fired // not loaded yet then just set a flag so that the onNativeReady can be fired
@ -948,7 +993,10 @@ public class DroidGap extends PhonegapActivity {
System.out.println("onReceivedError: Error code="+errorCode+" Description="+description+" URL="+failingUrl); System.out.println("onReceivedError: Error code="+errorCode+" Description="+description+" URL="+failingUrl);
// Clear timeout flag // Clear timeout flag
this.ctx.loadUrlTimeout = false; this.ctx.loadUrlTimeout++;
// Stop "app loading" spinner if showing
this.ctx.pluginManager.exec("Notification", "activityStop", null, "[]", false);
// Handle error // Handle error
this.ctx.onReceivedError(errorCode, description, failingUrl); this.ctx.onReceivedError(errorCode, description, failingUrl);
@ -1064,11 +1112,8 @@ public class DroidGap extends PhonegapActivity {
public void onReceivedError(int errorCode, String description, String failingUrl) { public void onReceivedError(int errorCode, String description, String failingUrl) {
final DroidGap me = this; final DroidGap me = this;
// Stop "app loading" spinner if showing
me.pluginManager.exec("Notification", "activityStop", null, "[]", false);
// If errorUrl specified, then load it // If errorUrl specified, then load it
final String errorUrl = me.getProperty("errorUrl", null); final String errorUrl = me.getStringProperty("errorUrl", null);
if ((errorUrl != null) && errorUrl.startsWith("file://") && (!failingUrl.equals(errorUrl))) { if ((errorUrl != null) && errorUrl.startsWith("file://") && (!failingUrl.equals(errorUrl))) {
// Load URL on UI thread // Load URL on UI thread