From 34ab64655df83df6f2f1c66eb9bac80daa85edd5 Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Wed, 25 Nov 2009 17:25:16 -0800 Subject: [PATCH] Experiments with 2.0 and backwards compatibility --- framework/src/com/phonegap/DroidGap.java | 45 ++++++-------- framework/src/com/phonegap/GapClient.java | 61 +++++++++++++++++++ .../src/com/phonegap/WebViewReflect.java | 61 +++++++++++++++++++ 3 files changed, 141 insertions(+), 26 deletions(-) create mode 100644 framework/src/com/phonegap/GapClient.java create mode 100644 framework/src/com/phonegap/WebViewReflect.java diff --git a/framework/src/com/phonegap/DroidGap.java b/framework/src/com/phonegap/DroidGap.java index 18e1a9ef..8090c0ca 100644 --- a/framework/src/com/phonegap/DroidGap.java +++ b/framework/src/com/phonegap/DroidGap.java @@ -22,7 +22,6 @@ package com.phonegap; * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import java.lang.reflect.Field; import android.app.Activity; import android.app.AlertDialog; @@ -38,15 +37,17 @@ import android.view.WindowManager; import android.webkit.JsResult; import android.webkit.WebChromeClient; import android.webkit.WebSettings; +import android.webkit.WebStorage; import android.webkit.WebView; import android.webkit.WebSettings.LayoutAlgorithm; import android.widget.LinearLayout; +import android.os.Build.*; public class DroidGap extends Activity { - + private static final String LOG_TAG = "DroidGap"; protected WebView appView; - private LinearLayout root; + private LinearLayout root; private String uri; private PhoneGap gap; @@ -57,6 +58,7 @@ public class DroidGap extends Activity { private FileUtils fs; private NetworkManager netMan; private CompassListener mCompass; + private WebViewReflect eclairCheck; /** Called when the activity is first created. */ @Override @@ -80,9 +82,11 @@ public class DroidGap extends Activity { appView = new WebView(this); appView.setLayoutParams(webviewParams); - + + WebViewReflect.checkCompatibility(); + /* This changes the setWebChromeClient to log alerts to LogCat! Important for Javascript Debugging */ - appView.setWebChromeClient(new GapClient(this)); + appView.setWebChromeClient(new PhoneGapClient(this)); appView.setInitialScale(100); WebSettings settings = appView.getSettings(); @@ -90,13 +94,17 @@ public class DroidGap extends Activity { settings.setJavaScriptCanOpenWindowsAutomatically(true); settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL); + + Package pack = this.getClass().getPackage(); + String appPackage = pack.getName(); + + WebViewReflect.setStorage(settings, true, "/data/data/" + appPackage + "/app_database/"); + /* Bind the appView object to the gap class methods */ bindBrowser(appView); root.addView(appView); - setContentView(root); - - + setContentView(root); } @Override @@ -137,28 +145,13 @@ public class DroidGap extends Activity { * Provides a hook for calling "alert" from javascript. Useful for * debugging your javascript. */ - final class GapClient extends WebChromeClient { + final class PhoneGapClient extends GapClient { - Context mCtx; - GapClient(Context ctx) - { - mCtx = ctx; + PhoneGapClient(Context ctx){ + super(ctx); } - @Override - public boolean onJsAlert(WebView view, String url, String message, JsResult result) { - Log.d(LOG_TAG, message); - // This shows the dialog box. This can be commented out for dev - AlertDialog.Builder alertBldr = new AlertDialog.Builder(mCtx); - alertBldr.setMessage(message); - alertBldr.setTitle("Alert"); - alertBldr.show(); - result.confirm(); - return true; - } - } - // This is required to start the camera activity! It has to come from the previous activity public void startCamera(int quality) diff --git a/framework/src/com/phonegap/GapClient.java b/framework/src/com/phonegap/GapClient.java new file mode 100644 index 00000000..1aae88a8 --- /dev/null +++ b/framework/src/com/phonegap/GapClient.java @@ -0,0 +1,61 @@ +package com.phonegap; + +import android.app.AlertDialog; +import android.content.Context; +import android.util.Log; +import android.webkit.JsResult; +import android.webkit.WebChromeClient; +import android.webkit.WebStorage; +import android.webkit.WebView; + + +public class GapClient extends WebChromeClient { + + private static final String LOG_TAG = "DroidGap"; + private long MAX_QUOTA = 2000000; + private WebChromeClient mInstance; + + /* class initialization fails when this throws an exception */ + static { + try { + + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + Context mCtx; + GapClient(Context ctx) + { + mCtx = ctx; + } + + @Override + public boolean onJsAlert(WebView view, String url, String message, JsResult result) { + Log.d(LOG_TAG, message); + // This shows the dialog box. This can be commented out for dev + AlertDialog.Builder alertBldr = new AlertDialog.Builder(mCtx); + alertBldr.setMessage(message); + alertBldr.setTitle("Alert"); + alertBldr.show(); + result.confirm(); + return true; + } + + public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize, + long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) + { + + if( estimatedSize < MAX_QUOTA) + { + long newQuota = estimatedSize; + quotaUpdater.updateQuota(newQuota); + } + else + { + // Set the quota to whatever it is and force an error + // TODO: get docs on how to handle this properly + quotaUpdater.updateQuota(currentQuota); + } + } +} diff --git a/framework/src/com/phonegap/WebViewReflect.java b/framework/src/com/phonegap/WebViewReflect.java new file mode 100644 index 00000000..3d1d2cd2 --- /dev/null +++ b/framework/src/com/phonegap/WebViewReflect.java @@ -0,0 +1,61 @@ +package com.phonegap; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import android.webkit.WebSettings; + +public class WebViewReflect { + private static Method mWebSettings_setDatabaseEnabled; + + static + { + checkCompatibility(); + } + + private static void setDatabaseEnabled(boolean e) throws IOException { + try + { + mWebSettings_setDatabaseEnabled.invoke(e); + } + catch (InvocationTargetException ite) { + /* unpack original exception when possible */ + Throwable cause = ite.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } else if (cause instanceof RuntimeException) { + throw (RuntimeException) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } else { + /* unexpected checked exception; wrap and re-throw */ + throw new RuntimeException(ite); + } + } catch (IllegalAccessException ie) { + System.err.println("unexpected " + ie); + } + } + + public static void checkCompatibility() { + try { + mWebSettings_setDatabaseEnabled = WebSettings.class.getMethod( + "setDatabaseEnabled", new Class[] { boolean.class } ); + /* success, this is a newer device */ + } catch (NoSuchMethodException nsme) { + /* failure, must be older device */ + } + } + + + public static void setStorage(WebSettings setting, boolean enable, String path) { + if (mWebSettings_setDatabaseEnabled != null) { + /* feature is supported */ + setting.setDatabaseEnabled(enable); + setting.setDatabasePath(path); + } else { + /* feature not supported, do something else */ + System.out.println("dump not supported"); + } + } +}