Merge branch 'master' into 4.0.x (ConfigXmlParser + two-phase init)

Conflicts:
	framework/src/org/apache/cordova/CordovaActivity.java
	framework/src/org/apache/cordova/CordovaChromeClient.java
	framework/src/org/apache/cordova/CordovaWebView.java
	framework/src/org/apache/cordova/CordovaWebViewClient.java
	framework/src/org/apache/cordova/PluginManager.java
This commit is contained in:
Andrew Grieve 2014-07-07 16:23:51 -04:00
commit 1571b26a65
13 changed files with 261 additions and 467 deletions

View File

@ -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 <content src="index.html" /> in config.xml
super.loadUrl(Config.getStartUrl());
//super.loadUrl("file:///android_asset/www/index.html");
loadUrl(launchUrl);
}
}

View File

@ -38,7 +38,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">
<intent-filter android:label="@string/launcher_name">
<action android:name="android.intent.action.MAIN" />

View File

@ -46,8 +46,6 @@ import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.util.Log;
/**
* This class is the WebChromeClient that implements callbacks for our web view.
* The kind of callbacks that happen here are on the chrome outside the document,
@ -62,10 +60,10 @@ import android.util.Log;
public class AndroidChromeClient extends WebChromeClient implements CordovaChromeClient {
public static final int FILECHOOSER_RESULTCODE = 5173;
private static final String LOG_TAG = "CordovaChromeClient";
private static final String LOG_TAG = "AndroidChromeClient";
private long MAX_QUOTA = 100 * 1024 * 1024;
protected CordovaInterface cordova;
protected AndroidWebView appView;
protected final CordovaInterface cordova;
protected final AndroidWebView appView;
// the video progress view
private View mVideoProgressView;
@ -73,12 +71,6 @@ public class AndroidChromeClient extends WebChromeClient implements CordovaChrom
// File Chooser
public ValueCallback<Uri> mUploadMessage;
/**
* Constructor.
*
* @param ctx
* @param app
*/
public AndroidChromeClient(CordovaInterface ctx, AndroidWebView app) {
this.cordova = ctx;
this.appView = app;

View File

@ -23,6 +23,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import org.apache.cordova.Config;
@ -30,7 +31,6 @@ import org.apache.cordova.CordovaInterface;
import org.apache.cordova.LOG;
import org.apache.cordova.PluginManager;
import org.apache.cordova.PluginResult;
import org.json.JSONException;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
@ -39,8 +39,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@ -50,7 +48,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;
@ -61,6 +58,7 @@ import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
/*
* This class is our web view.
*
@ -124,133 +122,51 @@ public class AndroidWebView extends WebView implements CordovaWebView {
ViewGroup.LayoutParams.MATCH_PARENT,
Gravity.CENTER);
/**
* Constructor.
*
* @param context
*/
/** Used when created via reflection. */
public AndroidWebView(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.loadConfiguration();
this.setup();
this(context, null);
}
/**
* Constructor.
*
* @param context
* @param attrs
*/
/** Required to allow view to be used within XML layouts. */
public AndroidWebView(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.loadConfiguration();
this.setup();
}
/**
* Constructor.
*
* @param context
* @param attrs
* @param defStyle
*
*/
public AndroidWebView(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.loadConfiguration();
this.setup();
}
/**
* Constructor.
*
* @param context
* @param attrs
* @param defStyle
* @param privateBrowsing
*/
@TargetApi(11)
public AndroidWebView(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.loadConfiguration();
this.setup();
}
/**
* Create a default WebViewClient object for this webview. This can be overridden by the
* main application's CordovaActivity subclass.
*
* There are two possible client objects that can be returned:
* AndroidWebViewClient for android < 3.0
* IceCreamCordovaWebViewClient for Android >= 3.0 (Supports shouldInterceptRequest)
*/
// Use two-phase init so that the control will work with XML layouts.
@Override
public CordovaWebViewClient makeWebViewClient() {
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
{
return (CordovaWebViewClient) new AndroidWebViewClient(this.cordova, this);
}
else
{
return (CordovaWebViewClient) new IceCreamCordovaWebViewClient(this.cordova, this);
public void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient, List<PluginEntry> pluginEntries) {
if (this.cordova != null) {
throw new IllegalStateException();
}
this.cordova = cordova;
setWebChromeClient(webChromeClient);
setWebViewClient(webViewClient);
pluginManager = new PluginManager(this, this.cordova, pluginEntries);
jsMessageQueue = new NativeToJsMessageQueue(this, cordova);
exposedJsApi = new AndroidExposedJsApi(pluginManager, jsMessageQueue);
resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
initWebViewSettings();
exposeJsInterface();
}
/**
* Create a default WebViewClient object for this webview. This can be overridden by the
* main application's CordovaActivity subclass.
*/
@Override
public CordovaChromeClient makeWebChromeClient() {
return (CordovaChromeClient) new AndroidChromeClient(this.cordova, this);
}
/**
* 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();
}
this.setInitialScale(0);
this.setVerticalScrollBarEnabled(false);
if (shouldRequestFocusOnInit()) {
this.requestFocusFromTouch();
}
// Enable JavaScript
WebSettings settings = this.getSettings();
this.requestFocusFromTouch();
}
// Enable JavaScript
final WebSettings settings = this.getSettings();
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
@ -286,31 +202,17 @@ public class AndroidWebView extends WebView implements CordovaWebView {
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);
@ -323,13 +225,12 @@ public class AndroidWebView extends WebView implements CordovaWebView {
// 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);
@ -337,18 +238,35 @@ public class AndroidWebView extends WebView implements CordovaWebView {
this.receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateUserAgentString();
settings.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 AndroidExposedJsApi(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();
}
}
@Override
public CordovaChromeClient makeWebChromeClient(CordovaInterface cordova) {
return new AndroidChromeClient(cordova, this);
}
@Override
public CordovaWebViewClient makeWebViewClient(CordovaInterface cordova) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return new AndroidWebViewClient(cordova, this);
}
return new IceCreamCordovaWebViewClient(cordova, this);
}
/**
@ -361,13 +279,8 @@ public class AndroidWebView extends WebView implements CordovaWebView {
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
@ -377,21 +290,13 @@ public class AndroidWebView extends WebView implements CordovaWebView {
this.addJavascriptInterface(exposedJsApi, "_cordovaNative");
}
/**
* Set the WebViewClient.
*
* @param client
*/
@Override
public void setWebViewClient(CordovaWebViewClient client) {
this.viewClient = client;
super.setWebViewClient((WebViewClient) client);
}
/**
* Set the WebChromeClient.
*
* @param client
*/
@Override
public void setWebChromeClient(CordovaChromeClient client) {
this.chromeClient = client;
super.setWebChromeClient((WebChromeClient) client);
@ -650,21 +555,6 @@ public class AndroidWebView extends WebView implements CordovaWebView {
}
}
/**
* Check configuration parameters from Config.
* Approved list of URLs that can be loaded into Cordova
* <access origin="http://server regexp" subdomains="true" />
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
* <log level="DEBUG" />
*/
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.
*
@ -843,7 +733,7 @@ public class AndroidWebView extends WebView implements CordovaWebView {
// 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);
}

View File

@ -18,20 +18,17 @@
*/
package org.apache.cordova;
import java.io.ByteArrayInputStream;
import java.util.Hashtable;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.TargetApi;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.util.Log;
import android.view.View;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
@ -54,25 +51,15 @@ import android.webkit.WebViewClient;
public class AndroidWebViewClient extends WebViewClient implements CordovaWebViewClient{
private static final String TAG = "AndroidWebViewClient";
private static final String CORDOVA_EXEC_URL_PREFIX = "http://cdv_exec/";
CordovaInterface cordova;
AndroidWebView appView;
CordovaUriHelper helper;
protected final CordovaInterface cordova;
protected final AndroidWebView appView;
protected final CordovaUriHelper helper;
private boolean doClearHistory = false;
boolean isCurrentlyLoading;
/** The authorization tokens. */
private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
/**
* Constructor.
*
* @param cordova
*/
public AndroidWebViewClient(CordovaInterface cordova) {
this.cordova = cordova;
}
/**
* Constructor.
*
@ -85,16 +72,6 @@ public class AndroidWebViewClient extends WebViewClient implements CordovaWebVie
helper = new CordovaUriHelper(cordova, view);
}
/**
* Constructor.
*
* @param view
*/
public void setWebView(AndroidWebView view) {
this.appView = view;
helper = new CordovaUriHelper(cordova, view);
}
/**
* Give the host application a chance to take over the control when a new url
* is about to be loaded in the current WebView.

View File

@ -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() {
}

View File

@ -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<PluginEntry> pluginEntries = new ArrayList<PluginEntry>(20);
private HashMap<String, List<String>> urlMap = new HashMap<String, List<String>>();
public Whitelist getWhitelist() {
return whitelist;
@ -59,10 +56,6 @@ public class ConfigXmlParser {
return launchUrl;
}
public HashMap<String, List<String>> 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<String> 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 <url-filter>");
if (urlMap.get(service) == null) {
urlMap.put(service, new ArrayList<String>(2));
if (urlMap == null) {
urlMap = new ArrayList<String>(2);
}
List<String> 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 {

View File

@ -20,8 +20,8 @@ package org.apache.cordova;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -46,7 +46,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@ -59,7 +58,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:
@ -74,9 +73,8 @@ import android.widget.LinearLayout;
* &#64;Override
* public void onCreate(Bundle savedInstanceState) {
* super.onCreate(savedInstanceState);
* super.init();
* // Load your application
* super.loadUrl(Config.getStartUrl());
* loadUrl(launchUrl);
* }
* }
* </pre>
@ -93,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();
@ -108,10 +110,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.
*/
@ -131,13 +129,17 @@ 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<PluginEntry> pluginEntries;
/**
* 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);
@ -147,22 +149,55 @@ 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
{
} else if (preferences.getBoolean("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);
}
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();
@ -170,20 +205,29 @@ 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 <html style="opacity:0">.
int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK);
root.setBackgroundColor(backgroundColor);
}
/**
* Get the Android activity.
*
* @return the Activity
*/
public Activity getActivity() {
@Override public Activity getActivity() {
return this;
}
@ -194,16 +238,16 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* require a more specialized web view.
*/
protected CordovaWebView makeWebView() {
String r = this.getStringProperty("webView", "org.apache.cordova.AndroidWebView");
String r = preferences.getString("webView", "org.apache.cordova.AndroidWebView");
try {
Class webViewClass = Class.forName(r);
Constructor<CordovaWebView> [] webViewConstructors = webViewClass.getConstructors();
Class<?> webViewClass = Class.forName(r);
Constructor<?>[] webViewConstructors = webViewClass.getConstructors();
if(CordovaWebView.class.isAssignableFrom(webViewClass)) {
for (Constructor<CordovaWebView> constructor : webViewConstructors) {
for (Constructor<?> constructor : webViewConstructors) {
try {
CordovaWebView webView = (CordovaWebView) constructor.newInstance(this);
CordovaWebView webView = (CordovaWebView) constructor.newInstance((Context)this);
return webView;
} catch (IllegalArgumentException e) {
LOG.d(TAG, "Illegal arguments; trying next constructor.");
@ -224,7 +268,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
}
// If all else fails, return a default WebView
return (CordovaWebView) new AndroidWebView(CordovaActivity.this);
return (CordovaWebView) new AndroidWebView(this);
}
/**
@ -237,7 +281,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* @param webView the default constructed web view object
*/
protected CordovaWebViewClient makeWebViewClient(CordovaWebView webView) {
return webView.makeWebViewClient();
return webView.makeWebViewClient(this);
}
/**
@ -250,77 +294,44 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* @param webView the default constructed web view object
*/
protected CordovaChromeClient makeChromeClient(CordovaWebView webView) {
return webView.makeWebChromeClient();
return webView.makeWebChromeClient(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);
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) {
//Note: We're using the parent class, because all we know is that this will be a view
this.appView.setOverScrollMode(View.OVER_SCROLL_NEVER);
}
if (webViewClient != null) {
this.appView.setWebViewClient(webViewClient);
}
if (webChromeClient != null) {
this.appView.setWebChromeClient(webChromeClient);
}
// Add web view but make it invisible while loading URL
this.appView.setVisibility(View.INVISIBLE);
this.root.addView((View) this.appView.getView());
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);
@ -391,16 +402,15 @@ 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();
}
this.appView.clearCache(true);
}
/**
* Clear web history in this web view.
*/
@Deprecated // Call method on appView directly.
public void clearHistory() {
this.appView.clearHistory();
}
@ -410,6 +420,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();
@ -419,103 +430,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);
}
/**
@ -562,8 +504,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;
@ -622,6 +562,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.addJavascript(statement);
@ -846,6 +787,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<String, Object> params) {
if (this.appView != null) {
appView.showWebPage(url, openExternal, clearHistory, params);

View File

@ -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();
}
}
}

View File

@ -1,12 +1,10 @@
package org.apache.cordova;
import java.util.HashMap;
import org.json.JSONException;
import java.util.List;
import android.content.Context;
import android.content.Intent;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebChromeClient.CustomViewCallback;
import android.widget.LinearLayout.LayoutParams;
@ -14,12 +12,14 @@ import android.widget.LinearLayout.LayoutParams;
public interface CordovaWebView {
public static final String CORDOVA_VERSION = "4.0.0-dev";
void init(CordovaInterface cordova, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient, List<PluginEntry> pluginEntries);
View getView();
CordovaWebViewClient makeWebViewClient();
CordovaChromeClient makeWebChromeClient();
CordovaWebViewClient makeWebViewClient(CordovaInterface cordova);
CordovaChromeClient makeWebChromeClient(CordovaInterface cordova);
void setWebViewClient(CordovaWebViewClient webViewClient);
void setWebChromeClient(CordovaChromeClient webChromeClient);
@ -132,4 +132,5 @@ public interface CordovaWebView {
// Required for test
String getUrl();
boolean isPaused();
}

View File

@ -35,12 +35,7 @@ import android.webkit.WebView;
public class IceCreamCordovaWebViewClient extends AndroidWebViewClient implements CordovaWebViewClient{
private static final String TAG = "IceCreamCordovaWebViewClient";
private CordovaUriHelper helper;
public IceCreamCordovaWebViewClient(CordovaInterface cordova) {
super(cordova);
}
public IceCreamCordovaWebViewClient(CordovaInterface cordova, AndroidWebView view) {
super(cordova, view);
}

View File

@ -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<String> 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<String> 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<String> 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;
}

View File

@ -19,7 +19,6 @@
package org.apache.cordova;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@ -54,13 +53,28 @@ public class PluginManager {
// Stores mapping of Plugin Name -> <url-filter> values.
// Using <url-filter> is deprecated.
protected HashMap<String, List<String>> urlMap;
protected HashMap<String, List<String>> urlMap = new HashMap<String, List<String>>();
private Set<String> pluginIdWhitelist;
public PluginManager(CordovaWebView app, CordovaInterface ctx) {
this.ctx = ctx;
this.app = app;
PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, List<PluginEntry> 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<PluginEntry> pluginEntries) {
this.onPause(false);
this.onDestroy();
this.clearPluginObjects();
for (PluginEntry entry : pluginEntries) {
addService(entry);
}
}
public void setPluginIdWhitelist(Set<String> pluginIdWhitelist) {
@ -72,33 +86,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());
for (PluginEntry entry : parser.getPluginEntries()) {
addService(entry);
}
urlMap = parser.getPluginUrlMap();
}
/**
@ -219,6 +214,10 @@ public class PluginManager {
*/
public void addService(PluginEntry entry) {
this.entries.put(entry.service, entry);
List<String> urlFilters = entry.getUrlFilters();
if (urlFilters != null) {
urlMap.put(entry.service, urlFilters);
}
}
/**
@ -324,11 +323,9 @@ public class PluginManager {
* Called when the app navigates or refreshes.
*/
public void onReset() {
Iterator<PluginEntry> 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();
}
}
}