summaryrefslogtreecommitdiff
path: root/StoneIsland/platforms/android/src
diff options
context:
space:
mode:
Diffstat (limited to 'StoneIsland/platforms/android/src')
-rwxr-xr-xStoneIsland/platforms/android/src/com/adobe/phonegap/push/GCMIntentService.java603
-rwxr-xr-xStoneIsland/platforms/android/src/com/adobe/phonegap/push/PushConstants.java53
-rwxr-xr-xStoneIsland/platforms/android/src/com/adobe/phonegap/push/PushHandlerActivity.java70
-rwxr-xr-xStoneIsland/platforms/android/src/com/adobe/phonegap/push/PushInstanceIDListenerService.java27
-rwxr-xr-xStoneIsland/platforms/android/src/com/adobe/phonegap/push/PushPlugin.java294
-rwxr-xr-xStoneIsland/platforms/android/src/com/adobe/phonegap/push/RegistrationIntentService.java42
-rwxr-xr-xStoneIsland/platforms/android/src/com/ionic/keyboard/IonicKeyboard.java96
-rw-r--r--StoneIsland/platforms/android/src/io/ionic/keyboard/IonicKeyboard.java130
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java49
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java280
-rw-r--r--StoneIsland/platforms/android/src/org/apache/cordova/BuildHelper.java70
-rw-r--r--StoneIsland/platforms/android/src/org/apache/cordova/PermissionHelper.java138
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/org/apache/cordova/device/Device.java19
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/org/apache/cordova/dialogs/Notification.java50
-rw-r--r--StoneIsland/platforms/android/src/org/apache/cordova/geolocation/Geolocation.java107
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowser.java294
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowserDialog.java1
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/org/apache/cordova/inappbrowser/InAppChromeClient.java0
-rwxr-xr-xStoneIsland/platforms/android/src/org/apache/cordova/networkinformation/NetworkManager.java72
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/org/apache/cordova/splashscreen/SplashScreen.java187
-rw-r--r--[-rwxr-xr-x]StoneIsland/platforms/android/src/org/apache/cordova/whitelist/WhitelistPlugin.java4
21 files changed, 1190 insertions, 1396 deletions
diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/GCMIntentService.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/GCMIntentService.java
deleted file mode 100755
index 24daa6a5..00000000
--- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/GCMIntentService.java
+++ /dev/null
@@ -1,603 +0,0 @@
-package com.adobe.phonegap.push;
-
-import android.annotation.SuppressLint;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v4.app.NotificationCompat;
-import android.text.Html;
-import android.util.Log;
-
-import com.google.android.gms.gcm.GcmListenerService;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Random;
-
-@SuppressLint("NewApi")
-public class GCMIntentService extends GcmListenerService implements PushConstants {
-
- private static final String LOG_TAG = "PushPlugin_GCMIntentService";
- private static HashMap<Integer, ArrayList<String>> messageMap = new HashMap<Integer, ArrayList<String>>();
-
- public void setNotification(int notId, String message){
- ArrayList<String> messageList = messageMap.get(notId);
- if(messageList == null) {
- messageList = new ArrayList<String>();
- messageMap.put(notId, messageList);
- }
-
- if(message.isEmpty()){
- messageList.clear();
- }else{
- messageList.add(message);
- }
- }
-
- @Override
- public void onMessageReceived(String from, Bundle extras) {
- Log.d(LOG_TAG, "onMessage - from: " + from);
-
- if (extras != null) {
-
- SharedPreferences prefs = getApplicationContext().getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE);
- boolean forceShow = prefs.getBoolean(FORCE_SHOW, false);
-
- extras = normalizeExtras(extras);
-
- // if we are in the foreground and forceShow is `false` only send data
- if (!forceShow && PushPlugin.isInForeground()) {
- Log.d(LOG_TAG, "foreground");
- extras.putBoolean(FOREGROUND, true);
- PushPlugin.sendExtras(extras);
- }
- // if we are in the foreground and forceShow is `true`, force show the notification if the data has at least a message or title
- else if (forceShow && PushPlugin.isInForeground()) {
- Log.d(LOG_TAG, "foreground force");
- extras.putBoolean(FOREGROUND, true);
-
- showNotificationIfPossible(getApplicationContext(), extras);
- }
- // if we are not in the foreground always send notification if the data has at least a message or title
- else {
- Log.d(LOG_TAG, "background");
- extras.putBoolean(FOREGROUND, false);
-
- showNotificationIfPossible(getApplicationContext(), extras);
- }
- }
- }
-
- /*
- * Change a values key in the extras bundle
- */
- private void replaceKey(String oldKey, String newKey, Bundle extras, Bundle newExtras) {
- Object value = extras.get(oldKey);
- if ( value != null ) {
- if (value instanceof String) {
- newExtras.putString(newKey, (String) value);
- } else if (value instanceof Boolean) {
- newExtras.putBoolean(newKey, (Boolean) value);
- } else if (value instanceof Number) {
- newExtras.putDouble(newKey, ((Number) value).doubleValue());
- } else {
- newExtras.putString(newKey, String.valueOf(value));
- }
- }
- }
-
- /*
- * Replace alternate keys with our canonical value
- */
- private String normalizeKey(String key) {
- if (key.equals(BODY) || key.equals(ALERT) || key.equals(GCM_NOTIFICATION_BODY)) {
- return MESSAGE;
- } else if (key.equals(MSGCNT) || key.equals(BADGE)) {
- return COUNT;
- } else if (key.equals(SOUNDNAME)) {
- return SOUND;
- } else if (key.startsWith(GCM_NOTIFICATION)) {
- return key.substring(GCM_NOTIFICATION.length()+1, key.length());
- } else if (key.startsWith(GCM_N)) {
- return key.substring(GCM_N.length()+1, key.length());
- } else if (key.startsWith(UA_PREFIX)) {
- key = key.substring(UA_PREFIX.length()+1, key.length());
- return key.toLowerCase();
- } else {
- return key;
- }
- }
-
- /*
- * Parse bundle into normalized keys.
- */
- private Bundle normalizeExtras(Bundle extras) {
- Log.d(LOG_TAG, "normalize extras");
- Iterator<String> it = extras.keySet().iterator();
- Bundle newExtras = new Bundle();
-
- while (it.hasNext()) {
- String key = it.next();
-
- Log.d(LOG_TAG, "key = " + key);
-
- // If normalizeKeythe key is "data" or "message" and the value is a json object extract
- // This is to support parse.com and other services. Issue #147 and pull #218
- if (key.equals(PARSE_COM_DATA) || key.equals(MESSAGE)) {
- Object json = extras.get(key);
- // Make sure data is json object stringified
- if ( json instanceof String && ((String) json).startsWith("{") ) {
- Log.d(LOG_TAG, "extracting nested message data from key = " + key);
- try {
- // If object contains message keys promote each value to the root of the bundle
- JSONObject data = new JSONObject((String) json);
- if ( data.has(ALERT) || data.has(MESSAGE) || data.has(BODY) || data.has(TITLE) ) {
- Iterator<String> jsonIter = data.keys();
- while (jsonIter.hasNext()) {
- String jsonKey = jsonIter.next();
-
- Log.d(LOG_TAG, "key = data/" + jsonKey);
-
- String value = data.getString(jsonKey);
- jsonKey = normalizeKey(jsonKey);
- newExtras.putString(jsonKey, value);
- }
- }
- } catch( JSONException e) {
- Log.e(LOG_TAG, "normalizeExtras: JSON exception");
- }
- }
- } else if (key.equals(("notification"))) {
- Bundle value = extras.getBundle(key);
- Iterator<String> iterator = value.keySet().iterator();
- while (iterator.hasNext()) {
- String notifkey = iterator.next();
-
- Log.d(LOG_TAG, "notifkey = " + notifkey);
- String newKey = normalizeKey(notifkey);
- Log.d(LOG_TAG, "replace key " + notifkey + " with " + newKey);
-
- newExtras.putString(newKey, value.getString(notifkey));
- }
- continue;
- }
-
- String newKey = normalizeKey(key);
- Log.d(LOG_TAG, "replace key " + key + " with " + newKey);
- replaceKey(key, newKey, extras, newExtras);
-
- } // while
-
- return newExtras;
- }
-
- private void showNotificationIfPossible (Context context, Bundle extras) {
-
- // Send a notification if there is a message or title, otherwise just send data
- String message = extras.getString(MESSAGE);
- String title = extras.getString(TITLE);
-
- Log.d(LOG_TAG, "message =[" + message + "]");
- Log.d(LOG_TAG, "title =[" + title + "]");
-
- if ((message != null && message.length() != 0) ||
- (title != null && title.length() != 0)) {
-
- Log.d(LOG_TAG, "create notification");
-
- createNotification(context, extras);
- } else {
- Log.d(LOG_TAG, "send notification event");
- PushPlugin.sendExtras(extras);
- }
- }
-
- public void createNotification(Context context, Bundle extras) {
- NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- String appName = getAppName(this);
- String packageName = context.getPackageName();
- Resources resources = context.getResources();
-
- int notId = parseInt(NOT_ID, extras);
- Intent notificationIntent = new Intent(this, PushHandlerActivity.class);
- notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- notificationIntent.putExtra(PUSH_BUNDLE, extras);
- notificationIntent.putExtra(NOT_ID, notId);
-
- int requestCode = new Random().nextInt();
- PendingIntent contentIntent = PendingIntent.getActivity(this, requestCode, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- NotificationCompat.Builder mBuilder =
- new NotificationCompat.Builder(context)
- .setWhen(System.currentTimeMillis())
- .setContentTitle(extras.getString(TITLE))
- .setTicker(extras.getString(TITLE))
- .setContentIntent(contentIntent)
- .setAutoCancel(true);
-
- SharedPreferences prefs = context.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE);
- String localIcon = prefs.getString(ICON, null);
- String localIconColor = prefs.getString(ICON_COLOR, null);
- boolean soundOption = prefs.getBoolean(SOUND, true);
- boolean vibrateOption = prefs.getBoolean(VIBRATE, true);
- Log.d(LOG_TAG, "stored icon=" + localIcon);
- Log.d(LOG_TAG, "stored iconColor=" + localIconColor);
- Log.d(LOG_TAG, "stored sound=" + soundOption);
- Log.d(LOG_TAG, "stored vibrate=" + vibrateOption);
-
- /*
- * Notification Vibration
- */
-
- setNotificationVibration(extras, vibrateOption, mBuilder);
-
- /*
- * Notification Icon Color
- *
- * Sets the small-icon background color of the notification.
- * To use, add the `iconColor` key to plugin android options
- *
- */
- setNotificationIconColor(extras.getString("color"), mBuilder, localIconColor);
-
- /*
- * Notification Icon
- *
- * Sets the small-icon of the notification.
- *
- * - checks the plugin options for `icon` key
- * - if none, uses the application icon
- *
- * The icon value must be a string that maps to a drawable resource.
- * If no resource is found, falls
- *
- */
- setNotificationSmallIcon(context, extras, packageName, resources, mBuilder, localIcon);
-
- /*
- * Notification Large-Icon
- *
- * Sets the large-icon of the notification
- *
- * - checks the gcm data for the `image` key
- * - checks to see if remote image, loads it.
- * - checks to see if assets image, Loads It.
- * - checks to see if resource image, LOADS IT!
- * - if none, we don't set the large icon
- *
- */
- setNotificationLargeIcon(extras, packageName, resources, mBuilder);
-
- /*
- * Notification Sound
- */
- if (soundOption) {
- setNotificationSound(context, extras, mBuilder);
- }
-
- /*
- * LED Notification
- */
- setNotificationLedColor(extras, mBuilder);
-
- /*
- * Priority Notification
- */
- setNotificationPriority(extras, mBuilder);
-
- /*
- * Notification message
- */
- setNotificationMessage(notId, extras, mBuilder);
-
- /*
- * Notification count
- */
- setNotificationCount(extras, mBuilder);
-
- /*
- * Notification add actions
- */
- createActions(extras, mBuilder, resources, packageName);
-
- mNotificationManager.notify(appName, notId, mBuilder.build());
- }
-
- private void createActions(Bundle extras, NotificationCompat.Builder mBuilder, Resources resources, String packageName) {
- Log.d(LOG_TAG, "create actions");
- String actions = extras.getString(ACTIONS);
- if (actions != null) {
- try {
- JSONArray actionsArray = new JSONArray(actions);
- for (int i=0; i < actionsArray.length(); i++) {
- Log.d(LOG_TAG, "adding action");
- JSONObject action = actionsArray.getJSONObject(i);
- Log.d(LOG_TAG, "adding callback = " + action.getString(CALLBACK));
- Intent intent = new Intent(this, PushHandlerActivity.class);
- intent.putExtra(CALLBACK, action.getString(CALLBACK));
- intent.putExtra(PUSH_BUNDLE, extras);
- PendingIntent pIntent = PendingIntent.getActivity(this, i, intent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- mBuilder.addAction(resources.getIdentifier(action.getString(ICON), DRAWABLE, packageName),
- action.getString(TITLE), pIntent);
- }
- } catch(JSONException e) {
- // nope
- }
- }
- }
-
- private void setNotificationCount(Bundle extras, NotificationCompat.Builder mBuilder) {
- String msgcnt = extras.getString(MSGCNT);
- if (msgcnt == null) {
- msgcnt = extras.getString(BADGE);
- }
- if (msgcnt != null) {
- mBuilder.setNumber(Integer.parseInt(msgcnt));
- }
- }
-
- private void setNotificationVibration(Bundle extras, Boolean vibrateOption, NotificationCompat.Builder mBuilder) {
- String vibrationPattern = extras.getString(VIBRATION_PATTERN);
- if (vibrationPattern != null) {
- String[] items = vibrationPattern.replaceAll("\\[", "").replaceAll("\\]", "").split(",");
- long[] results = new long[items.length];
- for (int i = 0; i < items.length; i++) {
- try {
- results[i] = Long.parseLong(items[i]);
- } catch (NumberFormatException nfe) {}
- }
- mBuilder.setVibrate(results);
- } else {
- if (vibrateOption) {
- mBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
- }
- }
- }
-
- private void setNotificationMessage(int notId, Bundle extras, NotificationCompat.Builder mBuilder) {
- String message = extras.getString(MESSAGE);
-
- String style = extras.getString(STYLE, STYLE_TEXT);
- if(STYLE_INBOX.equals(style)) {
- setNotification(notId, message);
-
- mBuilder.setContentText(message);
-
- ArrayList<String> messageList = messageMap.get(notId);
- Integer sizeList = messageList.size();
- if (sizeList > 1) {
- String sizeListMessage = sizeList.toString();
- String stacking = sizeList + " more";
- if (extras.getString(SUMMARY_TEXT) != null) {
- stacking = extras.getString(SUMMARY_TEXT);
- stacking = stacking.replace("%n%", sizeListMessage);
- }
- NotificationCompat.InboxStyle notificationInbox = new NotificationCompat.InboxStyle()
- .setBigContentTitle(extras.getString(TITLE))
- .setSummaryText(stacking);
-
- for (int i = messageList.size() - 1; i >= 0; i--) {
- notificationInbox.addLine(Html.fromHtml(messageList.get(i)));
- }
-
- mBuilder.setStyle(notificationInbox);
- } else {
- NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
- if (message != null) {
- bigText.bigText(message);
- bigText.setBigContentTitle(extras.getString(TITLE));
- mBuilder.setStyle(bigText);
- }
- }
- } else if (STYLE_PICTURE.equals(style)) {
- setNotification(notId, "");
-
- NotificationCompat.BigPictureStyle bigPicture = new NotificationCompat.BigPictureStyle();
- bigPicture.bigPicture(getBitmapFromURL(extras.getString(PICTURE)));
- bigPicture.setBigContentTitle(extras.getString(TITLE));
- bigPicture.setSummaryText(extras.getString(SUMMARY_TEXT));
-
- mBuilder.setContentTitle(extras.getString(TITLE));
- mBuilder.setContentText(message);
-
- mBuilder.setStyle(bigPicture);
- } else {
- setNotification(notId, "");
-
- NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
-
- if (message != null) {
- mBuilder.setContentText(Html.fromHtml(message));
-
- bigText.bigText(message);
- bigText.setBigContentTitle(extras.getString(TITLE));
-
- String summaryText = extras.getString(SUMMARY_TEXT);
- if (summaryText != null) {
- bigText.setSummaryText(summaryText);
- }
-
- mBuilder.setStyle(bigText);
- }
- /*
- else {
- mBuilder.setContentText("<missing message content>");
- }
- */
- }
- }
-
- private void setNotificationSound(Context context, Bundle extras, NotificationCompat.Builder mBuilder) {
- String soundname = extras.getString(SOUNDNAME);
- if (soundname == null) {
- soundname = extras.getString(SOUND);
- }
- if (soundname != null && !soundname.contentEquals(SOUND_DEFAULT)) {
- Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
- + "://" + context.getPackageName() + "/raw/" + soundname);
- Log.d(LOG_TAG, sound.toString());
- mBuilder.setSound(sound);
- } else {
- mBuilder.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI);
- }
- }
-
- private void setNotificationLedColor(Bundle extras, NotificationCompat.Builder mBuilder) {
- String ledColor = extras.getString(LED_COLOR);
- if (ledColor != null) {
- // Converts parse Int Array from ledColor
- String[] items = ledColor.replaceAll("\\[", "").replaceAll("\\]", "").split(",");
- int[] results = new int[items.length];
- for (int i = 0; i < items.length; i++) {
- try {
- results[i] = Integer.parseInt(items[i]);
- } catch (NumberFormatException nfe) {}
- }
- if (results.length == 4) {
- mBuilder.setLights(Color.argb(results[0], results[1], results[2], results[3]), 500, 500);
- } else {
- Log.e(LOG_TAG, "ledColor parameter must be an array of length == 4 (ARGB)");
- }
- }
- }
-
- private void setNotificationPriority(Bundle extras, NotificationCompat.Builder mBuilder) {
- String priorityStr = extras.getString(PRIORITY);
- if (priorityStr != null) {
- try {
- Integer priority = Integer.parseInt(priorityStr);
- if (priority >= NotificationCompat.PRIORITY_MIN && priority <= NotificationCompat.PRIORITY_MAX) {
- mBuilder.setPriority(priority);
- } else {
- Log.e(LOG_TAG, "Priority parameter must be between -2 and 2");
- }
- } catch (NumberFormatException e) {
- e.printStackTrace();
- }
- }
- }
-
- private void setNotificationLargeIcon(Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder) {
- String gcmLargeIcon = extras.getString(IMAGE); // from gcm
- if (gcmLargeIcon != null) {
- if (gcmLargeIcon.startsWith("http://") || gcmLargeIcon.startsWith("https://")) {
- mBuilder.setLargeIcon(getBitmapFromURL(gcmLargeIcon));
- Log.d(LOG_TAG, "using remote large-icon from gcm");
- } else {
- AssetManager assetManager = getAssets();
- InputStream istr;
- try {
- istr = assetManager.open(gcmLargeIcon);
- Bitmap bitmap = BitmapFactory.decodeStream(istr);
- mBuilder.setLargeIcon(bitmap);
- Log.d(LOG_TAG, "using assets large-icon from gcm");
- } catch (IOException e) {
- int largeIconId = 0;
- largeIconId = resources.getIdentifier(gcmLargeIcon, DRAWABLE, packageName);
- if (largeIconId != 0) {
- Bitmap largeIconBitmap = BitmapFactory.decodeResource(resources, largeIconId);
- mBuilder.setLargeIcon(largeIconBitmap);
- Log.d(LOG_TAG, "using resources large-icon from gcm");
- } else {
- Log.d(LOG_TAG, "Not setting large icon");
- }
- }
- }
- }
- }
-
- private void setNotificationSmallIcon(Context context, Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder, String localIcon) {
- int iconId = 0;
- String icon = extras.getString(ICON);
- if (icon != null) {
- iconId = resources.getIdentifier(icon, DRAWABLE, packageName);
- Log.d(LOG_TAG, "using icon from plugin options");
- }
- else if (localIcon != null) {
- iconId = resources.getIdentifier(localIcon, DRAWABLE, packageName);
- Log.d(LOG_TAG, "using icon from plugin options");
- }
- if (iconId == 0) {
- Log.d(LOG_TAG, "no icon resource found - using application icon");
- iconId = context.getApplicationInfo().icon;
- }
- mBuilder.setSmallIcon(iconId);
- }
-
- private void setNotificationIconColor(String color, NotificationCompat.Builder mBuilder, String localIconColor) {
- int iconColor = 0;
- if (color != null) {
- try {
- iconColor = Color.parseColor(color);
- } catch (IllegalArgumentException e) {
- Log.e(LOG_TAG, "couldn't parse color from android options");
- }
- }
- else if (localIconColor != null) {
- try {
- iconColor = Color.parseColor(localIconColor);
- } catch (IllegalArgumentException e) {
- Log.e(LOG_TAG, "couldn't parse color from android options");
- }
- }
- if (iconColor != 0) {
- mBuilder.setColor(iconColor);
- }
- }
-
- public Bitmap getBitmapFromURL(String strURL) {
- try {
- URL url = new URL(strURL);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setDoInput(true);
- connection.connect();
- InputStream input = connection.getInputStream();
- return BitmapFactory.decodeStream(input);
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- private static String getAppName(Context context) {
- CharSequence appName = context.getPackageManager().getApplicationLabel(context.getApplicationInfo());
- return (String)appName;
- }
-
- private int parseInt(String value, Bundle extras) {
- int retval = 0;
-
- try {
- retval = Integer.parseInt(extras.getString(value));
- }
- catch(NumberFormatException e) {
- Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage());
- }
- catch(Exception e) {
- Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage());
- }
-
- return retval;
- }
-}
diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushConstants.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushConstants.java
deleted file mode 100755
index aeb49c9b..00000000
--- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushConstants.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.adobe.phonegap.push;
-
-public interface PushConstants {
- public static final String COM_ADOBE_PHONEGAP_PUSH = "com.adobe.phonegap.push";
- public static final String REGISTRATION_ID = "registrationId";
- public static final String FOREGROUND = "foreground";
- public static final String TITLE = "title";
- public static final String NOT_ID = "notId";
- public static final String PUSH_BUNDLE = "pushBundle";
- public static final String ICON = "icon";
- public static final String ICON_COLOR = "iconColor";
- public static final String SOUND = "sound";
- public static final String SOUND_DEFAULT = "default";
- public static final String VIBRATE = "vibrate";
- public static final String ACTIONS = "actions";
- public static final String CALLBACK = "callback";
- public static final String DRAWABLE = "drawable";
- public static final String MSGCNT = "msgcnt";
- public static final String VIBRATION_PATTERN = "vibrationPattern";
- public static final String STYLE = "style";
- public static final String SUMMARY_TEXT = "summaryText";
- public static final String PICTURE = "picture";
- public static final String GCM_N = "gcm.n.";
- public static final String GCM_NOTIFICATION = "gcm.notification";
- public static final String GCM_NOTIFICATION_BODY = "gcm.notification.body";
- public static final String UA_PREFIX = "com.urbanairship.push";
- public static final String PARSE_COM_DATA = "data";
- public static final String ALERT = "alert";
- public static final String MESSAGE = "message";
- public static final String BODY = "body";
- public static final String SOUNDNAME = "soundname";
- public static final String LED_COLOR = "ledColor";
- public static final String PRIORITY = "priority";
- public static final String IMAGE = "image";
- public static final String STYLE_INBOX = "inbox";
- public static final String STYLE_PICTURE = "picture";
- public static final String STYLE_TEXT = "text";
- public static final String BADGE = "badge";
- public static final String INITIALIZE = "init";
- public static final String UNREGISTER = "unregister";
- public static final String EXIT = "exit";
- public static final String FINISH = "finish";
- public static final String ANDROID = "android";
- public static final String SENDER_ID = "senderID";
- public static final String CLEAR_NOTIFICATIONS = "clearNotifications";
- public static final String COLDSTART = "coldstart";
- public static final String ADDITIONAL_DATA = "additionalData";
- public static final String COUNT = "count";
- public static final String FROM = "from";
- public static final String COLLAPSE_KEY = "collapse_key";
- public static final String FORCE_SHOW = "forceShow";
- public static final String GCM = "GCM";
-}
diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushHandlerActivity.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushHandlerActivity.java
deleted file mode 100755
index dd9fbd36..00000000
--- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushHandlerActivity.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.adobe.phonegap.push;
-
-import android.app.Activity;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.util.Log;
-
-public class PushHandlerActivity extends Activity implements PushConstants {
- private static String LOG_TAG = "PushPlugin_PushHandlerActivity";
-
- /*
- * this activity will be started if the user touches a notification that we own.
- * We send it's data off to the push plugin for processing.
- * If needed, we boot up the main activity to kickstart the application.
- * @see android.app.Activity#onCreate(android.os.Bundle)
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- GCMIntentService gcm = new GCMIntentService();
- gcm.setNotification(getIntent().getIntExtra(NOT_ID, 0), "");
- super.onCreate(savedInstanceState);
- Log.v(LOG_TAG, "onCreate");
-
- boolean isPushPluginActive = PushPlugin.isActive();
- processPushBundle(isPushPluginActive);
-
- finish();
-
- if (!isPushPluginActive) {
- forceMainActivityReload();
- }
- }
-
- /**
- * Takes the pushBundle extras from the intent,
- * and sends it through to the PushPlugin for processing.
- */
- private void processPushBundle(boolean isPushPluginActive) {
- Bundle extras = getIntent().getExtras();
-
- if (extras != null) {
- Bundle originalExtras = extras.getBundle(PUSH_BUNDLE);
-
- originalExtras.putBoolean(FOREGROUND, false);
- originalExtras.putBoolean(COLDSTART, !isPushPluginActive);
- originalExtras.putString(CALLBACK, extras.getString("callback"));
-
- PushPlugin.sendExtras(originalExtras);
- }
- }
-
- /**
- * Forces the main activity to re-launch if it's unloaded.
- */
- private void forceMainActivityReload() {
- PackageManager pm = getPackageManager();
- Intent launchIntent = pm.getLaunchIntentForPackage(getApplicationContext().getPackageName());
- startActivity(launchIntent);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- final NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.cancelAll();
- }
-} \ No newline at end of file
diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushInstanceIDListenerService.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushInstanceIDListenerService.java
deleted file mode 100755
index eaa39a48..00000000
--- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushInstanceIDListenerService.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.adobe.phonegap.push;
-
-import android.content.Intent;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-import com.google.android.gms.iid.InstanceID;
-import com.google.android.gms.iid.InstanceIDListenerService;
-
-import org.json.JSONException;
-
-import java.io.IOException;
-
-public class PushInstanceIDListenerService extends InstanceIDListenerService implements PushConstants {
- public static final String LOG_TAG = "PushPlugin_PushInstanceIDListenerService";
-
- @Override
- public void onTokenRefresh() {
- SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE);
- String senderID = sharedPref.getString(SENDER_ID, "");
- if (!"".equals(senderID)) {
- Intent intent = new Intent(this, RegistrationIntentService.class);
- startService(intent);
- }
- }
-}
diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushPlugin.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushPlugin.java
deleted file mode 100755
index 41a91819..00000000
--- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/PushPlugin.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package com.adobe.phonegap.push;
-
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.util.Log;
-
-import com.google.android.gms.iid.InstanceID;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.PluginResult;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-
-public class PushPlugin extends CordovaPlugin implements PushConstants {
-
- public static final String LOG_TAG = "PushPlugin";
-
- private static CallbackContext pushContext;
- private static CordovaWebView gWebView;
- private static Bundle gCachedExtras = null;
- private static boolean gForeground = false;
-
- /**
- * Gets the application context from cordova's main activity.
- * @return the application context
- */
- private Context getApplicationContext() {
- return this.cordova.getActivity().getApplicationContext();
- }
-
- @Override
- public boolean execute(final String action, final JSONArray data, final CallbackContext callbackContext) {
- Log.v(LOG_TAG, "execute: action=" + action);
- gWebView = this.webView;
-
- if (INITIALIZE.equals(action)) {
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- pushContext = callbackContext;
- JSONObject jo = null;
-
- Log.v(LOG_TAG, "execute: data=" + data.toString());
- SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE);
- String token = null;
- String senderID = null;
-
- try {
- jo = data.getJSONObject(0).getJSONObject(ANDROID);
-
- Log.v(LOG_TAG, "execute: jo=" + jo.toString());
-
- senderID = jo.getString(SENDER_ID);
-
- Log.v(LOG_TAG, "execute: senderID=" + senderID);
-
- String savedSenderID = sharedPref.getString(SENDER_ID, "");
- String savedRegID = sharedPref.getString(REGISTRATION_ID, "");
-
- // first time run get new token
- if ("".equals(savedRegID)) {
- token = InstanceID.getInstance(getApplicationContext()).getToken(senderID, GCM);
- }
- // new sender ID, re-register
- else if (!savedSenderID.equals(senderID)) {
- token = InstanceID.getInstance(getApplicationContext()).getToken(senderID, GCM);
- }
- // use the saved one
- else {
- token = sharedPref.getString(REGISTRATION_ID, "");
- }
-
- if (!"".equals(token)) {
- JSONObject json = new JSONObject().put(REGISTRATION_ID, token);
-
- Log.v(LOG_TAG, "onRegistered: " + json.toString());
-
- PushPlugin.sendEvent( json );
- } else {
- callbackContext.error("Empty registration ID received from GCM");
- return;
- }
- } catch (JSONException e) {
- Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage());
- callbackContext.error(e.getMessage());
- } catch (IOException e) {
- Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage());
- callbackContext.error(e.getMessage());
- }
-
- if (jo != null) {
- SharedPreferences.Editor editor = sharedPref.edit();
- try {
- editor.putString(ICON, jo.getString(ICON));
- } catch (JSONException e) {
- Log.d(LOG_TAG, "no icon option");
- }
- try {
- editor.putString(ICON_COLOR, jo.getString(ICON_COLOR));
- } catch (JSONException e) {
- Log.d(LOG_TAG, "no iconColor option");
- }
- editor.putBoolean(SOUND, jo.optBoolean(SOUND, true));
- editor.putBoolean(VIBRATE, jo.optBoolean(VIBRATE, true));
- editor.putBoolean(CLEAR_NOTIFICATIONS, jo.optBoolean(CLEAR_NOTIFICATIONS, true));
- editor.putBoolean(FORCE_SHOW, jo.optBoolean(FORCE_SHOW, false));
- editor.putString(SENDER_ID, senderID);
- editor.putString(REGISTRATION_ID, token);
- editor.commit();
- }
-
- if (gCachedExtras != null) {
- Log.v(LOG_TAG, "sending cached extras");
- sendExtras(gCachedExtras);
- gCachedExtras = null;
- }
- }
- });
- } else if (UNREGISTER.equals(action)) {
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- try {
- InstanceID.getInstance(getApplicationContext()).deleteInstanceID();
- Log.v(LOG_TAG, "UNREGISTER");
-
- // Remove shared prefs
- SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPref.edit();
- editor.remove(SOUND);
- editor.remove(VIBRATE);
- editor.remove(CLEAR_NOTIFICATIONS);
- editor.remove(FORCE_SHOW);
- editor.remove(SENDER_ID);
- editor.remove(REGISTRATION_ID);
- editor.commit();
-
- callbackContext.success();
- } catch (IOException e) {
- Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage());
- callbackContext.error(e.getMessage());
- }
- }
- });
- } else if (FINISH.equals(action)) {
- callbackContext.success();
- } else {
- Log.e(LOG_TAG, "Invalid action : " + action);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- return true;
- }
-
- public static void sendEvent(JSONObject _json) {
- PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, _json);
- pluginResult.setKeepCallback(true);
- if (pushContext != null) {
- pushContext.sendPluginResult(pluginResult);
- }
- }
-
- public static void sendError(String message) {
- PluginResult pluginResult = new PluginResult(PluginResult.Status.ERROR, message);
- pluginResult.setKeepCallback(true);
- if (pushContext != null) {
- pushContext.sendPluginResult(pluginResult);
- }
- }
-
- /*
- * Sends the pushbundle extras to the client application.
- * If the client application isn't currently active, it is cached for later processing.
- */
- public static void sendExtras(Bundle extras) {
- if (extras != null) {
- if (gWebView != null) {
- sendEvent(convertBundleToJson(extras));
- } else {
- Log.v(LOG_TAG, "sendExtras: caching extras to send at a later time.");
- gCachedExtras = extras;
- }
- }
- }
-
- @Override
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- super.initialize(cordova, webView);
- gForeground = true;
- }
-
- @Override
- public void onPause(boolean multitasking) {
- super.onPause(multitasking);
- gForeground = false;
-
- SharedPreferences prefs = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE);
- if (prefs.getBoolean(CLEAR_NOTIFICATIONS, true)) {
- final NotificationManager notificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.cancelAll();
- }
- }
-
- @Override
- public void onResume(boolean multitasking) {
- super.onResume(multitasking);
- gForeground = true;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- gForeground = false;
- gWebView = null;
- }
-
- /*
- * serializes a bundle to JSON.
- */
- private static JSONObject convertBundleToJson(Bundle extras) {
- Log.d(LOG_TAG, "convert extras to json");
- try {
- JSONObject json = new JSONObject();
- JSONObject additionalData = new JSONObject();
-
- // Add any keys that need to be in top level json to this set
- HashSet<String> jsonKeySet = new HashSet();
- Collections.addAll(jsonKeySet, TITLE,MESSAGE,COUNT,SOUND,IMAGE);
-
- Iterator<String> it = extras.keySet().iterator();
- while (it.hasNext()) {
- String key = it.next();
- Object value = extras.get(key);
-
- Log.d(LOG_TAG, "key = " + key);
-
- if (jsonKeySet.contains(key)) {
- json.put(key, value);
- }
- else if (key.equals(COLDSTART)) {
- additionalData.put(key, extras.getBoolean(COLDSTART));
- }
- else if (key.equals(FOREGROUND)) {
- additionalData.put(key, extras.getBoolean(FOREGROUND));
- }
- else if ( value instanceof String ) {
- String strValue = (String)value;
- try {
- // Try to figure out if the value is another JSON object
- if (strValue.startsWith("{")) {
- additionalData.put(key, new JSONObject(strValue));
- }
- // Try to figure out if the value is another JSON array
- else if (strValue.startsWith("[")) {
- additionalData.put(key, new JSONArray(strValue));
- }
- else {
- additionalData.put(key, value);
- }
- } catch (Exception e) {
- additionalData.put(key, value);
- }
- }
- } // while
-
- json.put(ADDITIONAL_DATA, additionalData);
- Log.v(LOG_TAG, "extrasToJSON: " + json.toString());
-
- return json;
- }
- catch( JSONException e) {
- Log.e(LOG_TAG, "extrasToJSON: JSON exception");
- }
- return null;
- }
-
- public static boolean isInForeground() {
- return gForeground;
- }
-
- public static boolean isActive() {
- return gWebView != null;
- }
-} \ No newline at end of file
diff --git a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/RegistrationIntentService.java b/StoneIsland/platforms/android/src/com/adobe/phonegap/push/RegistrationIntentService.java
deleted file mode 100755
index c4489fc1..00000000
--- a/StoneIsland/platforms/android/src/com/adobe/phonegap/push/RegistrationIntentService.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.adobe.phonegap.push;
-
-import android.content.Context;
-
-import android.app.IntentService;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.util.Log;
-
-import com.google.android.gms.gcm.GoogleCloudMessaging;
-import com.google.android.gms.iid.InstanceID;
-
-import java.io.IOException;
-
-public class RegistrationIntentService extends IntentService implements PushConstants {
- public static final String LOG_TAG = "PushPlugin_RegistrationIntentService";
-
- public RegistrationIntentService() {
- super(LOG_TAG);
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE);
-
- try {
- InstanceID instanceID = InstanceID.getInstance(this);
- String senderID = sharedPreferences.getString(SENDER_ID, "");
- String token = instanceID.getToken(senderID,
- GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
- Log.i(LOG_TAG, "new GCM Registration Token: " + token);
-
- // save new token
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.putString(REGISTRATION_ID, token);
- editor.commit();
-
- } catch (Exception e) {
- Log.d(LOG_TAG, "Failed to complete token refresh", e);
- }
- }
-} \ No newline at end of file
diff --git a/StoneIsland/platforms/android/src/com/ionic/keyboard/IonicKeyboard.java b/StoneIsland/platforms/android/src/com/ionic/keyboard/IonicKeyboard.java
deleted file mode 100755
index deb914ab..00000000
--- a/StoneIsland/platforms/android/src/com/ionic/keyboard/IonicKeyboard.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.ionic.keyboard;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.PluginResult.Status;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-import android.view.inputmethod.InputMethodManager;
-
-public class IonicKeyboard extends CordovaPlugin{
-
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- super.initialize(cordova, webView);
-
- //calculate density-independent pixels (dp)
- //http://developer.android.com/guide/practices/screens_support.html
- DisplayMetrics dm = new DisplayMetrics();
- cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
- final float density = dm.density;
-
- final CordovaWebView appView = webView;
-
- //http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing
- final View rootView = cordova.getActivity().getWindow().getDecorView().findViewById(android.R.id.content).getRootView();
- OnGlobalLayoutListener list = new OnGlobalLayoutListener() {
- int previousHeightDiff = 0;
- @Override
- public void onGlobalLayout() {
- Rect r = new Rect();
- //r will be populated with the coordinates of your view that area still visible.
- rootView.getWindowVisibleDisplayFrame(r);
-
- int heightDiff = rootView.getRootView().getHeight() - (r.bottom - r.top);
- int pixelHeightDiff = (int)(heightDiff / density);
- if (pixelHeightDiff > 100 && pixelHeightDiff != previousHeightDiff) { // if more than 100 pixels, its probably a keyboard...
- appView.sendJavascript("cordova.plugins.Keyboard.isVisible = true");
- appView.sendJavascript("cordova.fireWindowEvent('native.keyboardshow', { 'keyboardHeight':" + Integer.toString(pixelHeightDiff)+"});");
-
- //deprecated
- appView.sendJavascript("cordova.fireWindowEvent('native.showkeyboard', { 'keyboardHeight':" + Integer.toString(pixelHeightDiff)+"});");
- }
- else if ( pixelHeightDiff != previousHeightDiff && ( previousHeightDiff - pixelHeightDiff ) > 100 ){
- appView.sendJavascript("cordova.plugins.Keyboard.isVisible = false");
- appView.sendJavascript("cordova.fireWindowEvent('native.keyboardhide')");
-
- //deprecated
- appView.sendJavascript("cordova.fireWindowEvent('native.hidekeyboard')");
- }
- previousHeightDiff = pixelHeightDiff;
- }
- };
-
- rootView.getViewTreeObserver().addOnGlobalLayoutListener(list);
- }
-
- public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
- if ("close".equals(action)) {
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- //http://stackoverflow.com/a/7696791/1091751
- InputMethodManager inputManager = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
- View v = cordova.getActivity().getCurrentFocus();
-
- if (v == null) {
- callbackContext.error("No current focus");
- } else {
- inputManager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
- callbackContext.success(); // Thread-safe.
- }
- }
- });
- return true;
- }
- if ("show".equals(action)) {
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- ((InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
- callbackContext.success(); // Thread-safe.
- }
- });
- return true;
- }
- return false; // Returning false results in a "MethodNotFound" error.
- }
-
-
-}
-
diff --git a/StoneIsland/platforms/android/src/io/ionic/keyboard/IonicKeyboard.java b/StoneIsland/platforms/android/src/io/ionic/keyboard/IonicKeyboard.java
new file mode 100644
index 00000000..128063b9
--- /dev/null
+++ b/StoneIsland/platforms/android/src/io/ionic/keyboard/IonicKeyboard.java
@@ -0,0 +1,130 @@
+package io.ionic.keyboard;
+
+import org.apache.cordova.CallbackContext;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaWebView;
+import org.apache.cordova.PluginResult;
+import org.apache.cordova.PluginResult.Status;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.inputmethod.InputMethodManager;
+
+// import additionally required classes for calculating screen height
+import android.view.Display;
+import android.graphics.Point;
+import android.os.Build;
+
+public class IonicKeyboard extends CordovaPlugin {
+
+ public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+ super.initialize(cordova, webView);
+ }
+
+ public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
+ if ("close".equals(action)) {
+ cordova.getThreadPool().execute(new Runnable() {
+ public void run() {
+ //http://stackoverflow.com/a/7696791/1091751
+ InputMethodManager inputManager = (InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+ View v = cordova.getActivity().getCurrentFocus();
+
+ if (v == null) {
+ callbackContext.error("No current focus");
+ } else {
+ inputManager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+ callbackContext.success(); // Thread-safe.
+ }
+ }
+ });
+ return true;
+ }
+ if ("show".equals(action)) {
+ cordova.getThreadPool().execute(new Runnable() {
+ public void run() {
+ ((InputMethodManager) cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);
+ callbackContext.success(); // Thread-safe.
+ }
+ });
+ return true;
+ }
+ if ("init".equals(action)) {
+ cordova.getThreadPool().execute(new Runnable() {
+ public void run() {
+ //calculate density-independent pixels (dp)
+ //http://developer.android.com/guide/practices/screens_support.html
+ DisplayMetrics dm = new DisplayMetrics();
+ cordova.getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
+ final float density = dm.density;
+
+ //http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing
+ final View rootView = cordova.getActivity().getWindow().getDecorView().findViewById(android.R.id.content).getRootView();
+ OnGlobalLayoutListener list = new OnGlobalLayoutListener() {
+ int previousHeightDiff = 0;
+ @Override
+ public void onGlobalLayout() {
+ Rect r = new Rect();
+ //r will be populated with the coordinates of your view that area still visible.
+ rootView.getWindowVisibleDisplayFrame(r);
+
+ PluginResult result;
+
+ // cache properties for later use
+ int rootViewHeight = rootView.getRootView().getHeight();
+ int resultBottom = r.bottom;
+
+ // calculate screen height differently for android versions >= 21: Lollipop 5.x, Marshmallow 6.x
+ //http://stackoverflow.com/a/29257533/3642890 beware of nexus 5
+ int screenHeight;
+
+ if (Build.VERSION.SDK_INT >= 21) {
+ Display display = cordova.getActivity().getWindowManager().getDefaultDisplay();
+ Point size = new Point();
+ display.getSize(size);
+ screenHeight = size.y;
+ } else {
+ screenHeight = rootViewHeight;
+ }
+
+ int heightDiff = screenHeight - resultBottom;
+
+ int pixelHeightDiff = (int)(heightDiff / density);
+ if (pixelHeightDiff > 100 && pixelHeightDiff != previousHeightDiff) { // if more than 100 pixels, its probably a keyboard...
+ String msg = "S" + Integer.toString(pixelHeightDiff);
+ result = new PluginResult(PluginResult.Status.OK, msg);
+ result.setKeepCallback(true);
+ callbackContext.sendPluginResult(result);
+ }
+ else if ( pixelHeightDiff != previousHeightDiff && ( previousHeightDiff - pixelHeightDiff ) > 100 ){
+ String msg = "H";
+ result = new PluginResult(PluginResult.Status.OK, msg);
+ result.setKeepCallback(true);
+ callbackContext.sendPluginResult(result);
+ }
+ previousHeightDiff = pixelHeightDiff;
+ }
+ };
+
+ rootView.getViewTreeObserver().addOnGlobalLayoutListener(list);
+
+
+ PluginResult dataResult = new PluginResult(PluginResult.Status.OK);
+ dataResult.setKeepCallback(true);
+ callbackContext.sendPluginResult(dataResult);
+ }
+ });
+ return true;
+ }
+ return false; // Returning false results in a "MethodNotFound" error.
+ }
+
+
+}
+
+
diff --git a/StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java b/StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java
index 9d3f3d63..3a52d287 100755..100644
--- a/StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java
+++ b/StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java
@@ -4,6 +4,8 @@ import android.content.Intent;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaActivity;
import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CordovaInterface;
+import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
@@ -16,19 +18,52 @@ import java.util.Locale;
public class LaunchMyApp extends CordovaPlugin {
private static final String ACTION_CHECKINTENT = "checkIntent";
+ private static final String ACTION_CLEARINTENT = "clearIntent";
+ private static final String ACTION_GETLASTINTENT = "getLastIntent";
+
+ private String lastIntentString = null;
+
+ /**
+ * We don't want to interfere with other plugins requiring the intent data,
+ * but in case of a multi-page app your app may receive the same intent data
+ * multiple times, that's why you'll get an option to reset it (null it).
+ *
+ * Add this to config.xml to enable that behaviour (default false):
+ * <preference name="CustomURLSchemePluginClearsAndroidIntent" value="true"/>
+ */
+ private boolean resetIntent;
+
+ @Override
+ public void initialize(final CordovaInterface cordova, CordovaWebView webView){
+ this.resetIntent = preferences.getBoolean("resetIntent", false) ||
+ preferences.getBoolean("CustomURLSchemePluginClearsAndroidIntent", false);
+ }
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
- if (ACTION_CHECKINTENT.equalsIgnoreCase(action)) {
+ if (ACTION_CLEARINTENT.equalsIgnoreCase(action)) {
+ final Intent intent = ((CordovaActivity) this.webView.getContext()).getIntent();
+ if (resetIntent){
+ intent.setData(null);
+ }
+ return true;
+ } else if (ACTION_CHECKINTENT.equalsIgnoreCase(action)) {
final Intent intent = ((CordovaActivity) this.webView.getContext()).getIntent();
final String intentString = intent.getDataString();
- if (intentString != null && intentString.contains("://") && intent.getScheme() != null) {
+ if (intentString != null && intent.getScheme() != null) {
+ lastIntentString = intentString;
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, intent.getDataString()));
- intent.setData(null);
} else {
callbackContext.error("App was not started via the launchmyapp URL scheme. Ignoring this errorcallback is the best approach.");
}
return true;
+ } else if (ACTION_GETLASTINTENT.equalsIgnoreCase(action)) {
+ if(lastIntentString != null) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, lastIntentString));
+ } else {
+ callbackContext.error("No intent received so far.");
+ }
+ return true;
} else {
callbackContext.error("This plugin only responds to the " + ACTION_CHECKINTENT + " action.");
return false;
@@ -38,8 +73,10 @@ public class LaunchMyApp extends CordovaPlugin {
@Override
public void onNewIntent(Intent intent) {
final String intentString = intent.getDataString();
- if (intentString != null && intentString.contains("://") && intent.getScheme() != null) {
- intent.setData(null);
+ if (intentString != null && intent.getScheme() != null) {
+ if (resetIntent){
+ intent.setData(null);
+ }
try {
StringWriter writer = new StringWriter(intentString.length() * 2);
escapeJavaStyleString(writer, intentString, true, false);
@@ -133,4 +170,4 @@ public class LaunchMyApp extends CordovaPlugin {
private static String hex(char ch) {
return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH);
}
-} \ No newline at end of file
+}
diff --git a/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java b/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java
index f1168f89..8de31da8 100755..100644
--- a/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java
+++ b/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java
@@ -26,7 +26,9 @@ import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
@@ -36,6 +38,7 @@ public class SocialSharing extends CordovaPlugin {
private static final String ACTION_AVAILABLE_EVENT = "available";
private static final String ACTION_SHARE_EVENT = "share";
+ private static final String ACTION_SHARE_WITH_OPTIONS_EVENT = "shareWithOptions";
private static final String ACTION_CAN_SHARE_VIA = "canShareVia";
private static final String ACTION_CAN_SHARE_VIA_EMAIL = "canShareViaEmail";
private static final String ACTION_SHARE_VIA = "shareVia";
@@ -47,7 +50,10 @@ public class SocialSharing extends CordovaPlugin {
private static final String ACTION_SHARE_VIA_SMS_EVENT = "shareViaSMS";
private static final String ACTION_SHARE_VIA_EMAIL_EVENT = "shareViaEmail";
- private static final int ACTIVITY_CODE_SENDVIAEMAIL = 2;
+ private static final int ACTIVITY_CODE_SEND__BOOLRESULT = 1;
+ private static final int ACTIVITY_CODE_SEND__OBJECT = 2;
+ private static final int ACTIVITY_CODE_SENDVIAEMAIL = 3;
+ private static final int ACTIVITY_CODE_SENDVIAWHATSAPP = 4;
private CallbackContext _callbackContext;
@@ -55,6 +61,7 @@ public class SocialSharing extends CordovaPlugin {
private abstract class SocialSharingRunnable implements Runnable {
public CallbackContext callbackContext;
+
SocialSharingRunnable(CallbackContext cb) {
this.callbackContext = cb;
}
@@ -68,23 +75,29 @@ public class SocialSharing extends CordovaPlugin {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
return true;
} else if (ACTION_SHARE_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), null, false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), null, null, false, true);
+ } else if (ACTION_SHARE_WITH_OPTIONS_EVENT.equals(action)) {
+ return shareWithOptions(callbackContext, args.getJSONObject(0));
} else if (ACTION_SHARE_VIA_TWITTER_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "twitter", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "twitter", null, false, true);
} else if (ACTION_SHARE_VIA_FACEBOOK_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", null, false, true);
} else if (ACTION_SHARE_VIA_FACEBOOK_WITH_PASTEMESSAGEHINT.equals(action)) {
this.pasteMessage = args.getString(4);
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", null, false, true);
} else if (ACTION_SHARE_VIA_WHATSAPP_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "whatsapp", false);
+ if (notEmpty(args.getString(4))) {
+ return shareViaWhatsAppDirectly(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4));
+ } else {
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "whatsapp", null, false, true);
+ }
} else if (ACTION_SHARE_VIA_INSTAGRAM_EVENT.equals(action)) {
if (notEmpty(args.getString(0))) {
copyHintToClipboard(args.getString(0), "Instagram paste message");
}
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "instagram", false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "instagram", null, false, true);
} else if (ACTION_CAN_SHARE_VIA.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), true);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), null, true, true);
} else if (ACTION_CAN_SHARE_VIA_EMAIL.equals(action)) {
if (isEmailAvailable()) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
@@ -94,7 +107,7 @@ public class SocialSharing extends CordovaPlugin {
return false;
}
} else if (ACTION_SHARE_VIA.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), false);
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), null, false, true);
} else if (ACTION_SHARE_VIA_SMS_EVENT.equals(action)) {
return invokeSMSIntent(callbackContext, args.getJSONObject(0), args.getString(1));
} else if (ACTION_SHARE_VIA_EMAIL_EVENT.equals(action)) {
@@ -158,8 +171,17 @@ public class SocialSharing extends CordovaPlugin {
callbackContext.error(e.getMessage());
}
+ // this was added to start the intent in a new window as suggested in #300 to prevent crashes upon return
+ draft.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
draft.setType("application/octet-stream");
- cordova.startActivityForResult(plugin, Intent.createChooser(draft, "Choose Email App"), ACTIVITY_CODE_SENDVIAEMAIL);
+
+ // as an experiment for #300 we're explicitly running it on the ui thread here
+ cordova.getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ cordova.startActivityForResult(plugin, Intent.createChooser(draft, "Choose Email App"), ACTIVITY_CODE_SENDVIAEMAIL);
+ }
+ });
}
});
@@ -178,7 +200,30 @@ public class SocialSharing extends CordovaPlugin {
}
}
- private boolean doSendIntent(final CallbackContext callbackContext, final String msg, final String subject, final JSONArray files, final String url, final String appPackageName, final boolean peek) {
+ private boolean shareWithOptions(CallbackContext callbackContext, JSONObject jsonObject) {
+ return doSendIntent(
+ callbackContext,
+ jsonObject.optString("message", null),
+ jsonObject.optString("subject", null),
+ jsonObject.optJSONArray("files") == null ? new JSONArray() : jsonObject.optJSONArray("files"),
+ jsonObject.optString("url", null),
+ null,
+ jsonObject.optString("chooserTitle", null),
+ false,
+ false
+ );
+ }
+
+ private boolean doSendIntent(
+ final CallbackContext callbackContext,
+ final String msg,
+ final String subject,
+ final JSONArray files,
+ final String url,
+ final String appPackageName,
+ final String chooserTitle,
+ final boolean peek,
+ final boolean boolResult) {
final CordovaInterface mycordova = cordova;
final CordovaPlugin plugin = this;
@@ -222,6 +267,7 @@ public class SocialSharing extends CordovaPlugin {
if (notEmpty(subject)) {
sendIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
}
+
// add the URL to the message, as there seems to be no separate field
if (notEmpty(url)) {
if (notEmpty(message)) {
@@ -238,6 +284,9 @@ public class SocialSharing extends CordovaPlugin {
}
}
+ // this was added to start the intent in a new window as suggested in #300 to prevent crashes upon return
+ sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
if (appPackageName != null) {
String packageName = appPackageName;
String passedActivityName = null;
@@ -254,7 +303,13 @@ public class SocialSharing extends CordovaPlugin {
sendIntent.addCategory(Intent.CATEGORY_LAUNCHER);
sendIntent.setComponent(new ComponentName(activity.applicationInfo.packageName,
passedActivityName != null ? passedActivityName : activity.name));
- mycordova.startActivityForResult(plugin, sendIntent, 0);
+
+ // as an experiment for #300 we're explicitly running it on the ui thread here
+ cordova.getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ mycordova.startActivityForResult(plugin, sendIntent, 0);
+ }
+ });
if (pasteMessage != null) {
// add a little delay because target app (facebook only atm) needs to be started first
@@ -275,7 +330,13 @@ public class SocialSharing extends CordovaPlugin {
if (peek) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
} else {
- mycordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, null), 1);
+ // experimenting a bit
+ // as an experiment for #300 we're explicitly running it on the ui thread here
+ cordova.getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ mycordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, chooserTitle), boolResult ? ACTIVITY_CODE_SEND__BOOLRESULT : ACTIVITY_CODE_SEND__OBJECT);
+ }
+ });
}
}
}
@@ -306,7 +367,12 @@ public class SocialSharing extends CordovaPlugin {
private Uri getFileUriAndSetType(Intent sendIntent, String dir, String image, String subject, int nthFile) throws IOException {
// we're assuming an image, but this can be any filetype you like
String localImage = image;
- sendIntent.setType("image/*");
+ if (image.endsWith("mp4") || image.endsWith("mov") || image.endsWith("3gp")){
+ sendIntent.setType("video/*");
+ } else {
+ sendIntent.setType("image/*");
+ }
+
if (image.startsWith("http") || image.startsWith("www/")) {
String filename = getFileName(image);
localImage = "file://" + dir + "/" + filename;
@@ -319,6 +385,10 @@ public class SocialSharing extends CordovaPlugin {
Matcher matcher = dispositionPattern.matcher(disposition);
if (matcher.find()) {
filename = matcher.group(1).replaceAll("[^a-zA-Z0-9._-]", "");
+ if (filename.length() == 0) {
+ // in this case we can't determine a filetype so some targets (gmail) may not render it correctly
+ filename = "file";
+ }
localImage = "file://" + dir + "/" + filename;
}
}
@@ -365,10 +435,160 @@ public class SocialSharing extends CordovaPlugin {
localImage = "file://" + dir + "/" + fileName;
} else if (!image.startsWith("file://")) {
throw new IllegalArgumentException("URL_NOT_SUPPORTED");
+ } else {
+ //get file MIME type
+ String type = getMIMEType(image);
+ //set intent data and Type
+ sendIntent.setType(type);
}
return Uri.parse(localImage);
}
+ private String getMIMEType(String fileName) {
+ String type = "*/*";
+ int dotIndex = fileName.lastIndexOf(".");
+ if (dotIndex == -1) {
+ return type;
+ }
+ final String end = fileName.substring(dotIndex+1, fileName.length()).toLowerCase();
+ String fromMap = MIME_Map.get(end);
+ return fromMap == null ? type : fromMap;
+ }
+
+ private static final Map<String, String> MIME_Map = new HashMap<String, String>();
+ static {
+ MIME_Map.put("3gp", "video/3gpp");
+ MIME_Map.put("apk", "application/vnd.android.package-archive");
+ MIME_Map.put("asf", "video/x-ms-asf");
+ MIME_Map.put("avi", "video/x-msvideo");
+ MIME_Map.put("bin", "application/octet-stream");
+ MIME_Map.put("bmp", "image/bmp");
+ MIME_Map.put("c", "text/plain");
+ MIME_Map.put("class", "application/octet-stream");
+ MIME_Map.put("conf", "text/plain");
+ MIME_Map.put("cpp", "text/plain");
+ MIME_Map.put("doc", "application/msword");
+ MIME_Map.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
+ MIME_Map.put("xls", "application/vnd.ms-excel");
+ MIME_Map.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ MIME_Map.put("exe", "application/octet-stream");
+ MIME_Map.put("gif", "image/gif");
+ MIME_Map.put("gtar", "application/x-gtar");
+ MIME_Map.put("gz", "application/x-gzip");
+ MIME_Map.put("h", "text/plain");
+ MIME_Map.put("htm", "text/html");
+ MIME_Map.put("html", "text/html");
+ MIME_Map.put("jar", "application/java-archive");
+ MIME_Map.put("java", "text/plain");
+ MIME_Map.put("jpeg", "image/jpeg");
+ MIME_Map.put("jpg", "image/*");
+ MIME_Map.put("js", "application/x-javascript");
+ MIME_Map.put("log", "text/plain");
+ MIME_Map.put("m3u", "audio/x-mpegurl");
+ MIME_Map.put("m4a", "audio/mp4a-latm");
+ MIME_Map.put("m4b", "audio/mp4a-latm");
+ MIME_Map.put("m4p", "audio/mp4a-latm");
+ MIME_Map.put("m4u", "video/vnd.mpegurl");
+ MIME_Map.put("m4v", "video/x-m4v");
+ MIME_Map.put("mov", "video/quicktime");
+ MIME_Map.put("mp2", "audio/x-mpeg");
+ MIME_Map.put("mp3", "audio/x-mpeg");
+ MIME_Map.put("mp4", "video/mp4");
+ MIME_Map.put("mpc", "application/vnd.mpohun.certificate");
+ MIME_Map.put("mpe", "video/mpeg");
+ MIME_Map.put("mpeg", "video/mpeg");
+ MIME_Map.put("mpg", "video/mpeg");
+ MIME_Map.put("mpg4", "video/mp4");
+ MIME_Map.put("mpga", "audio/mpeg");
+ MIME_Map.put("msg", "application/vnd.ms-outlook");
+ MIME_Map.put("ogg", "audio/ogg");
+ MIME_Map.put("pdf", "application/pdf");
+ MIME_Map.put("png", "image/png");
+ MIME_Map.put("pps", "application/vnd.ms-powerpoint");
+ MIME_Map.put("ppt", "application/vnd.ms-powerpoint");
+ MIME_Map.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
+ MIME_Map.put("prop", "text/plain");
+ MIME_Map.put("rc", "text/plain");
+ MIME_Map.put("rmvb", "audio/x-pn-realaudio");
+ MIME_Map.put("rtf", "application/rtf");
+ MIME_Map.put("sh", "text/plain");
+ MIME_Map.put("tar", "application/x-tar");
+ MIME_Map.put("tgz", "application/x-compressed");
+ MIME_Map.put("txt", "text/plain");
+ MIME_Map.put("wav", "audio/x-wav");
+ MIME_Map.put("wma", "audio/x-ms-wma");
+ MIME_Map.put("wmv", "audio/x-ms-wmv");
+ MIME_Map.put("wps", "application/vnd.ms-works");
+ MIME_Map.put("xml", "text/plain");
+ MIME_Map.put("z", "application/x-compress");
+ MIME_Map.put("zip", "application/x-zip-compressed");
+ MIME_Map.put("", "*/*");
+ }
+
+ private boolean shareViaWhatsAppDirectly(final CallbackContext callbackContext, String message, final String subject, final JSONArray files, final String url, final String number) {
+ // add the URL to the message, as there seems to be no separate field
+ if (notEmpty(url)) {
+ if (notEmpty(message)) {
+ message += " " + url;
+ } else {
+ message = url;
+ }
+ }
+ final String shareMessage = message;
+ final SocialSharing plugin = this;
+ cordova.getThreadPool().execute(new SocialSharingRunnable(callbackContext) {
+ public void run() {
+ final Intent intent = new Intent(Intent.ACTION_SENDTO);
+ intent.setData(Uri.parse("smsto:" + number));
+
+ intent.putExtra("sms_body", shareMessage);
+ intent.putExtra("sms_subject", subject);
+ intent.setPackage("com.whatsapp");
+
+ try {
+ if (files.length() > 0 && !"".equals(files.getString(0))) {
+ final boolean hasMultipleAttachments = files.length() > 1;
+ final String dir = getDownloadDir();
+ if (dir != null) {
+ ArrayList<Uri> fileUris = new ArrayList<Uri>();
+ Uri fileUri = null;
+ for (int i = 0; i < files.length(); i++) {
+ fileUri = getFileUriAndSetType(intent, dir, files.getString(i), subject, i);
+ if (fileUri != null) {
+ fileUris.add(fileUri);
+ }
+ }
+ if (!fileUris.isEmpty()) {
+ if (hasMultipleAttachments) {
+ intent.putExtra(Intent.EXTRA_STREAM, fileUris);
+ } else {
+ intent.putExtra(Intent.EXTRA_STREAM, fileUri);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ callbackContext.error(e.getMessage());
+ }
+ try {
+ // this was added to start the intent in a new window as suggested in #300 to prevent crashes upon return
+ // update: didn't help (doesn't seem to hurt either though)
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // as an experiment for #300 we're explicitly running it on the ui thread here
+ cordova.getActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ cordova.startActivityForResult(plugin, intent, ACTIVITY_CODE_SENDVIAWHATSAPP);
+ }
+ });
+ } catch (Exception e) {
+ callbackContext.error(e.getMessage());
+ }
+ }
+ });
+ return true;
+ }
+
private boolean invokeSMSIntent(final CallbackContext callbackContext, JSONObject options, String p_phonenumbers) {
final String message = options.optString("message");
// TODO test this on a real SMS enabled device before releasing it
@@ -404,6 +624,9 @@ public class SocialSharing extends CordovaPlugin {
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
}
}
+ // this was added to start the intent in a new window as suggested in #300 to prevent crashes upon return
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
cordova.startActivityForResult(plugin, intent, 0);
} catch (Exception e) {
callbackContext.error(e.getMessage());
@@ -451,10 +674,26 @@ public class SocialSharing extends CordovaPlugin {
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (_callbackContext != null) {
- if (ACTIVITY_CODE_SENDVIAEMAIL == requestCode) {
- _callbackContext.success();
- } else {
- _callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, resultCode == Activity.RESULT_OK));
+ switch (requestCode) {
+ case ACTIVITY_CODE_SEND__BOOLRESULT:
+ _callbackContext.sendPluginResult(new PluginResult(
+ PluginResult.Status.OK,
+ resultCode == Activity.RESULT_OK));
+ break;
+ case ACTIVITY_CODE_SEND__OBJECT:
+ JSONObject json = new JSONObject();
+ try {
+ json.put("completed", resultCode == Activity.RESULT_OK);
+ json.put("app", ""); // we need a completely different approach if we want to support this on Android. Idea: https://clickclickclack.wordpress.com/2012/01/03/intercepting-androids-action_send-intents/
+ _callbackContext.sendPluginResult(new PluginResult(
+ PluginResult.Status.OK,
+ json));
+ } catch (JSONException e) {
+ _callbackContext.error(e.getMessage());
+ }
+ break;
+ default:
+ _callbackContext.success();
}
}
}
@@ -471,13 +710,16 @@ public class SocialSharing extends CordovaPlugin {
}
private static String getFileName(String url) {
+ if (url.endsWith("/")) {
+ url = url.substring(0, url.length()-1);
+ }
final String pattern = ".*/([^?#]+)?";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(url);
if (m.find()) {
return m.group(1);
} else {
- return null;
+ return "file";
}
}
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)) {