From 663a71255ff0e3a7a3d31bda4cd72fa7b4de1283 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Fri, 4 Jul 2014 12:11:19 -0400 Subject: [PATCH 1/7] Move handling of Fullscreen preference to CordovaActivity Makes more sense here since that's where the other FullScreen related changes are. --- .../org/apache/cordova/CordovaActivity.java | 8 +++++--- .../org/apache/cordova/CordovaWebView.java | 20 ------------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java index 18ac670f..89d4c81f 100755 --- a/framework/src/org/apache/cordova/CordovaActivity.java +++ b/framework/src/org/apache/cordova/CordovaActivity.java @@ -213,12 +213,14 @@ public class CordovaActivity extends Activity implements CordovaInterface { Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version."); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - else - { + } else if (this.getBooleanProperty("Fullscreen", false)) { + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } else { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); } + // This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket! Display display = getWindowManager().getDefaultDisplay(); int width = display.getWidth(); diff --git a/framework/src/org/apache/cordova/CordovaWebView.java b/framework/src/org/apache/cordova/CordovaWebView.java index ad5c0f0e..9401e03b 100755 --- a/framework/src/org/apache/cordova/CordovaWebView.java +++ b/framework/src/org/apache/cordova/CordovaWebView.java @@ -49,7 +49,6 @@ import android.view.Gravity; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.webkit.WebBackForwardList; import android.webkit.WebHistoryItem; @@ -138,7 +137,6 @@ public class CordovaWebView extends WebView { { Log.d(TAG, "Your activity must implement CordovaInterface to work"); } - this.loadConfiguration(); this.setup(); } @@ -160,7 +158,6 @@ public class CordovaWebView extends WebView { } this.setWebChromeClient(new CordovaChromeClient(this.cordova, this)); this.initWebViewClient(this.cordova); - this.loadConfiguration(); this.setup(); } @@ -183,7 +180,6 @@ public class CordovaWebView extends WebView { Log.d(TAG, "Your activity must implement CordovaInterface to work"); } this.setWebChromeClient(new CordovaChromeClient(this.cordova, this)); - this.loadConfiguration(); this.setup(); } @@ -208,7 +204,6 @@ public class CordovaWebView extends WebView { } this.setWebChromeClient(new CordovaChromeClient(this.cordova)); this.initWebViewClient(this.cordova); - this.loadConfiguration(); this.setup(); } @@ -654,21 +649,6 @@ public class CordovaWebView extends WebView { } } - /** - * Check configuration parameters from Config. - * Approved list of URLs that can be loaded into Cordova - * - * Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR) - * - */ - private void loadConfiguration() { - - if ("true".equals(this.getProperty("Fullscreen", "false"))) { - this.cordova.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - this.cordova.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - } - /** * Get string property for activity. * From e74baf188fbc9672af47f7b653597ed2abbaa82f Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Fri, 4 Jul 2014 12:19:28 -0400 Subject: [PATCH 2/7] Don't re-parse config.xml in onResume. There shouldn't be any need to. --- framework/src/org/apache/cordova/CordovaActivity.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java index 89d4c81f..97697fcc 100755 --- a/framework/src/org/apache/cordova/CordovaActivity.java +++ b/framework/src/org/apache/cordova/CordovaActivity.java @@ -657,8 +657,6 @@ public class CordovaActivity extends Activity implements CordovaInterface { protected void onResume() { super.onResume(); LOG.d(TAG, "Resuming the App"); - //Reload the configuration - Config.init(this); if (this.activityState == ACTIVITY_STARTING) { this.activityState = ACTIVITY_RUNNING; From af77977fda281e912b9e8805d1d89a44e5ba1f52 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Fri, 4 Jul 2014 14:52:31 -0400 Subject: [PATCH 3/7] Refactor: Move url-filter information into PluginEntry. --- .../org/apache/cordova/ConfigXmlParser.java | 19 +++---- .../src/org/apache/cordova/PluginEntry.java | 49 ++++++++++--------- .../src/org/apache/cordova/PluginManager.java | 25 +++++----- 3 files changed, 46 insertions(+), 47 deletions(-) diff --git a/framework/src/org/apache/cordova/ConfigXmlParser.java b/framework/src/org/apache/cordova/ConfigXmlParser.java index 8062168a..a5958efa 100644 --- a/framework/src/org/apache/cordova/ConfigXmlParser.java +++ b/framework/src/org/apache/cordova/ConfigXmlParser.java @@ -21,8 +21,6 @@ package org.apache.cordova; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -41,7 +39,6 @@ public class ConfigXmlParser { private CordovaPreferences prefs = new CordovaPreferences(); private Whitelist whitelist = new Whitelist(); private ArrayList pluginEntries = new ArrayList(20); - private HashMap> urlMap = new HashMap>(); public Whitelist getWhitelist() { return whitelist; @@ -59,10 +56,6 @@ public class ConfigXmlParser { return launchUrl; } - public HashMap> getPluginUrlMap() { - return urlMap; - } - public void parse(Activity action) { // First checking the class namespace for config.xml int id = action.getResources().getIdentifier("config", "xml", action.getClass().getPackage().getName()); @@ -82,16 +75,17 @@ public class ConfigXmlParser { String service = "", pluginClass = "", paramType = ""; boolean onload = false; boolean insideFeature = false; + ArrayList urlMap = null; + while (eventType != XmlResourceParser.END_DOCUMENT) { if (eventType == XmlResourceParser.START_TAG) { String strNode = xml.getName(); if (strNode.equals("url-filter")) { Log.w(TAG, "Plugin " + service + " is using deprecated tag "); - if (urlMap.get(service) == null) { - urlMap.put(service, new ArrayList(2)); + if (urlMap == null) { + urlMap = new ArrayList(2); } - List filters = urlMap.get(service); - filters.add(xml.getAttributeValue(null, "value")); + urlMap.add(xml.getAttributeValue(null, "value")); } else if (strNode.equals("feature")) { //Check for supported feature sets aka. plugins (Accelerometer, Geolocation, etc) //Set the bit for reading params @@ -130,12 +124,13 @@ public class ConfigXmlParser { { String strNode = xml.getName(); if (strNode.equals("feature")) { - pluginEntries.add(new PluginEntry(service, pluginClass, onload)); + pluginEntries.add(new PluginEntry(service, pluginClass, onload, urlMap)); service = ""; pluginClass = ""; insideFeature = false; onload = false; + urlMap = null; } } try { diff --git a/framework/src/org/apache/cordova/PluginEntry.java b/framework/src/org/apache/cordova/PluginEntry.java index dcc19743..c54f6cb2 100755 --- a/framework/src/org/apache/cordova/PluginEntry.java +++ b/framework/src/org/apache/cordova/PluginEntry.java @@ -18,12 +18,12 @@ */ package org.apache.cordova; +import java.util.List; + import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaPlugin; -//import android.content.Context; -//import android.webkit.WebView; /** * This class represents a service entry object. @@ -52,30 +52,36 @@ public class PluginEntry { */ public boolean onload = false; + private List urlFilters; + + /** + * @param service The name of the service + * @param plugin The plugin associated with this entry + */ + public PluginEntry(String service, CordovaPlugin plugin) { + this(service, plugin.getClass().getName(), true, null); + this.plugin = plugin; + } + /** - * Constructor - * * @param service The name of the service * @param pluginClass The plugin class name * @param onload Create plugin object when HTML page is loaded */ public PluginEntry(String service, String pluginClass, boolean onload) { + this(service, pluginClass, onload, null); + } + + + public PluginEntry(String service, String pluginClass, boolean onload, List urlFilters) { this.service = service; this.pluginClass = pluginClass; this.onload = onload; + this.urlFilters = urlFilters; } - /** - * Alternate constructor - * - * @param service The name of the service - * @param plugin The plugin associated with this entry - */ - public PluginEntry(String service, CordovaPlugin plugin) { - this.service = service; - this.plugin = plugin; - this.pluginClass = plugin.getClass().getName(); - this.onload = false; + public List getUrlFilters() { + return urlFilters; } /** @@ -89,8 +95,7 @@ public class PluginEntry { return this.plugin; } try { - @SuppressWarnings("rawtypes") - Class c = getClassByName(this.pluginClass); + Class c = getClassByName(this.pluginClass); if (isCordovaPlugin(c)) { this.plugin = (CordovaPlugin) c.newInstance(); this.plugin.initialize(ctx, webView); @@ -110,9 +115,8 @@ public class PluginEntry { * @return a reference to the named class * @throws ClassNotFoundException */ - @SuppressWarnings("rawtypes") - private Class getClassByName(final String clazz) throws ClassNotFoundException { - Class c = null; + private Class getClassByName(final String clazz) throws ClassNotFoundException { + Class c = null; if ((clazz != null) && !("".equals(clazz))) { c = Class.forName(clazz); } @@ -122,10 +126,9 @@ public class PluginEntry { /** * Returns whether the given class extends CordovaPlugin. */ - @SuppressWarnings("rawtypes") - private boolean isCordovaPlugin(Class c) { + private boolean isCordovaPlugin(Class c) { if (c != null) { - return org.apache.cordova.CordovaPlugin.class.isAssignableFrom(c); + return CordovaPlugin.class.isAssignableFrom(c); } return false; } diff --git a/framework/src/org/apache/cordova/PluginManager.java b/framework/src/org/apache/cordova/PluginManager.java index c5ffd6cd..410cc6e2 100755 --- a/framework/src/org/apache/cordova/PluginManager.java +++ b/framework/src/org/apache/cordova/PluginManager.java @@ -19,7 +19,6 @@ package org.apache.cordova; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import org.apache.cordova.CordovaWebView; @@ -86,12 +85,12 @@ public class PluginManager { * Load plugins from res/xml/config.xml */ public void loadPlugins() { - ConfigXmlParser parser = new ConfigXmlParser(); - parser.parse(ctx.getActivity()); - for (PluginEntry entry : parser.getPluginEntries()) { - addService(entry); - } - urlMap = parser.getPluginUrlMap(); + ConfigXmlParser parser = new ConfigXmlParser(); + parser.parse(ctx.getActivity()); + urlMap = new HashMap>(); + for (PluginEntry entry : parser.getPluginEntries()) { + addService(entry); + } } /** @@ -206,6 +205,10 @@ public class PluginManager { */ public void addService(PluginEntry entry) { this.entries.put(entry.service, entry); + List urlFilters = entry.getUrlFilters(); + if (urlFilters != null) { + urlMap.put(entry.service, urlFilters); + } } /** @@ -311,11 +314,9 @@ public class PluginManager { * Called when the app navigates or refreshes. */ public void onReset() { - Iterator it = this.entries.values().iterator(); - while (it.hasNext()) { - CordovaPlugin plugin = it.next().plugin; - if (plugin != null) { - plugin.onReset(); + for (PluginEntry entry : this.entries.values()) { + if (entry.plugin != null) { + entry.plugin.onReset(); } } } From 965e4e9b19a25cd14edab6705804893e81a3b292 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Fri, 4 Jul 2014 16:27:16 -0400 Subject: [PATCH 4/7] Fix CordovaPreferences not correctly parsing hex values (valueOf->decode) --- .../apache/cordova/CordovaPreferences.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaPreferences.java b/framework/src/org/apache/cordova/CordovaPreferences.java index 9fa1898f..4b9eb373 100644 --- a/framework/src/org/apache/cordova/CordovaPreferences.java +++ b/framework/src/org/apache/cordova/CordovaPreferences.java @@ -48,7 +48,7 @@ public class CordovaPreferences { name = name.toLowerCase(Locale.ENGLISH); String value = prefs.get(name); if (value != null) { - return "true".equals(value); + return Boolean.parseBoolean(value); } else if (preferencesBundleExtras != null) { Object bundleValue = preferencesBundleExtras.get(name); if (bundleValue instanceof String) { @@ -64,7 +64,8 @@ public class CordovaPreferences { name = name.toLowerCase(Locale.ENGLISH); String value = prefs.get(name); if (value != null) { - return Integer.valueOf(value); + // Use Integer.decode() can't handle it if the highest bit is set. + return (int)(long)Long.decode(value); } else if (preferencesBundleExtras != null) { Object bundleValue = preferencesBundleExtras.get(name); if (bundleValue instanceof String) { @@ -123,30 +124,30 @@ public class CordovaPreferences { action.getIntent().putExtra(name, resource); } else if(name.equals("backgroundcolor")) { - int asInt = Integer.valueOf(value); + int asInt = (int)(long)Long.decode(value); action.getIntent().putExtra(name, asInt); } else if(name.equals("loadurltimeoutvalue")) { - int asInt = Integer.valueOf(value); + int asInt = Integer.decode(value); action.getIntent().putExtra(name, asInt); } else if(name.equals("splashscreendelay")) { - int asInt = Integer.valueOf(value); + int asInt = Integer.decode(value); action.getIntent().putExtra(name, asInt); } else if(name.equals("keeprunning")) { - boolean asBool = "true".equals(value); + boolean asBool = Boolean.parseBoolean(value); action.getIntent().putExtra(name, asBool); } else if(name.equals("inappbrowserstorageenabled")) { - boolean asBool = "true".equals(value); + boolean asBool = Boolean.parseBoolean(value); action.getIntent().putExtra(name, asBool); } else if(name.equals("disallowoverscroll")) { - boolean asBool = "true".equals(value); + boolean asBool = Boolean.parseBoolean(value); action.getIntent().putExtra(name, asBool); } else @@ -154,5 +155,9 @@ public class CordovaPreferences { action.getIntent().putExtra(name, value); } } + // In the normal case, the intent extras are null until the first call to putExtra(). + if (preferencesBundleExtras == null) { + preferencesBundleExtras = action.getIntent().getExtras(); + } } } From b636874bd934d90492e82d144d7de27eef44470b Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Fri, 4 Jul 2014 16:31:19 -0400 Subject: [PATCH 5/7] Deprecate some convenience methods on CordovaActivity They don't add much convenience and the file is too big already. --- .../src/org/apache/cordova/CordovaActivity.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java index 97697fcc..b1110e1c 100755 --- a/framework/src/org/apache/cordova/CordovaActivity.java +++ b/framework/src/org/apache/cordova/CordovaActivity.java @@ -57,7 +57,7 @@ import android.widget.LinearLayout; /** * This class is the main Android activity that represents the Cordova - * application. It should be extended by the user to load the specific + * application. It should be extended by the user to load the specific * html file that contains the application. * * As an example: @@ -91,9 +91,13 @@ public class CordovaActivity extends Activity implements CordovaInterface { // The webview for our app protected CordovaWebView appView; + + @Deprecated // unused. protected CordovaWebViewClient webViewClient; + @Deprecated // Will be removed. Use findViewById() to retrieve views. protected LinearLayout root; + protected ProgressDialog spinnerDialog = null; private final ExecutorService threadPool = Executors.newCachedThreadPool(); @@ -238,10 +242,8 @@ public class CordovaActivity extends Activity implements CordovaInterface { /** * Get the Android activity. - * - * @return the Activity */ - public Activity getActivity() { + @Override public Activity getActivity() { return this; } @@ -426,6 +428,7 @@ public class CordovaActivity extends Activity implements CordovaInterface { /** * Clear the resource cache. */ + @Deprecated // Call method on appView directly. public void clearCache() { if (this.appView == null) { this.init(); @@ -436,6 +439,7 @@ public class CordovaActivity extends Activity implements CordovaInterface { /** * Clear web history in this web view. */ + @Deprecated // Call method on appView directly. public void clearHistory() { this.appView.clearHistory(); } @@ -445,6 +449,7 @@ public class CordovaActivity extends Activity implements CordovaInterface { * * @return true if we went back, false if we are already at top */ + @Deprecated // Call method on appView directly. public boolean backHistory() { if (this.appView != null) { return appView.backHistory(); @@ -727,6 +732,7 @@ public class CordovaActivity extends Activity implements CordovaInterface { * * @param statement */ + @Deprecated // Call method on appView directly. public void sendJavascript(String statement) { if (this.appView != null) { this.appView.jsMessageQueue.addJavaScript(statement); @@ -949,6 +955,7 @@ public class CordovaActivity extends Activity implements CordovaInterface { * @param clearHistory Clear the history stack, so new page becomes top of history * @param params Parameters for new app */ + @Deprecated // Call method on appView directly. public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap params) { if (this.appView != null) { appView.showWebPage(url, openExternal, clearHistory, params); From 705991e5b037743e632934b3c6ee98976e18d3f8 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Fri, 4 Jul 2014 16:32:09 -0400 Subject: [PATCH 6/7] Refactor: Use ConfigXmlParser in activity. Adds CordovaWebView.init() This does subtly change the API surface due to CordovaWebView.init(), but only minimally, and is backwards compatibly with the default generated projects from prior versions. --- bin/templates/project/Activity.java | 7 +- framework/src/org/apache/cordova/Config.java | 2 +- .../org/apache/cordova/CordovaActivity.java | 229 +++++++----------- .../apache/cordova/CordovaChromeClient.java | 18 +- .../org/apache/cordova/CordovaWebView.java | 187 +++++--------- .../apache/cordova/CordovaWebViewClient.java | 7 +- .../src/org/apache/cordova/PluginManager.java | 55 ++--- 7 files changed, 176 insertions(+), 329 deletions(-) diff --git a/bin/templates/project/Activity.java b/bin/templates/project/Activity.java index a515ab0b..1bd9e1cb 100644 --- a/bin/templates/project/Activity.java +++ b/bin/templates/project/Activity.java @@ -22,16 +22,13 @@ package __ID__; import android.os.Bundle; import org.apache.cordova.*; -public class __ACTIVITY__ extends CordovaActivity +public class __ACTIVITY__ extends CordovaActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - super.init(); // Set by in config.xml - super.loadUrl(Config.getStartUrl()); - //super.loadUrl("file:///android_asset/www/index.html"); + loadUrl(launchUrl); } } - diff --git a/framework/src/org/apache/cordova/Config.java b/framework/src/org/apache/cordova/Config.java index 7865e004..dfb039d8 100644 --- a/framework/src/org/apache/cordova/Config.java +++ b/framework/src/org/apache/cordova/Config.java @@ -25,7 +25,7 @@ import android.util.Log; public class Config { private static final String TAG = "Config"; - private static ConfigXmlParser parser; + static ConfigXmlParser parser; private Config() { } diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java index b1110e1c..a3b6314c 100755 --- a/framework/src/org/apache/cordova/CordovaActivity.java +++ b/framework/src/org/apache/cordova/CordovaActivity.java @@ -18,8 +18,8 @@ */ package org.apache.cordova; +import java.util.ArrayList; import java.util.HashMap; -import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -72,9 +72,8 @@ import android.widget.LinearLayout; * @Override * public void onCreate(Bundle savedInstanceState) { * super.onCreate(savedInstanceState); - * super.init(); * // Load your application - * super.loadUrl(Config.getStartUrl()); + * loadUrl(launchUrl); * } * } * @@ -110,10 +109,6 @@ public class CordovaActivity extends Activity implements CordovaInterface { protected CordovaPlugin activityResultCallback = null; protected boolean activityResultKeepRunning; - // Default background color for activity - // (this is not the color for the webview, which is set in HTML) - private int backgroundColor = Color.BLACK; - /* * The variables below are used to cache some of the activity properties. */ @@ -133,6 +128,12 @@ public class CordovaActivity extends Activity implements CordovaInterface { private String initCallbackClass; + // Read from config.xml: + protected CordovaPreferences preferences; + protected Whitelist whitelist; + protected String launchUrl; + protected ArrayList pluginEntries; + /** * Sets the authentication token. * @@ -194,10 +195,8 @@ public class CordovaActivity extends Activity implements CordovaInterface { /** * Called when the activity is first created. */ - @SuppressWarnings("deprecation") @Override public void onCreate(Bundle savedInstanceState) { - Config.init(this); LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting"); LOG.d(TAG, "CordovaActivity.onCreate()"); super.onCreate(savedInstanceState); @@ -207,17 +206,19 @@ public class CordovaActivity extends Activity implements CordovaInterface { initCallbackClass = savedInstanceState.getString("callbackClass"); } - if(!this.getBooleanProperty("ShowTitle", false)) + loadConfig(); + + if(!preferences.getBoolean("ShowTitle", false)) { getWindow().requestFeature(Window.FEATURE_NO_TITLE); } - if(this.getBooleanProperty("SetFullscreen", false)) + if(preferences.getBoolean("SetFullscreen", false)) { Log.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version."); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - } else if (this.getBooleanProperty("Fullscreen", false)) { + } else if (preferences.getBoolean("Fullscreen", false)) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } else { @@ -225,6 +226,35 @@ public class CordovaActivity extends Activity implements CordovaInterface { WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); } + appView = makeWebView(); + appView.init(this, makeWebViewClient(appView), makeChromeClient(appView), pluginEntries); + + // TODO: Have the views set this themselves. + if (preferences.getBoolean("DisallowOverscroll", false)) { + appView.setOverScrollMode(View.OVER_SCROLL_NEVER); + } + createViews(); + + // TODO: Make this a preference (CB-6153) + // Setup the hardware volume controls to handle volume control + setVolumeControlStream(AudioManager.STREAM_MUSIC); + } + + protected void loadConfig() { + ConfigXmlParser parser = new ConfigXmlParser(); + parser.parse(this); + preferences = parser.getPreferences(); + preferences.setPreferencesBundle(getIntent().getExtras()); + preferences.copyIntoIntentExtras(this); + whitelist = parser.getWhitelist(); + launchUrl = parser.getLaunchUrl(); + pluginEntries = parser.getPluginEntries(); + Config.parser = parser; + } + + @SuppressWarnings("deprecation") + protected void createViews() { + // This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket! // This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket! Display display = getWindowManager().getDefaultDisplay(); int width = display.getWidth(); @@ -232,12 +262,23 @@ public class CordovaActivity extends Activity implements CordovaInterface { root = new LinearLayoutSoftKeyboardDetect(this, width, height); root.setOrientation(LinearLayout.VERTICAL); - root.setBackgroundColor(this.backgroundColor); root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0.0F)); - // Setup the hardware volume controls to handle volume control - setVolumeControlStream(AudioManager.STREAM_MUSIC); + appView.setId(100); + appView.setLayoutParams(new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, + 1.0F)); + + // Add web view but make it invisible while loading URL + appView.setVisibility(View.INVISIBLE); + root.addView((View) appView); + setContentView(root); + + // TODO: Setting this on the appView causes it to show when . + int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK); + root.setBackgroundColor(backgroundColor); } /** @@ -266,11 +307,7 @@ public class CordovaActivity extends Activity implements CordovaInterface { * @param webView the default constructed web view object */ protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) { - if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { - return new CordovaWebViewClient(this, webView); - } else { - return new IceCreamCordovaWebViewClient(this, webView); - } + return webView.makeWebViewClient(this); } /** @@ -282,78 +319,46 @@ public class CordovaActivity extends Activity implements CordovaInterface { * @param webView the default constructed web view object */ protected CordovaChromeClient makeChromeClient(CordovaWebView webView) { - return new CordovaChromeClient(this, webView); + return webView.makeChromeClient(this); } - /** - * Create and initialize web container with default web view objects. - */ + @Deprecated // No need to call init() anymore. public void init() { - CordovaWebView webView = makeWebView(); - this.init(webView, makeWebViewClient(webView), makeChromeClient(webView)); + this.init(appView, null, null); } - /** - * Initialize web container with web view objects. - * - * @param webView - * @param webViewClient - * @param webChromeClient - */ @SuppressLint("NewApi") + @Deprecated // No need to call init() anymore. public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) { LOG.d(TAG, "CordovaActivity.init()"); - // Set up web container - this.appView = webView; - this.appView.setId(100); + appView = webView; - this.appView.setWebViewClient(webViewClient); - this.appView.setWebChromeClient(webChromeClient); - webViewClient.setWebView(this.appView); - webChromeClient.setWebView(this.appView); - - this.appView.setLayoutParams(new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT, - 1.0F)); - - if (this.getBooleanProperty("DisallowOverscroll", false)) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) { - this.appView.setOverScrollMode(CordovaWebView.OVER_SCROLL_NEVER); - } + if (webViewClient != null) { + this.appView.setWebViewClient(webViewClient); + webViewClient.setWebView(this.appView); + } + if (webChromeClient != null) { + this.appView.setWebChromeClient(webChromeClient); + webChromeClient.setWebView(this.appView); } - - // Add web view but make it invisible while loading URL - this.appView.setVisibility(View.INVISIBLE); - this.root.addView(this.appView); - setContentView(this.root); } /** * Load the url into the webview. */ public void loadUrl(String url) { - - // Init web view if not already done - if (this.appView == null) { - this.init(); - } - - this.splashscreenTime = this.getIntegerProperty("SplashScreenDelay", this.splashscreenTime); - if(this.splashscreenTime > 0) + this.splashscreenTime = preferences.getInteger("SplashScreenDelay", this.splashscreenTime); + String splash = preferences.getString("SplashScreen", null); + if(this.splashscreenTime > 0 && splash != null) { - this.splashscreen = this.getIntegerProperty("SplashScreen", 0); + this.splashscreen = getResources().getIdentifier(splash, "drawable", getClass().getPackage().getName());; if(this.splashscreen != 0) { this.showSplashScreen(this.splashscreenTime); } } - // Set backgroundColor - this.backgroundColor = this.getIntegerProperty("BackgroundColor", Color.BLACK); - this.root.setBackgroundColor(this.backgroundColor); - // If keepRunning this.keepRunning = this.getBooleanProperty("KeepRunning", true); @@ -430,9 +435,6 @@ public class CordovaActivity extends Activity implements CordovaInterface { */ @Deprecated // Call method on appView directly. public void clearCache() { - if (this.appView == null) { - this.init(); - } this.appView.clearCache(true); } @@ -459,103 +461,34 @@ public class CordovaActivity extends Activity implements CordovaInterface { /** * Get boolean property for activity. - * - * @param name - * @param defaultValue - * @return the boolean value of the named property */ + @Deprecated // Call method on preferences directly. public boolean getBooleanProperty(String name, boolean defaultValue) { - Bundle bundle = this.getIntent().getExtras(); - if (bundle == null) { - return defaultValue; - } - name = name.toLowerCase(Locale.getDefault()); - Boolean p; - try { - p = (Boolean) bundle.get(name); - } catch (ClassCastException e) { - String s = bundle.get(name).toString(); - if ("true".equals(s)) { - p = true; - } - else { - p = false; - } - } - if (p == null) { - return defaultValue; - } - return p.booleanValue(); + return preferences.getBoolean(name, defaultValue); } /** * Get int property for activity. - * - * @param name - * @param defaultValue - * @return the int value for the named property */ + @Deprecated // Call method on preferences directly. public int getIntegerProperty(String name, int defaultValue) { - Bundle bundle = this.getIntent().getExtras(); - if (bundle == null) { - return defaultValue; - } - name = name.toLowerCase(Locale.getDefault()); - Integer p; - try { - p = (Integer) bundle.get(name); - } catch (ClassCastException e) { - p = Integer.parseInt(bundle.get(name).toString()); - } - if (p == null) { - return defaultValue; - } - return p.intValue(); + return preferences.getInteger(name, defaultValue); } /** * Get string property for activity. - * - * @param name - * @param defaultValue - * @return the String value for the named property */ + @Deprecated // Call method on preferences directly. public String getStringProperty(String name, String defaultValue) { - Bundle bundle = this.getIntent().getExtras(); - if (bundle == null) { - return defaultValue; - } - name = name.toLowerCase(Locale.getDefault()); - String p = bundle.getString(name); - if (p == null) { - return defaultValue; - } - return p; + return preferences.getString(name, defaultValue); } /** * Get double property for activity. - * - * @param name - * @param defaultValue - * @return the double value for the named property */ + @Deprecated // Call method on preferences directly. public double getDoubleProperty(String name, double defaultValue) { - Bundle bundle = this.getIntent().getExtras(); - if (bundle == null) { - return defaultValue; - } - name = name.toLowerCase(Locale.getDefault()); - Double p; - try { - p = (Double) bundle.get(name); - } catch (ClassCastException e) { - p = Double.parseDouble(bundle.get(name).toString()); - } - if (p == null) { - return defaultValue; - } - return p.doubleValue(); + return preferences.getDouble(name, defaultValue); } /** diff --git a/framework/src/org/apache/cordova/CordovaChromeClient.java b/framework/src/org/apache/cordova/CordovaChromeClient.java index f2c33501..0337098b 100755 --- a/framework/src/org/apache/cordova/CordovaChromeClient.java +++ b/framework/src/org/apache/cordova/CordovaChromeClient.java @@ -72,31 +72,17 @@ public class CordovaChromeClient extends WebChromeClient { // File Chooser public ValueCallback mUploadMessage; - /** - * Constructor. - * - * @param cordova - */ + @Deprecated public CordovaChromeClient(CordovaInterface cordova) { this.cordova = cordova; } - /** - * Constructor. - * - * @param ctx - * @param app - */ public CordovaChromeClient(CordovaInterface ctx, CordovaWebView app) { this.cordova = ctx; this.appView = app; } - /** - * Constructor. - * - * @param view - */ + @Deprecated public void setWebView(CordovaWebView view) { this.appView = view; } diff --git a/framework/src/org/apache/cordova/CordovaWebView.java b/framework/src/org/apache/cordova/CordovaWebView.java index 9401e03b..8d0b4a9b 100755 --- a/framework/src/org/apache/cordova/CordovaWebView.java +++ b/framework/src/org/apache/cordova/CordovaWebView.java @@ -21,9 +21,12 @@ package org.apache.cordova; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Locale; +import java.util.Map; import org.apache.cordova.Config; import org.apache.cordova.CordovaInterface; @@ -122,114 +125,51 @@ public class CordovaWebView extends WebView { ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER); - /** - * Constructor. - * - * @param context - */ public CordovaWebView(Context context) { - super(context); - if (CordovaInterface.class.isInstance(context)) - { - this.cordova = (CordovaInterface) context; - } - else - { - Log.d(TAG, "Your activity must implement CordovaInterface to work"); - } - this.setup(); + this(context, null); } - /** - * Constructor. - * - * @param context - * @param attrs - */ public CordovaWebView(Context context, AttributeSet attrs) { super(context, attrs); - if (CordovaInterface.class.isInstance(context)) - { - this.cordova = (CordovaInterface) context; - } - else - { - Log.d(TAG, "Your activity must implement CordovaInterface to work"); - } - this.setWebChromeClient(new CordovaChromeClient(this.cordova, this)); - this.initWebViewClient(this.cordova); - this.setup(); } - /** - * Constructor. - * - * @param context - * @param attrs - * @param defStyle - * - */ + @Deprecated public CordovaWebView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - if (CordovaInterface.class.isInstance(context)) - { - this.cordova = (CordovaInterface) context; - } - else - { - Log.d(TAG, "Your activity must implement CordovaInterface to work"); - } - this.setWebChromeClient(new CordovaChromeClient(this.cordova, this)); - this.setup(); } - /** - * Constructor. - * - * @param context - * @param attrs - * @param defStyle - * @param privateBrowsing - */ @TargetApi(11) + @Deprecated public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) { super(context, attrs, defStyle, privateBrowsing); - if (CordovaInterface.class.isInstance(context)) - { - this.cordova = (CordovaInterface) context; - } - else - { - Log.d(TAG, "Your activity must implement CordovaInterface to work"); - } - this.setWebChromeClient(new CordovaChromeClient(this.cordova)); - this.initWebViewClient(this.cordova); - this.setup(); } - /** - * set the WebViewClient, but provide special case handling for IceCreamSandwich. - */ - private void initWebViewClient(CordovaInterface cordova) { - if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB || - android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) - { - this.setWebViewClient(new CordovaWebViewClient(this.cordova, this)); - } - else - { - this.setWebViewClient(new IceCreamCordovaWebViewClient(this.cordova, this)); + // Use two-phase init so that the control will work with XML layouts. + public void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient chromeClient, List pluginEntries) { + if (this.cordova != null) { + throw new IllegalStateException(); } + this.cordova = cordova; + this.viewClient = webViewClient; + this.chromeClient = chromeClient; + super.setWebChromeClient(chromeClient); + super.setWebViewClient(webViewClient); + + pluginManager = new PluginManager(this, this.cordova, pluginEntries); + jsMessageQueue = new NativeToJsMessageQueue(this, cordova); + exposedJsApi = new ExposedJsApi(pluginManager, jsMessageQueue); + resourceApi = new CordovaResourceApi(this.getContext(), pluginManager); + + initWebViewSettings(); + exposeJsInterface(); } - /** - * Initialize webview. - */ + @SuppressLint("SetJavaScriptEnabled") @SuppressWarnings("deprecation") - @SuppressLint("NewApi") - private void setup() { + private void initWebViewSettings() { this.setInitialScale(0); this.setVerticalScrollBarEnabled(false); + // TODO: The Activity is the one that should call requestFocus(). if (shouldRequestFocusOnInit()) { this.requestFocusFromTouch(); } @@ -270,31 +210,17 @@ public class CordovaWebView extends WebView { Level16Apis.enableUniversalAccess(settings); // Enable database // We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16 - String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); + String databasePath = getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); settings.setDatabaseEnabled(true); settings.setDatabasePath(databasePath); //Determine whether we're in debug or release mode, and turn on Debugging! - try { - final String packageName = this.cordova.getActivity().getPackageName(); - final PackageManager pm = this.cordova.getActivity().getPackageManager(); - ApplicationInfo appInfo; - - appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); - - if((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 && - android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) - { - setWebContentsDebuggingEnabled(true); - } - } catch (IllegalArgumentException e) { - Log.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! "); - e.printStackTrace(); - } catch (NameNotFoundException e) { - Log.d(TAG, "This should never happen: Your application's package can't be found."); - e.printStackTrace(); - } + ApplicationInfo appInfo = getContext().getApplicationContext().getApplicationInfo(); + if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0 && + android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + enableRemoteDebugging(); + } settings.setGeolocationDatabasePath(databasePath); @@ -307,13 +233,12 @@ public class CordovaWebView extends WebView { // Enable AppCache // Fix for CB-2282 settings.setAppCacheMaxSize(5 * 1048576); - String pathToCache = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); - settings.setAppCachePath(pathToCache); + settings.setAppCachePath(databasePath); settings.setAppCacheEnabled(true); // Fix for CB-1405 // Google issue 4641 - this.updateUserAgentString(); + settings.getUserAgentString(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); @@ -321,18 +246,33 @@ public class CordovaWebView extends WebView { this.receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - updateUserAgentString(); + getSettings().getUserAgentString(); } }; - this.cordova.getActivity().registerReceiver(this.receiver, intentFilter); + getContext().registerReceiver(this.receiver, intentFilter); } // end CB-1405 + } - pluginManager = new PluginManager(this, this.cordova); - jsMessageQueue = new NativeToJsMessageQueue(this, cordova); - exposedJsApi = new ExposedJsApi(pluginManager, jsMessageQueue); - resourceApi = new CordovaResourceApi(this.getContext(), pluginManager); - exposeJsInterface(); + @TargetApi(Build.VERSION_CODES.KITKAT) + private void enableRemoteDebugging() { + try { + WebView.setWebContentsDebuggingEnabled(true); + } catch (IllegalArgumentException e) { + Log.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! "); + e.printStackTrace(); + } + } + + public CordovaChromeClient makeChromeClient(CordovaInterface cordova) { + return new CordovaChromeClient(cordova, this); + } + + public CordovaWebViewClient makeWebViewClient(CordovaInterface cordova) { + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + return new CordovaWebViewClient(cordova, this); + } + return new IceCreamCordovaWebViewClient(cordova, this); } /** @@ -345,13 +285,8 @@ public class CordovaWebView extends WebView { return true; } - private void updateUserAgentString() { - this.getSettings().getUserAgentString(); - } - private void exposeJsInterface() { - int SDK_INT = Build.VERSION.SDK_INT; - if ((SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) { + if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) { Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old."); // Bug being that Java Strings do not get converted to JS strings automatically. // This isn't hard to work-around on the JS side, but it's easier to just @@ -363,9 +298,8 @@ public class CordovaWebView extends WebView { /** * Set the WebViewClient. - * - * @param client */ + @Deprecated // Set this in init() instead. public void setWebViewClient(CordovaWebViewClient client) { this.viewClient = client; super.setWebViewClient(client); @@ -373,9 +307,8 @@ public class CordovaWebView extends WebView { /** * Set the WebChromeClient. - * - * @param client */ + @Deprecated // Set this in init() instead. public void setWebChromeClient(CordovaChromeClient client) { this.chromeClient = client; super.setWebChromeClient(client); @@ -849,7 +782,7 @@ public class CordovaWebView extends WebView { // unregister the receiver if (this.receiver != null) { try { - this.cordova.getActivity().unregisterReceiver(this.receiver); + getContext().unregisterReceiver(this.receiver); } catch (Exception e) { Log.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e); } diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java index 9e276d75..65d8ff67 100755 --- a/framework/src/org/apache/cordova/CordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java @@ -64,11 +64,7 @@ public class CordovaWebViewClient extends WebViewClient { /** The authorization tokens. */ private Hashtable authenticationTokens = new Hashtable(); - /** - * Constructor. - * - * @param cordova - */ + @Deprecated public CordovaWebViewClient(CordovaInterface cordova) { this.cordova = cordova; } @@ -90,6 +86,7 @@ public class CordovaWebViewClient extends WebViewClient { * * @param view */ + @Deprecated public void setWebView(CordovaWebView view) { this.appView = view; helper = new CordovaUriHelper(cordova, view); diff --git a/framework/src/org/apache/cordova/PluginManager.java b/framework/src/org/apache/cordova/PluginManager.java index 410cc6e2..4bd4754e 100755 --- a/framework/src/org/apache/cordova/PluginManager.java +++ b/framework/src/org/apache/cordova/PluginManager.java @@ -52,11 +52,31 @@ public class PluginManager { // Stores mapping of Plugin Name -> values. // Using is deprecated. - protected HashMap> urlMap; + protected HashMap> urlMap = new HashMap>(); - public PluginManager(CordovaWebView app, CordovaInterface ctx) { - this.ctx = ctx; - this.app = app; + @Deprecated + PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova) { + this(cordovaWebView, cordova, null); + } + + PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, List pluginEntries) { + this.ctx = cordova; + this.app = cordovaWebView; + if (pluginEntries == null) { + ConfigXmlParser parser = new ConfigXmlParser(); + parser.parse(ctx.getActivity()); + pluginEntries = parser.getPluginEntries(); + } + setPluginEntries(pluginEntries); + } + + public void setPluginEntries(List pluginEntries) { + this.onPause(false); + this.onDestroy(); + this.clearPluginObjects(); + for (PluginEntry entry : pluginEntries) { + addService(entry); + } } /** @@ -64,33 +84,14 @@ public class PluginManager { */ public void init() { LOG.d(TAG, "init()"); - - // If first time, then load plugins from config.xml file - if (urlMap == null) { - this.loadPlugins(); - } - - // Stop plugins on current HTML page and discard plugin objects - else { - this.onPause(false); - this.onDestroy(); - this.clearPluginObjects(); - } - - // Start up all plugins that have onload specified + this.onPause(false); + this.onDestroy(); + this.clearPluginObjects(); this.startupPlugins(); } - /** - * Load plugins from res/xml/config.xml - */ + @Deprecated public void loadPlugins() { - ConfigXmlParser parser = new ConfigXmlParser(); - parser.parse(ctx.getActivity()); - urlMap = new HashMap>(); - for (PluginEntry entry : parser.getPluginEntries()) { - addService(entry); - } } /** From 0f156081750589864e68bfb4f93ed71557e5cb43 Mon Sep 17 00:00:00 2001 From: Andrew Grieve Date: Mon, 7 Jul 2014 13:07:51 -0400 Subject: [PATCH 7/7] CB-4404 Revert setting android:windowSoftInputMode to "adjustPan" "adjustResize" is what the value has been set to for the longest time (due to it being in the wrong place in the manifest). "adjustResize" is a better default value anyways. --- bin/templates/project/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/templates/project/AndroidManifest.xml b/bin/templates/project/AndroidManifest.xml index 5336be31..cea9dc31 100644 --- a/bin/templates/project/AndroidManifest.xml +++ b/bin/templates/project/AndroidManifest.xml @@ -36,7 +36,7 @@ android:label="@string/activity_name" android:launchMode="singleTop" android:theme="@android:style/Theme.Black.NoTitleBar" - android:windowSoftInputMode="adjustPan" + android:windowSoftInputMode="adjustResize" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale">