diff options
| author | Jules Laplace <jules@okfoc.us> | 2016-11-08 12:37:03 -0500 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2016-11-08 12:37:03 -0500 |
| commit | ef4f212fc1482136dba1e690ec589b315b4a377f (patch) | |
| tree | 0b7e16d72567fafcfd3e08d7c5c591ad07a63458 /StoneIsland/platforms/android/src/org/apache | |
| parent | 5fa81da81260d65113f57a293b6256d334fe8e2d (diff) | |
build 0.7.0
Diffstat (limited to 'StoneIsland/platforms/android/src/org/apache')
11 files changed, 756 insertions, 186 deletions
diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/BuildHelper.java b/StoneIsland/platforms/android/src/org/apache/cordova/BuildHelper.java new file mode 100644 index 00000000..d9b18aa2 --- /dev/null +++ b/StoneIsland/platforms/android/src/org/apache/cordova/BuildHelper.java @@ -0,0 +1,70 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +package org.apache.cordova; + +/* + * This is a utility class that allows us to get the BuildConfig variable, which is required + * for the use of different providers. This is not guaranteed to work, and it's better for this + * to be set in the build step in config.xml + * + */ + +import android.app.Activity; +import android.content.Context; + +import java.lang.reflect.Field; + + +public class BuildHelper { + + + private static String TAG="BuildHelper"; + + /* + * This needs to be implemented if you wish to use the Camera Plugin or other plugins + * that read the Build Configuration. + * + * Thanks to Phil@Medtronic and Graham Borland for finding the answer and posting it to + * StackOverflow. This is annoying as hell! However, this method does not work with + * ProGuard, and you should use the config.xml to define the application_id + * + */ + + public static Object getBuildConfigValue(Context ctx, String key) + { + try + { + Class<?> clazz = Class.forName(ctx.getPackageName() + ".BuildConfig"); + Field field = clazz.getField(key); + return field.get(null); + } catch (ClassNotFoundException e) { + LOG.d(TAG, "Unable to get the BuildConfig, is this built with ANT?"); + e.printStackTrace(); + } catch (NoSuchFieldException e) { + LOG.d(TAG, key + " is not a valid field. Check your build.gradle"); + } catch (IllegalAccessException e) { + LOG.d(TAG, "Illegal Access Exception: Let's print a stack trace."); + e.printStackTrace(); + } + + return null; + } + +} diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/PermissionHelper.java b/StoneIsland/platforms/android/src/org/apache/cordova/PermissionHelper.java new file mode 100644 index 00000000..bbd79112 --- /dev/null +++ b/StoneIsland/platforms/android/src/org/apache/cordova/PermissionHelper.java @@ -0,0 +1,138 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +package org.apache.cordova; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; + +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.LOG; + +import android.content.pm.PackageManager; + +/** + * This class provides reflective methods for permission requesting and checking so that plugins + * written for cordova-android 5.0.0+ can still compile with earlier cordova-android versions. + */ +public class PermissionHelper { + private static final String LOG_TAG = "CordovaPermissionHelper"; + + /** + * Requests a "dangerous" permission for the application at runtime. This is a helper method + * alternative to cordovaInterface.requestPermission() that does not require the project to be + * built with cordova-android 5.0.0+ + * + * @param plugin The plugin the permission is being requested for + * @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult() + * along with the result of the permission request + * @param permission The permission to be requested + */ + public static void requestPermission(CordovaPlugin plugin, int requestCode, String permission) { + PermissionHelper.requestPermissions(plugin, requestCode, new String[] {permission}); + } + + /** + * Requests "dangerous" permissions for the application at runtime. This is a helper method + * alternative to cordovaInterface.requestPermissions() that does not require the project to be + * built with cordova-android 5.0.0+ + * + * @param plugin The plugin the permissions are being requested for + * @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult() + * along with the result of the permissions request + * @param permissions The permissions to be requested + */ + public static void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) { + try { + Method requestPermission = CordovaInterface.class.getDeclaredMethod( + "requestPermissions", CordovaPlugin.class, int.class, String[].class); + + // If there is no exception, then this is cordova-android 5.0.0+ + requestPermission.invoke(plugin.cordova, plugin, requestCode, permissions); + } catch (NoSuchMethodException noSuchMethodException) { + // cordova-android version is less than 5.0.0, so permission is implicitly granted + LOG.d(LOG_TAG, "No need to request permissions " + Arrays.toString(permissions)); + + // Notify the plugin that all were granted by using more reflection + deliverPermissionResult(plugin, requestCode, permissions); + } catch (IllegalAccessException illegalAccessException) { + // Should never be caught; this is a public method + LOG.e(LOG_TAG, "IllegalAccessException when requesting permissions " + Arrays.toString(permissions), illegalAccessException); + } catch(InvocationTargetException invocationTargetException) { + // This method does not throw any exceptions, so this should never be caught + LOG.e(LOG_TAG, "invocationTargetException when requesting permissions " + Arrays.toString(permissions), invocationTargetException); + } + } + + /** + * Checks at runtime to see if the application has been granted a permission. This is a helper + * method alternative to cordovaInterface.hasPermission() that does not require the project to + * be built with cordova-android 5.0.0+ + * + * @param plugin The plugin the permission is being checked against + * @param permission The permission to be checked + * + * @return True if the permission has already been granted and false otherwise + */ + public static boolean hasPermission(CordovaPlugin plugin, String permission) { + try { + Method hasPermission = CordovaInterface.class.getDeclaredMethod("hasPermission", String.class); + + // If there is no exception, then this is cordova-android 5.0.0+ + return (Boolean) hasPermission.invoke(plugin.cordova, permission); + } catch (NoSuchMethodException noSuchMethodException) { + // cordova-android version is less than 5.0.0, so permission is implicitly granted + LOG.d(LOG_TAG, "No need to check for permission " + permission); + return true; + } catch (IllegalAccessException illegalAccessException) { + // Should never be caught; this is a public method + LOG.e(LOG_TAG, "IllegalAccessException when checking permission " + permission, illegalAccessException); + } catch(InvocationTargetException invocationTargetException) { + // This method does not throw any exceptions, so this should never be caught + LOG.e(LOG_TAG, "invocationTargetException when checking permission " + permission, invocationTargetException); + } + return false; + } + + private static void deliverPermissionResult(CordovaPlugin plugin, int requestCode, String[] permissions) { + // Generate the request results + int[] requestResults = new int[permissions.length]; + Arrays.fill(requestResults, PackageManager.PERMISSION_GRANTED); + + try { + Method onRequestPermissionResult = CordovaPlugin.class.getDeclaredMethod( + "onRequestPermissionResult", int.class, String[].class, int[].class); + + onRequestPermissionResult.invoke(plugin, requestCode, permissions, requestResults); + } catch (NoSuchMethodException noSuchMethodException) { + // Should never be caught since the plugin must be written for cordova-android 5.0.0+ if it + // made it to this point + LOG.e(LOG_TAG, "NoSuchMethodException when delivering permissions results", noSuchMethodException); + } catch (IllegalAccessException illegalAccessException) { + // Should never be caught; this is a public method + LOG.e(LOG_TAG, "IllegalAccessException when delivering permissions results", illegalAccessException); + } catch(InvocationTargetException invocationTargetException) { + // This method may throw a JSONException. We are just duplicating cordova-android's + // exception handling behavior here; all it does is log the exception in CordovaActivity, + // print the stacktrace, and ignore it + LOG.e(LOG_TAG, "InvocationTargetException when delivering permissions results", invocationTargetException); + } + } +} diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/device/Device.java b/StoneIsland/platforms/android/src/org/apache/cordova/device/Device.java index 5eded907..e9efcb49 100755..100644 --- a/StoneIsland/platforms/android/src/org/apache/cordova/device/Device.java +++ b/StoneIsland/platforms/android/src/org/apache/cordova/device/Device.java @@ -67,13 +67,15 @@ public class Device extends CordovaPlugin { * @return True if the action was valid, false if not. */ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - if (action.equals("getDeviceInfo")) { + if ("getDeviceInfo".equals(action)) { JSONObject r = new JSONObject(); r.put("uuid", Device.uuid); r.put("version", this.getOSVersion()); r.put("platform", this.getPlatform()); r.put("model", this.getModel()); r.put("manufacturer", this.getManufacturer()); + r.put("isVirtual", this.isVirtual()); + r.put("serial", this.getSerialNumber()); callbackContext.success(r); } else { @@ -88,7 +90,7 @@ public class Device extends CordovaPlugin { /** * Get the OS name. - * + * * @return */ public String getPlatform() { @@ -125,6 +127,12 @@ public class Device extends CordovaPlugin { String manufacturer = android.os.Build.MANUFACTURER; return manufacturer; } + + public String getSerialNumber() { + String serial = android.os.Build.SERIAL; + return serial; + } + /** * Get the OS version. * @@ -148,7 +156,7 @@ public class Device extends CordovaPlugin { /** * Function to check if the device is manufactured by Amazon - * + * * @return */ public boolean isAmazonDevice() { @@ -158,4 +166,9 @@ public class Device extends CordovaPlugin { return false; } + public boolean isVirtual() { + return android.os.Build.FINGERPRINT.contains("generic") || + android.os.Build.PRODUCT.contains("sdk"); + } + } diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/dialogs/Notification.java b/StoneIsland/platforms/android/src/org/apache/cordova/dialogs/Notification.java index 3bc3cee6..f19bc888 100755..100644 --- a/StoneIsland/platforms/android/src/org/apache/cordova/dialogs/Notification.java +++ b/StoneIsland/platforms/android/src/org/apache/cordova/dialogs/Notification.java @@ -21,6 +21,7 @@ package org.apache.cordova.dialogs; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.LOG; import org.apache.cordova.PluginResult; import org.json.JSONArray; import org.json.JSONException; @@ -31,6 +32,7 @@ import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.ProgressDialog; import android.content.DialogInterface; +import android.content.res.Resources; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; @@ -48,6 +50,8 @@ import android.widget.TextView; */ public class Notification extends CordovaPlugin { + private static final String LOG_TAG = "Notification"; + public int confirmResult = -1; public ProgressDialog spinnerDialog = null; public ProgressDialog progressDialog = null; @@ -139,6 +143,7 @@ public class Notification extends CordovaPlugin { try { Thread.sleep(100); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); } } } @@ -215,7 +220,9 @@ public class Notification extends CordovaPlugin { callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 1)); } }); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on first button."); + } } // Second button @@ -228,7 +235,9 @@ public class Notification extends CordovaPlugin { callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 2)); } }); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on second button."); + } } // Third button @@ -241,7 +250,9 @@ public class Notification extends CordovaPlugin { callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 3)); } }); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on third button."); + } } dlg.setOnCancelListener(new AlertDialog.OnCancelListener() { public void onCancel(DialogInterface dialog) @@ -276,7 +287,14 @@ public class Notification extends CordovaPlugin { Runnable runnable = new Runnable() { public void run() { final EditText promptInput = new EditText(cordova.getActivity()); - promptInput.setHint(defaultText); + + /* CB-11677 - By default, prompt input text color is set according current theme. + But for some android versions is not visible (for example 5.1.1). + android.R.color.primary_text_light will make text visible on all versions. */ + Resources resources = cordova.getActivity().getResources(); + int promptInputTextColor = resources.getColor(android.R.color.primary_text_light); + promptInput.setTextColor(promptInputTextColor); + promptInput.setText(defaultText); AlertDialog.Builder dlg = createDialog(cordova); // new AlertDialog.Builder(cordova.getActivity(), AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); dlg.setMessage(message); dlg.setTitle(title); @@ -296,11 +314,15 @@ public class Notification extends CordovaPlugin { try { result.put("buttonIndex",1); result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); - } catch (JSONException e) { e.printStackTrace(); } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on first button.", e); + } callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); } }); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on first button."); + } } // Second button @@ -313,11 +335,15 @@ public class Notification extends CordovaPlugin { try { result.put("buttonIndex",2); result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); - } catch (JSONException e) { e.printStackTrace(); } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on second button.", e); + } callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); } }); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on second button."); + } } // Third button @@ -330,11 +356,15 @@ public class Notification extends CordovaPlugin { try { result.put("buttonIndex",3); result.put("input1", promptInput.getText().toString().trim().length()==0 ? defaultText : promptInput.getText()); - } catch (JSONException e) { e.printStackTrace(); } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on third button.", e); + } callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result)); } }); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG,"JSONException on third button."); + } } dlg.setOnCancelListener(new AlertDialog.OnCancelListener() { public void onCancel(DialogInterface dialog){ diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/geolocation/Geolocation.java b/StoneIsland/platforms/android/src/org/apache/cordova/geolocation/Geolocation.java new file mode 100644 index 00000000..6452170a --- /dev/null +++ b/StoneIsland/platforms/android/src/org/apache/cordova/geolocation/Geolocation.java @@ -0,0 +1,107 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + + +package org.apache.cordova.geolocation; + +import android.content.pm.PackageManager; +import android.Manifest; +import android.os.Build; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaArgs; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.PermissionHelper; +import org.apache.cordova.PluginResult; +import org.apache.cordova.LOG; +import org.json.JSONArray; +import org.json.JSONException; + +import javax.security.auth.callback.Callback; + +public class Geolocation extends CordovaPlugin { + + String TAG = "GeolocationPlugin"; + CallbackContext context; + + String [] permissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }; + + + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + LOG.d(TAG, "We are entering execute"); + context = callbackContext; + if(action.equals("getPermission")) + { + if(hasPermisssion()) + { + PluginResult r = new PluginResult(PluginResult.Status.OK); + context.sendPluginResult(r); + return true; + } + else { + PermissionHelper.requestPermissions(this, 0, permissions); + } + return true; + } + return false; + } + + + public void onRequestPermissionResult(int requestCode, String[] permissions, + int[] grantResults) throws JSONException + { + PluginResult result; + //This is important if we're using Cordova without using Cordova, but we have the geolocation plugin installed + if(context != null) { + for (int r : grantResults) { + if (r == PackageManager.PERMISSION_DENIED) { + LOG.d(TAG, "Permission Denied!"); + result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION); + context.sendPluginResult(result); + return; + } + + } + result = new PluginResult(PluginResult.Status.OK); + context.sendPluginResult(result); + } + } + + public boolean hasPermisssion() { + for(String p : permissions) + { + if(!PermissionHelper.hasPermission(this, p)) + { + return false; + } + } + return true; + } + + /* + * We override this so that we can access the permissions variable, which no longer exists in + * the parent class, since we can't initialize it reliably in the constructor! + */ + + public void requestPermissions(int requestCode) + { + PermissionHelper.requestPermissions(this, requestCode, permissions); + } + + + +} diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowser.java b/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowser.java index 60437451..8f4f3d97 100755..100644 --- a/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowser.java +++ b/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowser.java @@ -19,7 +19,6 @@ package org.apache.cordova.inappbrowser; import android.annotation.SuppressLint; -import org.apache.cordova.inappbrowser.InAppBrowserDialog; import android.content.Context; import android.content.Intent; import android.provider.Browser; @@ -30,7 +29,6 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.text.InputType; -import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; @@ -41,17 +39,21 @@ import android.view.WindowManager.LayoutParams; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.webkit.CookieManager; +import android.webkit.CookieSyncManager; +import android.webkit.HttpAuthHandler; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; -import android.widget.Button; import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import org.apache.cordova.CallbackContext; import org.apache.cordova.Config; import org.apache.cordova.CordovaArgs; +import org.apache.cordova.CordovaHttpAuthHandler; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaWebView; import org.apache.cordova.LOG; @@ -61,6 +63,7 @@ import org.json.JSONException; import org.json.JSONObject; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.StringTokenizer; @@ -82,6 +85,8 @@ public class InAppBrowser extends CordovaPlugin { private static final String CLEAR_ALL_CACHE = "clearcache"; private static final String CLEAR_SESSION_CACHE = "clearsessioncache"; private static final String HARDWARE_BACK_BUTTON = "hardwareback"; + private static final String MEDIA_PLAYBACK_REQUIRES_USER_ACTION = "mediaPlaybackRequiresUserAction"; + private static final String SHOULD_PAUSE = "shouldPauseOnSuspend"; private InAppBrowserDialog dialog; private WebView inAppWebView; @@ -93,6 +98,8 @@ public class InAppBrowser extends CordovaPlugin { private boolean clearAllCache = false; private boolean clearSessionCache = false; private boolean hadwareBackButton = true; + private boolean mediaPlaybackRequiresUserGesture = false; + private boolean shouldPauseInAppBrowser = false; /** * Executes the request and returns PluginResult. @@ -113,7 +120,7 @@ public class InAppBrowser extends CordovaPlugin { final String target = t; final HashMap<String, Boolean> features = parseFeature(args.optString(2)); - Log.d(LOG_TAG, "target = " + target); + LOG.d(LOG_TAG, "target = " + target); this.cordova.getActivity().runOnUiThread(new Runnable() { @Override @@ -121,7 +128,7 @@ public class InAppBrowser extends CordovaPlugin { String result = ""; // SELF if (SELF.equals(target)) { - Log.d(LOG_TAG, "in self"); + LOG.d(LOG_TAG, "in self"); /* This code exists for compatibility between 3.x and 4.x versions of Cordova. * Previously the Config class had a static method, isUrlWhitelisted(). That * responsibility has been moved to the plugins, with an aggregating method in @@ -136,8 +143,11 @@ public class InAppBrowser extends CordovaPlugin { Method iuw = Config.class.getMethod("isUrlWhiteListed", String.class); shouldAllowNavigation = (Boolean)iuw.invoke(null, url); } catch (NoSuchMethodException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); } catch (IllegalAccessException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); } catch (InvocationTargetException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); } } if (shouldAllowNavigation == null) { @@ -147,20 +157,23 @@ public class InAppBrowser extends CordovaPlugin { Method san = pm.getClass().getMethod("shouldAllowNavigation", String.class); shouldAllowNavigation = (Boolean)san.invoke(pm, url); } catch (NoSuchMethodException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); } catch (IllegalAccessException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); } catch (InvocationTargetException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); } } // load in webview if (Boolean.TRUE.equals(shouldAllowNavigation)) { - Log.d(LOG_TAG, "loading in webview"); + LOG.d(LOG_TAG, "loading in webview"); webView.loadUrl(url); } //Load the dialer else if (url.startsWith(WebView.SCHEME_TEL)) { try { - Log.d(LOG_TAG, "loading in dialer"); + LOG.d(LOG_TAG, "loading in dialer"); Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse(url)); cordova.getActivity().startActivity(intent); @@ -170,18 +183,18 @@ public class InAppBrowser extends CordovaPlugin { } // load in InAppBrowser else { - Log.d(LOG_TAG, "loading in InAppBrowser"); + LOG.d(LOG_TAG, "loading in InAppBrowser"); result = showWebPage(url, features); } } // SYSTEM else if (SYSTEM.equals(target)) { - Log.d(LOG_TAG, "in system"); + LOG.d(LOG_TAG, "in system"); result = openExternal(url); } // BLANK - or anything else else { - Log.d(LOG_TAG, "in blank"); + LOG.d(LOG_TAG, "in blank"); result = showWebPage(url, features); } @@ -197,7 +210,7 @@ public class InAppBrowser extends CordovaPlugin { else if (action.equals("injectScriptCode")) { String jsWrapper = null; if (args.getBoolean(1)) { - jsWrapper = String.format("prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')", callbackContext.getCallbackId()); + jsWrapper = String.format("(function(){prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')})()", callbackContext.getCallbackId()); } injectDeferredObject(args.getString(0), jsWrapper); } @@ -254,6 +267,26 @@ public class InAppBrowser extends CordovaPlugin { } /** + * Called when the system is about to start resuming a previous activity. + */ + @Override + public void onPause(boolean multitasking) { + if (shouldPauseInAppBrowser) { + inAppWebView.onPause(); + } + } + + /** + * Called when the activity will start interacting with the user. + */ + @Override + public void onResume(boolean multitasking) { + if (shouldPauseInAppBrowser) { + inAppWebView.onResume(); + } + } + + /** * Called by AccelBroker when listener is to be shut down. * Stop listener. */ @@ -350,7 +383,7 @@ public class InAppBrowser extends CordovaPlugin { this.cordova.getActivity().startActivity(intent); return ""; } catch (android.content.ActivityNotFoundException e) { - Log.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString()); + LOG.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString()); return e.toString(); } } @@ -359,20 +392,22 @@ public class InAppBrowser extends CordovaPlugin { * Closes the dialog */ public void closeDialog() { - final WebView childView = this.inAppWebView; - // The JS protects against multiple calls, so this should happen only when - // closeDialog() is called by other native code. - if (childView == null) { - return; - } this.cordova.getActivity().runOnUiThread(new Runnable() { @Override public void run() { + final WebView childView = inAppWebView; + // The JS protects against multiple calls, so this should happen only when + // closeDialog() is called by other native code. + if (childView == null) { + return; + } + childView.setWebViewClient(new WebViewClient() { // NB: wait for about:blank before dismissing public void onPageFinished(WebView view, String url) { if (dialog != null) { dialog.dismiss(); + dialog = null; } } }); @@ -380,16 +415,16 @@ public class InAppBrowser extends CordovaPlugin { // other than your app's UI thread, it can cause unexpected results." // http://developer.android.com/guide/webapps/migrating.html#Threads childView.loadUrl("about:blank"); + + try { + JSONObject obj = new JSONObject(); + obj.put("type", EXIT_EVENT); + sendUpdate(obj, false); + } catch (JSONException ex) { + LOG.d(LOG_TAG, "Should never happen"); + } } }); - - try { - JSONObject obj = new JSONObject(); - obj.put("type", EXIT_EVENT); - sendUpdate(obj, false); - } catch (JSONException ex) { - Log.d(LOG_TAG, "Should never happen"); - } } /** @@ -468,6 +503,8 @@ public class InAppBrowser extends CordovaPlugin { showLocationBar = true; showZoomControls = true; openWindowHidden = false; + mediaPlaybackRequiresUserGesture = false; + if (features != null) { Boolean show = features.get(LOCATION); if (show != null) { @@ -485,6 +522,10 @@ public class InAppBrowser extends CordovaPlugin { if (hardwareBack != null) { hadwareBackButton = hardwareBack.booleanValue(); } + Boolean mediaPlayback = features.get(MEDIA_PLAYBACK_REQUIRES_USER_ACTION); + if (mediaPlayback != null) { + mediaPlaybackRequiresUserGesture = mediaPlayback.booleanValue(); + } Boolean cache = features.get(CLEAR_ALL_CACHE); if (cache != null) { clearAllCache = cache.booleanValue(); @@ -494,6 +535,10 @@ public class InAppBrowser extends CordovaPlugin { clearSessionCache = cache.booleanValue(); } } + Boolean shouldPause = features.get(SHOULD_PAUSE); + if (shouldPause != null) { + shouldPauseInAppBrowser = shouldPause.booleanValue(); + } } final CordovaWebView thatWebView = this.webView; @@ -516,6 +561,12 @@ public class InAppBrowser extends CordovaPlugin { @SuppressLint("NewApi") public void run() { + + // CB-6702 InAppBrowser hangs when opening more than one instance + if (dialog != null) { + dialog.dismiss(); + }; + // Let's create the main dialog dialog = new InAppBrowserDialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar); dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog; @@ -541,26 +592,28 @@ public class InAppBrowser extends CordovaPlugin { actionButtonContainer.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); actionButtonContainer.setHorizontalGravity(Gravity.LEFT); actionButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL); - actionButtonContainer.setId(1); + actionButtonContainer.setId(Integer.valueOf(1)); // Back button - Button back = new Button(cordova.getActivity()); + ImageButton back = new ImageButton(cordova.getActivity()); RelativeLayout.LayoutParams backLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); backLayoutParams.addRule(RelativeLayout.ALIGN_LEFT); back.setLayoutParams(backLayoutParams); back.setContentDescription("Back Button"); - back.setId(2); + back.setId(Integer.valueOf(2)); Resources activityRes = cordova.getActivity().getResources(); int backResId = activityRes.getIdentifier("ic_action_previous_item", "drawable", cordova.getActivity().getPackageName()); Drawable backIcon = activityRes.getDrawable(backResId); - if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) - { - back.setBackgroundDrawable(backIcon); - } + if (Build.VERSION.SDK_INT >= 16) + back.setBackground(null); else - { - back.setBackground(backIcon); - } + back.setBackgroundDrawable(null); + back.setImageDrawable(backIcon); + back.setScaleType(ImageView.ScaleType.FIT_CENTER); + back.setPadding(0, this.dpToPixels(10), 0, this.dpToPixels(10)); + if (Build.VERSION.SDK_INT >= 16) + back.getAdjustViewBounds(); + back.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { goBack(); @@ -568,22 +621,24 @@ public class InAppBrowser extends CordovaPlugin { }); // Forward button - Button forward = new Button(cordova.getActivity()); + ImageButton forward = new ImageButton(cordova.getActivity()); RelativeLayout.LayoutParams forwardLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); forwardLayoutParams.addRule(RelativeLayout.RIGHT_OF, 2); forward.setLayoutParams(forwardLayoutParams); forward.setContentDescription("Forward Button"); - forward.setId(3); + forward.setId(Integer.valueOf(3)); int fwdResId = activityRes.getIdentifier("ic_action_next_item", "drawable", cordova.getActivity().getPackageName()); Drawable fwdIcon = activityRes.getDrawable(fwdResId); - if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) - { - forward.setBackgroundDrawable(fwdIcon); - } + if (Build.VERSION.SDK_INT >= 16) + forward.setBackground(null); else - { - forward.setBackground(fwdIcon); - } + forward.setBackgroundDrawable(null); + forward.setImageDrawable(fwdIcon); + forward.setScaleType(ImageView.ScaleType.FIT_CENTER); + forward.setPadding(0, this.dpToPixels(10), 0, this.dpToPixels(10)); + if (Build.VERSION.SDK_INT >= 16) + forward.getAdjustViewBounds(); + forward.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { goForward(); @@ -596,7 +651,7 @@ public class InAppBrowser extends CordovaPlugin { textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1); textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5); edittext.setLayoutParams(textLayoutParams); - edittext.setId(4); + edittext.setId(Integer.valueOf(4)); edittext.setSingleLine(true); edittext.setText(url); edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI); @@ -614,22 +669,24 @@ public class InAppBrowser extends CordovaPlugin { }); // Close/Done button - Button close = new Button(cordova.getActivity()); + ImageButton close = new ImageButton(cordova.getActivity()); RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); close.setLayoutParams(closeLayoutParams); forward.setContentDescription("Close Button"); - close.setId(5); + close.setId(Integer.valueOf(5)); int closeResId = activityRes.getIdentifier("ic_action_remove", "drawable", cordova.getActivity().getPackageName()); Drawable closeIcon = activityRes.getDrawable(closeResId); - if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) - { - close.setBackgroundDrawable(closeIcon); - } + if (Build.VERSION.SDK_INT >= 16) + close.setBackground(null); else - { - close.setBackground(closeIcon); - } + close.setBackgroundDrawable(null); + close.setImageDrawable(closeIcon); + close.setScaleType(ImageView.ScaleType.FIT_CENTER); + back.setPadding(0, this.dpToPixels(10), 0, this.dpToPixels(10)); + if (Build.VERSION.SDK_INT >= 16) + close.getAdjustViewBounds(); + close.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { closeDialog(); @@ -639,6 +696,7 @@ public class InAppBrowser extends CordovaPlugin { // WebView inAppWebView = new WebView(cordova.getActivity()); inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + inAppWebView.setId(Integer.valueOf(6)); inAppWebView.setWebChromeClient(new InAppChromeClient(thatWebView)); WebViewClient client = new InAppBrowserClient(thatWebView, edittext); inAppWebView.setWebViewClient(client); @@ -648,6 +706,20 @@ public class InAppBrowser extends CordovaPlugin { settings.setBuiltInZoomControls(showZoomControls); settings.setPluginState(android.webkit.WebSettings.PluginState.ON); + if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { + settings.setMediaPlaybackRequiresUserGesture(mediaPlaybackRequiresUserGesture); + } + + String overrideUserAgent = preferences.getString("OverrideUserAgent", null); + String appendUserAgent = preferences.getString("AppendUserAgent", null); + + if (overrideUserAgent != null) { + settings.setUserAgentString(overrideUserAgent); + } + if (appendUserAgent != null) { + settings.setUserAgentString(settings.getUserAgentString() + appendUserAgent); + } + //Toggle whether this is enabled or not! Bundle appSettings = cordova.getActivity().getIntent().getExtras(); boolean enableDatabase = appSettings == null ? true : appSettings.getBoolean("InAppBrowserStorageEnabled", true); @@ -665,7 +737,7 @@ public class InAppBrowser extends CordovaPlugin { } inAppWebView.loadUrl(url); - inAppWebView.setId(6); + inAppWebView.setId(Integer.valueOf(6)); inAppWebView.getSettings().setLoadWithOverviewMode(true); inAppWebView.getSettings().setUseWideViewPort(true); inAppWebView.requestFocus(); @@ -753,34 +825,30 @@ public class InAppBrowser extends CordovaPlugin { } /** - * Notify the host application that a page has started loading. + * Override the URL that should be loaded + * + * This handles a small subset of all the URIs that would be encountered. * - * @param view The webview initiating the callback. - * @param url The url of the page. + * @param webView + * @param url */ @Override - public void onPageStarted(WebView view, String url, Bitmap favicon) { - super.onPageStarted(view, url, favicon); - String newloc = ""; - if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) { - newloc = url; - } - // If dialing phone (tel:5551212) - else if (url.startsWith(WebView.SCHEME_TEL)) { + public boolean shouldOverrideUrlLoading(WebView webView, String url) { + if (url.startsWith(WebView.SCHEME_TEL)) { try { Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse(url)); cordova.getActivity().startActivity(intent); + return true; } catch (android.content.ActivityNotFoundException e) { LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString()); } - } - - else if (url.startsWith("geo:") || url.startsWith(WebView.SCHEME_MAILTO) || url.startsWith("market:")) { + } else if (url.startsWith("geo:") || url.startsWith(WebView.SCHEME_MAILTO) || url.startsWith("market:") || url.startsWith("intent:")) { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); cordova.getActivity().startActivity(intent); + return true; } catch (android.content.ActivityNotFoundException e) { LOG.e(LOG_TAG, "Error with " + url + ": " + e.toString()); } @@ -795,8 +863,7 @@ public class InAppBrowser extends CordovaPlugin { int parmIndex = url.indexOf('?'); if (parmIndex == -1) { address = url.substring(4); - } - else { + } else { address = url.substring(4, parmIndex); // If body, then set sms body @@ -812,32 +879,64 @@ public class InAppBrowser extends CordovaPlugin { intent.putExtra("address", address); intent.setType("vnd.android-dir/mms-sms"); cordova.getActivity().startActivity(intent); + return true; } catch (android.content.ActivityNotFoundException e) { LOG.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString()); } } - else { + return false; + } + + + /* + * onPageStarted fires the LOAD_START_EVENT + * + * @param view + * @param url + * @param favicon + */ + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + String newloc = ""; + if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) { + newloc = url; + } + else + { + // Assume that everything is HTTP at this point, because if we don't specify, + // it really should be. Complain loudly about this!!! + LOG.e(LOG_TAG, "Possible Uncaught/Unknown URI"); newloc = "http://" + url; } + // Update the UI if we haven't already if (!newloc.equals(edittext.getText().toString())) { edittext.setText(newloc); - } + } try { JSONObject obj = new JSONObject(); obj.put("type", LOAD_START_EVENT); obj.put("url", newloc); - sendUpdate(obj, true); } catch (JSONException ex) { - Log.d(LOG_TAG, "Should never happen"); + LOG.e(LOG_TAG, "URI passed in has caused a JSON error."); } } + + public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); + // CB-10395 InAppBrowser's WebView not storing cookies reliable to local device storage + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + CookieManager.getInstance().flush(); + } else { + CookieSyncManager.getInstance().sync(); + } + try { JSONObject obj = new JSONObject(); obj.put("type", LOAD_STOP_EVENT); @@ -845,7 +944,7 @@ public class InAppBrowser extends CordovaPlugin { sendUpdate(obj, true); } catch (JSONException ex) { - Log.d(LOG_TAG, "Should never happen"); + LOG.d(LOG_TAG, "Should never happen"); } } @@ -861,9 +960,46 @@ public class InAppBrowser extends CordovaPlugin { sendUpdate(obj, true, PluginResult.Status.ERROR); } catch (JSONException ex) { - Log.d(LOG_TAG, "Should never happen"); + LOG.d(LOG_TAG, "Should never happen"); } } + + /** + * On received http auth request. + */ + @Override + public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { + + // Check if there is some plugin which can resolve this auth challenge + PluginManager pluginManager = null; + try { + Method gpm = webView.getClass().getMethod("getPluginManager"); + pluginManager = (PluginManager)gpm.invoke(webView); + } catch (NoSuchMethodException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); + } catch (IllegalAccessException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); + } catch (InvocationTargetException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); + } + + if (pluginManager == null) { + try { + Field pmf = webView.getClass().getField("pluginManager"); + pluginManager = (PluginManager)pmf.get(webView); + } catch (NoSuchFieldException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); + } catch (IllegalAccessException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); + } + } + + if (pluginManager != null && pluginManager.onReceivedHttpAuthRequest(webView, new CordovaHttpAuthHandler(handler), host, realm)) { + return; + } + + // By default handle 401 like we'd normally do! + super.onReceivedHttpAuthRequest(view, handler, host, realm); + } } } - diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowserDialog.java b/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowserDialog.java index d7017202..e7b212f2 100755..100644 --- a/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowserDialog.java +++ b/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowserDialog.java @@ -21,7 +21,6 @@ package org.apache.cordova.inappbrowser; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; -import android.util.Log; import org.json.JSONException; import org.json.JSONObject; diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppChromeClient.java b/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppChromeClient.java index a2145e6a..a2145e6a 100755..100644 --- a/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppChromeClient.java +++ b/StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppChromeClient.java diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/networkinformation/NetworkManager.java b/StoneIsland/platforms/android/src/org/apache/cordova/networkinformation/NetworkManager.java index 4c85ddab..614b6e7b 100755 --- a/StoneIsland/platforms/android/src/org/apache/cordova/networkinformation/NetworkManager.java +++ b/StoneIsland/platforms/android/src/org/apache/cordova/networkinformation/NetworkManager.java @@ -21,6 +21,7 @@ package org.apache.cordova.networkinformation; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.LOG; import org.apache.cordova.PluginResult; import org.apache.cordova.CordovaWebView; import org.json.JSONArray; @@ -33,7 +34,8 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.util.Log; + +import java.util.Locale; public class NetworkManager extends CordovaPlugin { @@ -45,14 +47,16 @@ public class NetworkManager extends CordovaPlugin { public static final String WIMAX = "wimax"; // mobile public static final String MOBILE = "mobile"; - - // Android L calls this Cellular, because I have no idea! + + // Android L calls this Cellular, because I have no idea! public static final String CELLULAR = "cellular"; // 2G network types + public static final String TWO_G = "2g"; public static final String GSM = "gsm"; public static final String GPRS = "gprs"; public static final String EDGE = "edge"; // 3G network types + public static final String THREE_G = "3g"; public static final String CDMA = "cdma"; public static final String UMTS = "umts"; public static final String HSPA = "hspa"; @@ -61,12 +65,14 @@ public class NetworkManager extends CordovaPlugin { public static final String ONEXRTT = "1xrtt"; public static final String EHRPD = "ehrpd"; // 4G network types + public static final String FOUR_G = "4g"; public static final String LTE = "lte"; public static final String UMB = "umb"; public static final String HSPA_PLUS = "hspa+"; // return type public static final String TYPE_UNKNOWN = "unknown"; public static final String TYPE_ETHERNET = "ethernet"; + public static final String TYPE_ETHERNET_SHORT = "eth"; public static final String TYPE_WIFI = "wifi"; public static final String TYPE_2G = "2g"; public static final String TYPE_3G = "3g"; @@ -125,7 +131,9 @@ public class NetworkManager extends CordovaPlugin { String connectionType = ""; try { connectionType = this.getConnectionInfo(info).get("type").toString(); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); + } PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, connectionType); pluginResult.setKeepCallback(true); @@ -143,7 +151,7 @@ public class NetworkManager extends CordovaPlugin { try { webView.getContext().unregisterReceiver(this.receiver); } catch (Exception e) { - Log.e(LOG_TAG, "Error unregistering network receiver: " + e.getMessage(), e); + LOG.e(LOG_TAG, "Error unregistering network receiver: " + e.getMessage(), e); } finally { receiver = null; } @@ -169,7 +177,9 @@ public class NetworkManager extends CordovaPlugin { String connectionType = ""; try { connectionType = thisInfo.get("type").toString(); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); + } sendUpdate(connectionType); lastInfo = thisInfo; @@ -196,15 +206,17 @@ public class NetworkManager extends CordovaPlugin { extraInfo = info.getExtraInfo(); } - Log.d("CordovaNetworkManager", "Connection Type: " + type); - Log.d("CordovaNetworkManager", "Connection Extra Info: " + extraInfo); + LOG.d(LOG_TAG, "Connection Type: " + type); + LOG.d(LOG_TAG, "Connection Extra Info: " + extraInfo); JSONObject connectionInfo = new JSONObject(); try { connectionInfo.put("type", type); connectionInfo.put("extraInfo", extraInfo); - } catch (JSONException e) { } + } catch (JSONException e) { + LOG.d(LOG_TAG, e.getLocalizedMessage()); + } return connectionInfo; } @@ -231,30 +243,38 @@ public class NetworkManager extends CordovaPlugin { */ private String getType(NetworkInfo info) { if (info != null) { - String type = info.getTypeName(); + String type = info.getTypeName().toLowerCase(Locale.US); - if (type.toLowerCase().equals(WIFI)) { + LOG.d(LOG_TAG, "toLower : " + type.toLowerCase()); + LOG.d(LOG_TAG, "wifi : " + WIFI); + if (type.equals(WIFI)) { return TYPE_WIFI; } - else if (type.toLowerCase().equals(MOBILE) || type.toLowerCase().equals(CELLULAR)) { - type = info.getSubtypeName(); - if (type.toLowerCase().equals(GSM) || - type.toLowerCase().equals(GPRS) || - type.toLowerCase().equals(EDGE)) { + else if (type.toLowerCase().equals(TYPE_ETHERNET) || type.toLowerCase().startsWith(TYPE_ETHERNET_SHORT)) { + return TYPE_ETHERNET; + } + else if (type.equals(MOBILE) || type.equals(CELLULAR)) { + type = info.getSubtypeName().toLowerCase(Locale.US); + if (type.equals(GSM) || + type.equals(GPRS) || + type.equals(EDGE) || + type.equals(TWO_G)) { return TYPE_2G; } - else if (type.toLowerCase().startsWith(CDMA) || - type.toLowerCase().equals(UMTS) || - type.toLowerCase().equals(ONEXRTT) || - type.toLowerCase().equals(EHRPD) || - type.toLowerCase().equals(HSUPA) || - type.toLowerCase().equals(HSDPA) || - type.toLowerCase().equals(HSPA)) { + else if (type.startsWith(CDMA) || + type.equals(UMTS) || + type.equals(ONEXRTT) || + type.equals(EHRPD) || + type.equals(HSUPA) || + type.equals(HSDPA) || + type.equals(HSPA) || + type.equals(THREE_G)) { return TYPE_3G; } - else if (type.toLowerCase().equals(LTE) || - type.toLowerCase().equals(UMB) || - type.toLowerCase().equals(HSPA_PLUS)) { + else if (type.equals(LTE) || + type.equals(UMB) || + type.equals(HSPA_PLUS) || + type.equals(FOUR_G)) { return TYPE_4G; } } diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/splashscreen/SplashScreen.java b/StoneIsland/platforms/android/src/org/apache/cordova/splashscreen/SplashScreen.java index 75ad724c..14b63790 100755..100644 --- a/StoneIsland/platforms/android/src/org/apache/cordova/splashscreen/SplashScreen.java +++ b/StoneIsland/platforms/android/src/org/apache/cordova/splashscreen/SplashScreen.java @@ -25,13 +25,20 @@ import android.content.Context; import android.content.DialogInterface; import android.content.res.Configuration; import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; import android.os.Handler; import android.view.Display; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; +import android.view.animation.Animation; +import android.view.animation.AlphaAnimation; +import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaPlugin; @@ -44,9 +51,12 @@ public class SplashScreen extends CordovaPlugin { // Cordova 3.x.x has a copy of this plugin bundled with it (SplashScreenInternal.java). // Enable functionality only if running on 4.x.x. private static final boolean HAS_BUILT_IN_SPLASH_SCREEN = Integer.valueOf(CordovaWebView.CORDOVA_VERSION.split("\\.")[0]) < 4; + private static final int DEFAULT_SPLASHSCREEN_DURATION = 3000; + private static final int DEFAULT_FADE_DURATION = 500; private static Dialog splashDialog; private static ProgressDialog spinnerDialog; private static boolean firstShow = true; + private static boolean lastHideAfterDelay; // https://issues.apache.org/jira/browse/CB-9094 /** * Displays the splash drawable. @@ -69,11 +79,17 @@ public class SplashScreen extends CordovaPlugin { @Override protected void pluginInitialize() { - if (HAS_BUILT_IN_SPLASH_SCREEN || !firstShow) { + if (HAS_BUILT_IN_SPLASH_SCREEN) { return; } // Make WebView invisible while loading URL - getView().setVisibility(View.INVISIBLE); + // CB-11326 Ensure we're calling this on UI thread + cordova.getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + getView().setVisibility(View.INVISIBLE); + } + }); int drawableId = preferences.getInteger("SplashDrawableId", 0); if (drawableId == 0) { String splashResource = preferences.getString("SplashScreen", "screen"); @@ -89,9 +105,14 @@ public class SplashScreen extends CordovaPlugin { // Save initial orientation. orientation = cordova.getActivity().getResources().getConfiguration().orientation; - firstShow = false; - loadSpinner(); - showSplashScreen(true); + if (firstShow) { + boolean autoHide = preferences.getBoolean("AutoHideSplashScreen", true); + showSplashScreen(autoHide); + } + + if (preferences.getBoolean("SplashShowOnlyFirstTime", true)) { + firstShow = false; + } } /** @@ -101,13 +122,26 @@ public class SplashScreen extends CordovaPlugin { return preferences.getBoolean("SplashMaintainAspectRatio", false); } + private int getFadeDuration () { + int fadeSplashScreenDuration = preferences.getBoolean("FadeSplashScreen", true) ? + preferences.getInteger("FadeSplashScreenDuration", DEFAULT_FADE_DURATION) : 0; + + if (fadeSplashScreenDuration < 30) { + // [CB-9750] This value used to be in decimal seconds, so we will assume that if someone specifies 10 + // they mean 10 seconds, and not the meaningless 10ms + fadeSplashScreenDuration *= 1000; + } + + return fadeSplashScreenDuration; + } + @Override public void onPause(boolean multitasking) { if (HAS_BUILT_IN_SPLASH_SCREEN) { return; } // hide the splash screen to avoid leaking a window - this.removeSplashScreen(); + this.removeSplashScreen(true); } @Override @@ -116,7 +150,7 @@ public class SplashScreen extends CordovaPlugin { return; } // hide the splash screen to avoid leaking a window - this.removeSplashScreen(); + this.removeSplashScreen(true); // If we set this to true onDestroy, we lose track when we go from page to page! //firstShow = true; } @@ -135,16 +169,6 @@ public class SplashScreen extends CordovaPlugin { webView.postMessage("splashscreen", "show"); } }); - } else if (action.equals("spinnerStart")) { - if (!HAS_BUILT_IN_SPLASH_SCREEN) { - final String title = args.getString(0); - final String message = args.getString(1); - cordova.getActivity().runOnUiThread(new Runnable() { - public void run() { - spinnerStart(title, message); - } - }); - } } else { return false; } @@ -160,17 +184,16 @@ public class SplashScreen extends CordovaPlugin { } if ("splashscreen".equals(id)) { if ("hide".equals(data.toString())) { - this.removeSplashScreen(); + this.removeSplashScreen(false); } else { this.showSplashScreen(false); } } else if ("spinner".equals(id)) { if ("stop".equals(data.toString())) { - this.spinnerStop(); getView().setVisibility(View.VISIBLE); } } else if ("onReceivedError".equals(id)) { - spinnerStop(); + this.spinnerStop(); } return null; } @@ -190,13 +213,45 @@ public class SplashScreen extends CordovaPlugin { } } - private void removeSplashScreen() { + private void removeSplashScreen(final boolean forceHideImmediately) { cordova.getActivity().runOnUiThread(new Runnable() { public void run() { if (splashDialog != null && splashDialog.isShowing()) { - splashDialog.dismiss(); - splashDialog = null; - splashImageView = null; + final int fadeSplashScreenDuration = getFadeDuration(); + // CB-10692 If the plugin is being paused/destroyed, skip the fading and hide it immediately + if (fadeSplashScreenDuration > 0 && forceHideImmediately == false) { + AlphaAnimation fadeOut = new AlphaAnimation(1, 0); + fadeOut.setInterpolator(new DecelerateInterpolator()); + fadeOut.setDuration(fadeSplashScreenDuration); + + splashImageView.setAnimation(fadeOut); + splashImageView.startAnimation(fadeOut); + + fadeOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + spinnerStop(); + } + + @Override + public void onAnimationEnd(Animation animation) { + if (splashDialog != null && splashDialog.isShowing()) { + splashDialog.dismiss(); + splashDialog = null; + splashImageView = null; + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + } else { + spinnerStop(); + splashDialog.dismiss(); + splashDialog = null; + splashImageView = null; + } } } }); @@ -207,9 +262,14 @@ public class SplashScreen extends CordovaPlugin { */ @SuppressWarnings("deprecation") private void showSplashScreen(final boolean hideAfterDelay) { - final int splashscreenTime = preferences.getInteger("SplashScreenDelay", 3000); + final int splashscreenTime = preferences.getInteger("SplashScreenDelay", DEFAULT_SPLASHSCREEN_DURATION); final int drawableId = preferences.getInteger("SplashDrawableId", 0); + final int fadeSplashScreenDuration = getFadeDuration(); + final int effectiveSplashDuration = Math.max(0, splashscreenTime - fadeSplashScreenDuration); + + lastHideAfterDelay = hideAfterDelay; + // If the splash dialog is showing don't try to show it again if (splashDialog != null && splashDialog.isShowing()) { return; @@ -257,60 +317,57 @@ public class SplashScreen extends CordovaPlugin { splashDialog.setCancelable(false); splashDialog.show(); + if (preferences.getBoolean("ShowSplashScreenSpinner", true)) { + spinnerStart(); + } + // Set Runnable to remove splash screen just in case if (hideAfterDelay) { final Handler handler = new Handler(); handler.postDelayed(new Runnable() { public void run() { - removeSplashScreen(); + if (lastHideAfterDelay) { + removeSplashScreen(false); + } } - }, splashscreenTime); + }, effectiveSplashDuration); } } }); } - /* - * Load the spinner - */ - private void loadSpinner() { - // If loadingDialog property, then show the App loading dialog for first page of app - String loading = null; - if (webView.canGoBack()) { - loading = preferences.getString("LoadingDialog", null); - } - else { - loading = preferences.getString("LoadingPageDialog", null); - } - if (loading != null) { - String title = ""; - String message = "Loading Application..."; - - if (loading.length() > 0) { - int comma = loading.indexOf(','); - if (comma > 0) { - title = loading.substring(0, comma); - message = loading.substring(comma + 1); - } - else { - title = ""; - message = loading; - } - } - spinnerStart(title, message); - } - } - - private void spinnerStart(final String title, final String message) { + // Show only spinner in the center of the screen + private void spinnerStart() { cordova.getActivity().runOnUiThread(new Runnable() { public void run() { spinnerStop(); - spinnerDialog = ProgressDialog.show(webView.getContext(), title, message, true, true, - new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - spinnerDialog = null; - } - }); + + spinnerDialog = new ProgressDialog(webView.getContext()); + spinnerDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + spinnerDialog = null; + } + }); + + spinnerDialog.setCancelable(false); + spinnerDialog.setIndeterminate(true); + + RelativeLayout centeredLayout = new RelativeLayout(cordova.getActivity()); + centeredLayout.setGravity(Gravity.CENTER); + centeredLayout.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + + ProgressBar progressBar = new ProgressBar(webView.getContext()); + RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); + progressBar.setLayoutParams(layoutParams); + + centeredLayout.addView(progressBar); + + spinnerDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + spinnerDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + + spinnerDialog.show(); + spinnerDialog.setContentView(centeredLayout); } }); } diff --git a/StoneIsland/platforms/android/src/org/apache/cordova/whitelist/WhitelistPlugin.java b/StoneIsland/platforms/android/src/org/apache/cordova/whitelist/WhitelistPlugin.java index 4e4f57e1..36567886 100755..100644 --- a/StoneIsland/platforms/android/src/org/apache/cordova/whitelist/WhitelistPlugin.java +++ b/StoneIsland/platforms/android/src/org/apache/cordova/whitelist/WhitelistPlugin.java @@ -21,11 +21,11 @@ package org.apache.cordova.whitelist; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.ConfigXmlParser; +import org.apache.cordova.LOG; import org.apache.cordova.Whitelist; import org.xmlpull.v1.XmlPullParser; import android.content.Context; -import android.util.Log; public class WhitelistPlugin extends CordovaPlugin { private static final String LOG_TAG = "WhitelistPlugin"; @@ -90,7 +90,7 @@ public class WhitelistPlugin extends CordovaPlugin { boolean external = (xml.getAttributeValue(null, "launch-external") != null); if (origin != null) { if (external) { - Log.w(LOG_TAG, "Found <access launch-external> within config.xml. Please use <allow-intent> instead."); + LOG.w(LOG_TAG, "Found <access launch-external> within config.xml. Please use <allow-intent> instead."); allowedIntents.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0)); } else { if ("*".equals(origin)) { |
