From 597fa051833ca3df6eb185c0143ff82e02dacba1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 26 Sep 2017 01:35:13 +0200 Subject: push plugin ugh --- .../push/BackgroundActionButtonHandler.java | 4 +- .../com/adobe/phonegap/push/FCMService.java | 891 +++++++++++++++++++++ .../com/adobe/phonegap/push/GCMIntentService.java | 802 ------------------- .../com/adobe/phonegap/push/PermissionUtils.java | 4 + .../com/adobe/phonegap/push/PushConstants.java | 16 +- .../adobe/phonegap/push/PushDismissedHandler.java | 25 + .../adobe/phonegap/push/PushHandlerActivity.java | 32 +- .../push/PushInstanceIDListenerService.java | 19 +- .../com/adobe/phonegap/push/PushPlugin.java | 132 +-- .../phonegap/push/RegistrationIntentService.java | 38 - 10 files changed, 1034 insertions(+), 929 deletions(-) create mode 100644 StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/FCMService.java delete mode 100644 StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/GCMIntentService.java create mode 100644 StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushDismissedHandler.java delete mode 100644 StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/RegistrationIntentService.java (limited to 'StoneIsland/plugins/phonegap-plugin-push/src/android/com') diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.java index 3ccea6cb..4456f525 100644 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.java +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.java @@ -9,7 +9,7 @@ import android.util.Log; import android.support.v4.app.RemoteInput; public class BackgroundActionButtonHandler extends BroadcastReceiver implements PushConstants { - private static String LOG_TAG = "PushPlugin_BackgroundActionButtonHandler"; + private static String LOG_TAG = "Push_BGActionButton"; @Override public void onReceive(Context context, Intent intent) { @@ -19,7 +19,7 @@ public class BackgroundActionButtonHandler extends BroadcastReceiver implements int notId = intent.getIntExtra(NOT_ID, 0); Log.d(LOG_TAG, "not id = " + notId); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancel(GCMIntentService.getAppName(context), notId); + notificationManager.cancel(FCMService.getAppName(context), notId); if (extras != null) { Bundle originalExtras = extras.getBundle(PUSH_BUNDLE); diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/FCMService.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/FCMService.java new file mode 100644 index 00000000..af328fb2 --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/FCMService.java @@ -0,0 +1,891 @@ +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.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Paint; +import android.graphics.Canvas; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationCompat.WearableExtender; +import android.support.v4.app.RemoteInput; +import android.text.Html; +import android.text.Spanned; +import android.util.Log; + +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; + +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.Map; +import java.util.Random; + +@SuppressLint("NewApi") +public class FCMService extends FirebaseMessagingService implements PushConstants { + + private static final String LOG_TAG = "Push_FCMService"; + private static HashMap> messageMap = new HashMap>(); + + public void setNotification(int notId, String message){ + ArrayList messageList = messageMap.get(notId); + if(messageList == null) { + messageList = new ArrayList(); + messageMap.put(notId, messageList); + } + + if(message.isEmpty()){ + messageList.clear(); + }else{ + messageList.add(message); + } + } + + @Override + public void onMessageReceived(RemoteMessage message){ + + String from = message.getFrom(); + Log.d(LOG_TAG, "onMessage - from: " + from); + + Bundle extras = new Bundle(); + + if (message.getNotification()!=null) { + extras.putString(TITLE,message.getNotification().getTitle()); + extras.putString(MESSAGE,message.getNotification().getBody()); + } + for (Map.Entry entry : message.getData().entrySet()) { + extras.putString(entry.getKey(), entry.getValue()); + } + + if (extras != null && isAvailableSender(from)) { + Context applicationContext = getApplicationContext(); + + SharedPreferences prefs = applicationContext.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); + boolean forceShow = prefs.getBoolean(FORCE_SHOW, false); + boolean clearBadge = prefs.getBoolean(CLEAR_BADGE, false); + String messageKey = prefs.getString(MESSAGE_KEY, MESSAGE); + String titleKey = prefs.getString(TITLE_KEY, TITLE); + + extras = normalizeExtras(applicationContext, extras, messageKey, titleKey); + + if (clearBadge) { + PushPlugin.setApplicationIconBadgeNumber(getApplicationContext(), 0); + } + + // 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); + extras.putBoolean(COLDSTART, false); + 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); + extras.putBoolean(COLDSTART, false); + + showNotificationIfPossible(applicationContext, 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); + extras.putBoolean(COLDSTART, PushPlugin.isActive()); + + showNotificationIfPossible(applicationContext, extras); + } + } + } + + /* + * Change a values key in the extras bundle + */ + private void replaceKey(Context context, String oldKey, String newKey, Bundle extras, Bundle newExtras) { + Object value = extras.get(oldKey); + if ( value != null ) { + if (value instanceof String) { + value = localizeKey(context, newKey, (String) value); + + 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)); + } + } + } + + /* + * Normalize localization for key + */ + private String localizeKey(Context context, String key, String value) { + if (key.equals(TITLE) || key.equals(MESSAGE) || key.equals(SUMMARY_TEXT)) { + try { + JSONObject localeObject = new JSONObject(value); + + String localeKey = localeObject.getString(LOC_KEY); + + ArrayList localeFormatData = new ArrayList(); + if (!localeObject.isNull(LOC_DATA)) { + String localeData = localeObject.getString(LOC_DATA); + JSONArray localeDataArray = new JSONArray(localeData); + for (int i = 0 ; i < localeDataArray.length(); i++) { + localeFormatData.add(localeDataArray.getString(i)); + } + } + + String packageName = context.getPackageName(); + Resources resources = context.getResources(); + + int resourceId = resources.getIdentifier(localeKey, "string", packageName); + + if (resourceId != 0) { + return resources.getString(resourceId, localeFormatData.toArray()); + } + else { + Log.d(LOG_TAG, "can't find resource for locale key = " + localeKey); + + return value; + } + } + catch(JSONException e) { + Log.d(LOG_TAG, "no locale found for key = " + key + ", error " + e.getMessage()); + + return value; + } + } + + return value; + } + + /* + * Replace alternate keys with our canonical value + */ + private String normalizeKey(String key, String messageKey, String titleKey) { + if (key.equals(BODY) || key.equals(ALERT) || key.equals(MP_MESSAGE) || key.equals(GCM_NOTIFICATION_BODY) || key.equals(TWILIO_BODY) || key.equals(messageKey)) { + return MESSAGE; + } else if (key.equals(TWILIO_TITLE) || key.equals(SUBJECT) || key.equals(titleKey)) { + return TITLE; + }else if (key.equals(MSGCNT) || key.equals(BADGE)) { + return COUNT; + } else if (key.equals(SOUNDNAME) || key.equals(TWILIO_SOUND)) { + 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(Context context, Bundle extras, String messageKey, String titleKey) { + Log.d(LOG_TAG, "normalize extras"); + Iterator 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) || key.equals(messageKey)) { + 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) || + data.has(messageKey) || data.has(titleKey) ) { + Iterator 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, messageKey, titleKey); + value = localizeKey(context, jsonKey, value); + + newExtras.putString(jsonKey, value); + } + } + } catch( JSONException e) { + Log.e(LOG_TAG, "normalizeExtras: JSON exception"); + } + } else { + String newKey = normalizeKey(key, messageKey, titleKey); + Log.d(LOG_TAG, "replace key " + key + " with " + newKey); + replaceKey(context, key, newKey, extras, newExtras); + } + } else if (key.equals(("notification"))) { + Bundle value = extras.getBundle(key); + Iterator iterator = value.keySet().iterator(); + while (iterator.hasNext()) { + String notifkey = iterator.next(); + + Log.d(LOG_TAG, "notifkey = " + notifkey); + String newKey = normalizeKey(notifkey, messageKey, titleKey); + Log.d(LOG_TAG, "replace key " + notifkey + " with " + newKey); + + String valueData = value.getString(notifkey); + valueData = localizeKey(context, newKey, valueData); + + newExtras.putString(newKey, valueData); + } + continue; + // In case we weren't working on the payload data node or the notification node, + // normalize the key. + // This allows to have "message" as the payload data key without colliding + // with the other "message" key (holding the body of the payload) + // See issue #1663 + } else { + String newKey = normalizeKey(key, messageKey, titleKey); + Log.d(LOG_TAG, "replace key " + key + " with " + newKey); + replaceKey(context, key, newKey, extras, newExtras); + } + + } // while + + return newExtras; + } + + private int extractBadgeCount(Bundle extras) { + int count = -1; + String msgcnt = extras.getString(COUNT); + + try { + if (msgcnt != null) { + count = Integer.parseInt(msgcnt); + } + } catch (NumberFormatException e) { + Log.e(LOG_TAG, e.getLocalizedMessage(), e); + } + + return count; + } + + 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); + String contentAvailable = extras.getString(CONTENT_AVAILABLE); + String forceStart = extras.getString(FORCE_START); + int badgeCount = extractBadgeCount(extras); + if (badgeCount >= 0) { + Log.d(LOG_TAG, "count =[" + badgeCount + "]"); + PushPlugin.setApplicationIconBadgeNumber(context, badgeCount); + } + + Log.d(LOG_TAG, "message =[" + message + "]"); + Log.d(LOG_TAG, "title =[" + title + "]"); + Log.d(LOG_TAG, "contentAvailable =[" + contentAvailable + "]"); + Log.d(LOG_TAG, "forceStart =[" + forceStart + "]"); + + if ((message != null && message.length() != 0) || + (title != null && title.length() != 0)) { + + Log.d(LOG_TAG, "create notification"); + + if(title == null || title.isEmpty()){ + extras.putString(TITLE, getAppName(this)); + } + + createNotification(context, extras); + } + + if(!PushPlugin.isActive() && "1".equals(forceStart)){ + Log.d(LOG_TAG, "app is not running but we should start it and put in background"); + Intent intent = new Intent(this, PushHandlerActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(PUSH_BUNDLE, extras); + intent.putExtra(START_IN_BACKGROUND, true); + intent.putExtra(FOREGROUND, false); + startActivity(intent); + } else if ("1".equals(contentAvailable)) { + Log.d(LOG_TAG, "app is not running and content available true"); + 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); + + Intent dismissedNotificationIntent = new Intent(this, PushDismissedHandler.class); + dismissedNotificationIntent.putExtra(PUSH_BUNDLE, extras); + dismissedNotificationIntent.putExtra(NOT_ID, notId); + dismissedNotificationIntent.putExtra(DISMISSED, true); + dismissedNotificationIntent.setAction(PUSH_DISMISSED); + + requestCode = new Random().nextInt(); + PendingIntent deleteIntent = PendingIntent.getBroadcast(this, requestCode, dismissedNotificationIntent, PendingIntent.FLAG_CANCEL_CURRENT); + + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(context) + .setWhen(System.currentTimeMillis()) + .setContentTitle(fromHtml(extras.getString(TITLE))) + .setTicker(fromHtml(extras.getString(TITLE))) + .setContentIntent(contentIntent) + .setDeleteIntent(deleteIntent) + .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(context, extras, mBuilder); + + /* + * Notification count + */ + setVisibility(context, extras, mBuilder); + + /* + * Notification add actions + */ + createActions(extras, mBuilder, resources, packageName, notId); + + mNotificationManager.notify(appName, notId, mBuilder.build()); + } + + private void updateIntent(Intent intent, String callback, Bundle extras, boolean foreground, int notId) { + intent.putExtra(CALLBACK, callback); + intent.putExtra(PUSH_BUNDLE, extras); + intent.putExtra(FOREGROUND, foreground); + intent.putExtra(NOT_ID, notId); + } + + private void createActions(Bundle extras, NotificationCompat.Builder mBuilder, Resources resources, String packageName, int notId) { + Log.d(LOG_TAG, "create actions: with in-line"); + String actions = extras.getString(ACTIONS); + if (actions != null) { + try { + JSONArray actionsArray = new JSONArray(actions); + ArrayList wActions = new ArrayList(); + for (int i=0; i < actionsArray.length(); i++) { + int min = 1; + int max = 2000000000; + Random random = new Random(); + int uniquePendingIntentRequestCode = random.nextInt((max - min) + 1) + min; + Log.d(LOG_TAG, "adding action"); + JSONObject action = actionsArray.getJSONObject(i); + Log.d(LOG_TAG, "adding callback = " + action.getString(CALLBACK)); + boolean foreground = action.optBoolean(FOREGROUND, true); + boolean inline = action.optBoolean("inline", false); + Intent intent = null; + PendingIntent pIntent = null; + if (inline) { + Log.d(LOG_TAG, "Version: " + android.os.Build.VERSION.SDK_INT + " = " + android.os.Build.VERSION_CODES.M); + if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { + Log.d(LOG_TAG, "push activity"); + intent = new Intent(this, PushHandlerActivity.class); + } else { + Log.d(LOG_TAG, "push receiver"); + intent = new Intent(this, BackgroundActionButtonHandler.class); + } + + updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); + + if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { + Log.d(LOG_TAG, "push activity for notId " + notId); + pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); + } else { + Log.d(LOG_TAG, "push receiver for notId " + notId); + pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); + } + } else if (foreground) { + intent = new Intent(this, PushHandlerActivity.class); + updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); + pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); + } else { + intent = new Intent(this, BackgroundActionButtonHandler.class); + updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); + pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); + } + + NotificationCompat.Action.Builder actionBuilder = + new NotificationCompat.Action.Builder(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), + action.getString(TITLE), pIntent); + + RemoteInput remoteInput = null; + if (inline) { + Log.d(LOG_TAG, "create remote input"); + String replyLabel = "Enter your reply here"; + remoteInput = + new RemoteInput.Builder(INLINE_REPLY) + .setLabel(replyLabel) + .build(); + actionBuilder.addRemoteInput(remoteInput); + } + + NotificationCompat.Action wAction = actionBuilder.build(); + wActions.add(actionBuilder.build()); + + if (inline) { + mBuilder.addAction(wAction); + } else { + mBuilder.addAction(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), + action.getString(TITLE), pIntent); + } + wAction = null; + pIntent = null; + } + mBuilder.extend(new WearableExtender().addActions(wActions)); + wActions.clear(); + } catch(JSONException e) { + // nope + } + } + } + + private void setNotificationCount(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { + int count = extractBadgeCount(extras); + if (count >= 0) { + Log.d(LOG_TAG, "count =[" + count + "]"); + mBuilder.setNumber(count); + } + } + + + private void setVisibility(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { + String visibilityStr = extras.getString(VISIBILITY); + if (visibilityStr != null) { + try { + Integer visibility = Integer.parseInt(visibilityStr); + if (visibility >= NotificationCompat.VISIBILITY_SECRET && visibility <= NotificationCompat.VISIBILITY_PUBLIC) { + mBuilder.setVisibility(visibility); + } else { + Log.e(LOG_TAG, "Visibility parameter must be between -1 and 1"); + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + } + + 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].trim()); + } 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(fromHtml(message)); + + ArrayList 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(fromHtml(extras.getString(TITLE))) + .setSummaryText(fromHtml(stacking)); + + for (int i = messageList.size() - 1; i >= 0; i--) { + notificationInbox.addLine(fromHtml(messageList.get(i))); + } + + mBuilder.setStyle(notificationInbox); + } else { + NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); + if (message != null) { + bigText.bigText(fromHtml(message)); + bigText.setBigContentTitle(fromHtml(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(fromHtml(extras.getString(TITLE))); + bigPicture.setSummaryText(fromHtml(extras.getString(SUMMARY_TEXT))); + + mBuilder.setContentTitle(fromHtml(extras.getString(TITLE))); + mBuilder.setContentText(fromHtml(message)); + + mBuilder.setStyle(bigPicture); + } else { + setNotification(notId, ""); + + NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); + + if (message != null) { + mBuilder.setContentText(fromHtml(message)); + + bigText.bigText(fromHtml(message)); + bigText.setBigContentTitle(fromHtml(extras.getString(TITLE))); + + String summaryText = extras.getString(SUMMARY_TEXT); + if (summaryText != null) { + bigText.setSummaryText(fromHtml(summaryText)); + } + + mBuilder.setStyle(bigText); + } + /* + else { + mBuilder.setContentText(""); + } + */ + } + } + + private void setNotificationSound(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { + String soundname = extras.getString(SOUNDNAME); + if (soundname == null) { + soundname = extras.getString(SOUND); + } + if (SOUND_RINGTONE.equals(soundname)) { + mBuilder.setSound(android.provider.Settings.System.DEFAULT_RINGTONE_URI); + } else 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].trim()); + } 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 Bitmap getCircleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return null; + } + + final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(output); + final int color = Color.RED; + final Paint paint = new Paint(); + final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); + final RectF rectF = new RectF(rect); + + paint.setAntiAlias(true); + canvas.drawARGB(0, 0, 0, 0); + paint.setColor(color); + float cx = bitmap.getWidth()/2; + float cy = bitmap.getHeight()/2; + float radius = cx < cy ? cx : cy; + canvas.drawCircle(cx,cy,radius,paint); + + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(bitmap, rect, rect, paint); + + bitmap.recycle(); + + return output; + } + + private void setNotificationLargeIcon(Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder) { + String gcmLargeIcon = extras.getString(IMAGE); // from gcm + String imageType = extras.getString(IMAGE_TYPE, IMAGE_TYPE_SQUARE); + if (gcmLargeIcon != null && !"".equals(gcmLargeIcon)) { + if (gcmLargeIcon.startsWith("http://") || gcmLargeIcon.startsWith("https://")) { + Bitmap bitmap = getBitmapFromURL(gcmLargeIcon); + if (IMAGE_TYPE_SQUARE.equalsIgnoreCase(imageType)) { + mBuilder.setLargeIcon(bitmap); + } else { + Bitmap bm = getCircleBitmap(bitmap); + mBuilder.setLargeIcon(bm); + } + 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); + if (IMAGE_TYPE_SQUARE.equalsIgnoreCase(imageType)) { + mBuilder.setLargeIcon(bitmap); + } else { + Bitmap bm = getCircleBitmap(bitmap); + mBuilder.setLargeIcon(bm); + } + 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 && !"".equals(icon)) { + iconId = resources.getIdentifier(icon, DRAWABLE, packageName); + Log.d(LOG_TAG, "using icon from plugin options"); + } + else if (localIcon != null && !"".equals(localIcon)) { + 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 && !"".equals(color)) { + try { + iconColor = Color.parseColor(color); + } catch (IllegalArgumentException e) { + Log.e(LOG_TAG, "couldn't parse color from android options"); + } + } + else if (localIconColor != null && !"".equals(localIconColor)) { + 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.setConnectTimeout(15000); + connection.setDoInput(true); + connection.connect(); + InputStream input = connection.getInputStream(); + return BitmapFactory.decodeStream(input); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public 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; + } + + private Spanned fromHtml(String source) { + if (source != null) + return Html.fromHtml(source); + else + return null; + } + + private boolean isAvailableSender(String from) { + SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); + String savedSenderID = sharedPref.getString(SENDER_ID, ""); + + return from.equals(savedSenderID) || from.startsWith("/topics/"); + } +} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/GCMIntentService.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/GCMIntentService.java deleted file mode 100644 index e1a2b75c..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/GCMIntentService.java +++ /dev/null @@ -1,802 +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.support.v4.app.NotificationManagerCompat; -import android.support.v4.app.NotificationCompat.WearableExtender; -import android.support.v4.app.RemoteInput; -import android.text.Html; -import android.text.Spanned; -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> messageMap = new HashMap>(); - - public void setNotification(int notId, String message){ - ArrayList messageList = messageMap.get(notId); - if(messageList == null) { - messageList = new ArrayList(); - 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) { - Context applicationContext = getApplicationContext(); - - SharedPreferences prefs = applicationContext.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - boolean forceShow = prefs.getBoolean(FORCE_SHOW, false); - boolean clearBadge = prefs.getBoolean(CLEAR_BADGE, false); - - extras = normalizeExtras(applicationContext, extras); - - if (clearBadge) { - PushPlugin.setApplicationIconBadgeNumber(getApplicationContext(), 0); - } - - // 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); - extras.putBoolean(COLDSTART, false); - 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); - extras.putBoolean(COLDSTART, false); - - showNotificationIfPossible(applicationContext, 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); - extras.putBoolean(COLDSTART, PushPlugin.isActive()); - - showNotificationIfPossible(applicationContext, extras); - } - } - } - - /* - * Change a values key in the extras bundle - */ - private void replaceKey(Context context, String oldKey, String newKey, Bundle extras, Bundle newExtras) { - Object value = extras.get(oldKey); - if ( value != null ) { - if (value instanceof String) { - value = localizeKey(context, newKey, (String) value); - - 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)); - } - } - } - - /* - * Normalize localization for key - */ - private String localizeKey(Context context, String key, String value) { - if (key.equals(TITLE) || key.equals(MESSAGE) || key.equals(SUMMARY_TEXT)) { - try { - JSONObject localeObject = new JSONObject(value); - - String localeKey = localeObject.getString(LOC_KEY); - - ArrayList localeFormatData = new ArrayList(); - if (!localeObject.isNull(LOC_DATA)) { - String localeData = localeObject.getString(LOC_DATA); - JSONArray localeDataArray = new JSONArray(localeData); - for (int i = 0 ; i < localeDataArray.length(); i++) { - localeFormatData.add(localeDataArray.getString(i)); - } - } - - String packageName = context.getPackageName(); - Resources resources = context.getResources(); - - int resourceId = resources.getIdentifier(localeKey, "string", packageName); - - if (resourceId != 0) { - return resources.getString(resourceId, localeFormatData.toArray()); - } - else { - Log.d(LOG_TAG, "can't find resource for locale key = " + localeKey); - - return value; - } - } - catch(JSONException e) { - Log.d(LOG_TAG, "no locale found for key = " + key + ", error " + e.getMessage()); - - return value; - } - } - - return 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) || key.equals(TWILIO_BODY)) { - return MESSAGE; - } else if (key.equals(TWILIO_TITLE)) { - return TITLE; - }else if (key.equals(MSGCNT) || key.equals(BADGE)) { - return COUNT; - } else if (key.equals(SOUNDNAME) || key.equals(TWILIO_SOUND)) { - 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(Context context, Bundle extras) { - Log.d(LOG_TAG, "normalize extras"); - Iterator 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 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); - value = localizeKey(context, jsonKey, value); - - 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 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); - - String valueData = value.getString(notifkey); - valueData = localizeKey(context, newKey, valueData); - - newExtras.putString(newKey, valueData); - } - continue; - } - - String newKey = normalizeKey(key); - Log.d(LOG_TAG, "replace key " + key + " with " + newKey); - replaceKey(context, key, newKey, extras, newExtras); - - } // while - - return newExtras; - } - - private int extractBadgeCount(Bundle extras) { - int count = -1; - String msgcnt = extras.getString(COUNT); - - try { - if (msgcnt != null) { - count = Integer.parseInt(msgcnt); - } - } catch (NumberFormatException e) { - Log.e(LOG_TAG, e.getLocalizedMessage(), e); - } - - return count; - } - - 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); - String contentAvailable = extras.getString(CONTENT_AVAILABLE); - String forceStart = extras.getString(FORCE_START); - int badgeCount = extractBadgeCount(extras); - if (badgeCount >= 0) { - Log.d(LOG_TAG, "count =[" + badgeCount + "]"); - PushPlugin.setApplicationIconBadgeNumber(context, badgeCount); - } - - Log.d(LOG_TAG, "message =[" + message + "]"); - Log.d(LOG_TAG, "title =[" + title + "]"); - Log.d(LOG_TAG, "contentAvailable =[" + contentAvailable + "]"); - Log.d(LOG_TAG, "forceStart =[" + forceStart + "]"); - - if ((message != null && message.length() != 0) || - (title != null && title.length() != 0)) { - - Log.d(LOG_TAG, "create notification"); - - if(title == null || title.isEmpty()){ - extras.putString(TITLE, getAppName(this)); - } - - createNotification(context, extras); - } - - if(!PushPlugin.isActive() && "1".equals(forceStart)){ - Log.d(LOG_TAG, "app is not running but we should start it and put in background"); - Intent intent = new Intent(this, PushHandlerActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(PUSH_BUNDLE, extras); - intent.putExtra(START_IN_BACKGROUND, true); - intent.putExtra(FOREGROUND, false); - startActivity(intent); - } else if ("1".equals(contentAvailable)) { - Log.d(LOG_TAG, "app is not running and content available true"); - 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(fromHtml(extras.getString(TITLE))) - .setTicker(fromHtml(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(context, extras, mBuilder); - - /* - * Notification count - */ - setVisibility(context, extras, mBuilder); - - /* - * Notification add actions - */ - createActions(extras, mBuilder, resources, packageName, notId); - - mNotificationManager.notify(appName, notId, mBuilder.build()); - } - - private void updateIntent(Intent intent, String callback, Bundle extras, boolean foreground, int notId) { - intent.putExtra(CALLBACK, callback); - intent.putExtra(PUSH_BUNDLE, extras); - intent.putExtra(FOREGROUND, foreground); - intent.putExtra(NOT_ID, notId); - } - - private void createActions(Bundle extras, NotificationCompat.Builder mBuilder, Resources resources, String packageName, int notId) { - Log.d(LOG_TAG, "create actions: with in-line"); - String actions = extras.getString(ACTIONS); - if (actions != null) { - try { - JSONArray actionsArray = new JSONArray(actions); - ArrayList wActions = new ArrayList(); - for (int i=0; i < actionsArray.length(); i++) { - int min = 1; - int max = 2000000000; - Random random = new Random(); - int uniquePendingIntentRequestCode = random.nextInt((max - min) + 1) + min; - Log.d(LOG_TAG, "adding action"); - JSONObject action = actionsArray.getJSONObject(i); - Log.d(LOG_TAG, "adding callback = " + action.getString(CALLBACK)); - boolean foreground = action.optBoolean(FOREGROUND, true); - boolean inline = action.optBoolean("inline", false); - Intent intent = null; - PendingIntent pIntent = null; - if (inline) { - Log.d(LOG_TAG, "Version: " + android.os.Build.VERSION.SDK_INT + " = " + android.os.Build.VERSION_CODES.M); - if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { - Log.d(LOG_TAG, "push activity"); - intent = new Intent(this, PushHandlerActivity.class); - } else { - Log.d(LOG_TAG, "push receiver"); - intent = new Intent(this, BackgroundActionButtonHandler.class); - } - - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - - if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { - Log.d(LOG_TAG, "push activity for notId " + notId); - pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); - } else { - Log.d(LOG_TAG, "push receiver for notId " + notId); - pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); - } - } else if (foreground) { - intent = new Intent(this, PushHandlerActivity.class); - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } else { - intent = new Intent(this, BackgroundActionButtonHandler.class); - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } - - NotificationCompat.Action.Builder actionBuilder = - new NotificationCompat.Action.Builder(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), - action.getString(TITLE), pIntent); - - RemoteInput remoteInput = null; - if (inline) { - Log.d(LOG_TAG, "create remote input"); - String replyLabel = "Enter your reply here"; - remoteInput = - new RemoteInput.Builder(INLINE_REPLY) - .setLabel(replyLabel) - .build(); - actionBuilder.addRemoteInput(remoteInput); - } - - NotificationCompat.Action wAction = actionBuilder.build(); - wActions.add(actionBuilder.build()); - - if (inline) { - mBuilder.addAction(wAction); - } else { - mBuilder.addAction(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), - action.getString(TITLE), pIntent); - } - wAction = null; - pIntent = null; - } - mBuilder.extend(new WearableExtender().addActions(wActions)); - wActions.clear(); - } catch(JSONException e) { - // nope - } - } - } - - private void setNotificationCount(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - int count = extractBadgeCount(extras); - if (count >= 0) { - Log.d(LOG_TAG, "count =[" + count + "]"); - mBuilder.setNumber(count); - } - } - - - private void setVisibility(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - String visibilityStr = extras.getString(VISIBILITY); - if (visibilityStr != null) { - try { - Integer visibility = Integer.parseInt(visibilityStr); - if (visibility >= NotificationCompat.VISIBILITY_SECRET && visibility <= NotificationCompat.VISIBILITY_PUBLIC) { - mBuilder.setVisibility(visibility); - } else { - Log.e(LOG_TAG, "Visibility parameter must be between -1 and 1"); - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } - } - } - - 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].trim()); - } 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(fromHtml(message)); - - ArrayList 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(fromHtml(extras.getString(TITLE))) - .setSummaryText(fromHtml(stacking)); - - for (int i = messageList.size() - 1; i >= 0; i--) { - notificationInbox.addLine(fromHtml(messageList.get(i))); - } - - mBuilder.setStyle(notificationInbox); - } else { - NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); - if (message != null) { - bigText.bigText(fromHtml(message)); - bigText.setBigContentTitle(fromHtml(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(fromHtml(extras.getString(TITLE))); - bigPicture.setSummaryText(fromHtml(extras.getString(SUMMARY_TEXT))); - - mBuilder.setContentTitle(fromHtml(extras.getString(TITLE))); - mBuilder.setContentText(fromHtml(message)); - - mBuilder.setStyle(bigPicture); - } else { - setNotification(notId, ""); - - NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); - - if (message != null) { - mBuilder.setContentText(fromHtml(message)); - - bigText.bigText(fromHtml(message)); - bigText.setBigContentTitle(fromHtml(extras.getString(TITLE))); - - String summaryText = extras.getString(SUMMARY_TEXT); - if (summaryText != null) { - bigText.setSummaryText(fromHtml(summaryText)); - } - - mBuilder.setStyle(bigText); - } - /* - else { - mBuilder.setContentText(""); - } - */ - } - } - - private void setNotificationSound(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - String soundname = extras.getString(SOUNDNAME); - if (soundname == null) { - soundname = extras.getString(SOUND); - } - if (SOUND_RINGTONE.equals(soundname)) { - mBuilder.setSound(android.provider.Settings.System.DEFAULT_RINGTONE_URI); - } else 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].trim()); - } 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 && !"".equals(gcmLargeIcon)) { - 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 && !"".equals(icon)) { - iconId = resources.getIdentifier(icon, DRAWABLE, packageName); - Log.d(LOG_TAG, "using icon from plugin options"); - } - else if (localIcon != null && !"".equals(localIcon)) { - 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 && !"".equals(color)) { - try { - iconColor = Color.parseColor(color); - } catch (IllegalArgumentException e) { - Log.e(LOG_TAG, "couldn't parse color from android options"); - } - } - else if (localIconColor != null && !"".equals(localIconColor)) { - 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; - } - } - - public 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; - } - - private Spanned fromHtml(String source) { - if (source != null) - return Html.fromHtml(source); - else - return null; - } -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PermissionUtils.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PermissionUtils.java index 6aa5c9bf..41bc6a6f 100644 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PermissionUtils.java +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PermissionUtils.java @@ -10,8 +10,12 @@ import java.lang.reflect.Method; public class PermissionUtils { private static final String CHECK_OP_NO_THROW = "checkOpNoThrow"; + private static final int MIN_API_LEVEL = 19; // required by AppOpsManager public static boolean hasPermission(Context appContext, String appOpsServiceId) throws UnknownError { + if (android.os.Build.VERSION.SDK_INT < MIN_API_LEVEL) { + return true; + } ApplicationInfo appInfo = appContext.getApplicationInfo(); diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushConstants.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushConstants.java index 37874e04..e3aa217c 100644 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushConstants.java +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushConstants.java @@ -3,6 +3,7 @@ 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 REGISTRATION_TYPE = "registrationType"; public static final String FOREGROUND = "foreground"; public static final String TITLE = "title"; public static final String NOT_ID = "notId"; @@ -55,10 +56,11 @@ public interface PushConstants { 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"; + public static final String FCM = "FCM"; public static final String CONTENT_AVAILABLE = "content-available"; public static final String TOPICS = "topics"; public static final String SET_APPLICATION_ICON_BADGE_NUMBER = "setApplicationIconBadgeNumber"; + public static final String GET_APPLICATION_ICON_BADGE_NUMBER = "getApplicationIconBadgeNumber"; public static final String CLEAR_ALL_NOTIFICATIONS = "clearAllNotifications"; public static final String VISIBILITY = "visibility"; public static final String INLINE_REPLY = "inlineReply"; @@ -67,6 +69,18 @@ public interface PushConstants { public static final String TWILIO_BODY = "twi_body"; public static final String TWILIO_TITLE = "twi_title"; public static final String TWILIO_SOUND = "twi_sound"; + public static final String MP_MESSAGE = "mp_message"; public static final String START_IN_BACKGROUND = "cdvStartInBackground"; public static final String FORCE_START = "force-start"; + public static final String MESSAGE_KEY = "messageKey"; + public static final String TITLE_KEY = "titleKey"; + public static final String NO_CACHE = "no-cache"; + public static final String DISMISSED = "dismissed"; + public static final String IMAGE_TYPE = "image-type"; + public static final String IMAGE_TYPE_SQUARE = "square"; + public static final String IMAGE_TYPE_CIRCLE = "circle"; + public static final String SUBJECT = "subject"; + public static final String GOOGLE_APP_ID = "google_app_id"; + public static final String GCM_DEFAULT_SENDER_ID = "gcm_defaultSenderId"; + public static final String PUSH_DISMISSED = "push_dismissed"; } diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushDismissedHandler.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushDismissedHandler.java new file mode 100644 index 00000000..a517bc1e --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushDismissedHandler.java @@ -0,0 +1,25 @@ +package com.adobe.phonegap.push; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +public class PushDismissedHandler extends BroadcastReceiver implements PushConstants { + private static String LOG_TAG = "Push_DismissedHandler"; + + @Override + public void onReceive(Context context, Intent intent) { + Bundle extras = intent.getExtras(); + FCMService fcm = new FCMService(); + String action = intent.getAction(); + int notID = intent.getIntExtra(NOT_ID, 0); + + if (action.equals(PUSH_DISMISSED)) { + Log.d(LOG_TAG, "PushDismissedHandler = " + extras); + Log.d(LOG_TAG, "not id = " + notID); + + fcm.setNotification(notID, ""); + } + } +} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.java index 23682ac8..0d399a61 100644 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.java +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.java @@ -11,7 +11,7 @@ import android.support.v4.app.RemoteInput; public class PushHandlerActivity extends Activity implements PushConstants { - private static String LOG_TAG = "PushPlugin_PushHandlerActivity"; + private static String LOG_TAG = "Push_HandlerActivity"; /* * this activity will be started if the user touches a notification that we own. @@ -21,7 +21,7 @@ public class PushHandlerActivity extends Activity implements PushConstants { */ @Override public void onCreate(Bundle savedInstanceState) { - GCMIntentService gcm = new GCMIntentService(); + FCMService gcm = new FCMService(); Intent intent = getIntent(); @@ -34,16 +34,18 @@ public class PushHandlerActivity extends Activity implements PushConstants { Log.d(LOG_TAG, "callback = " + callback); boolean foreground = getIntent().getExtras().getBoolean("foreground", true); boolean startOnBackground = getIntent().getExtras().getBoolean(START_IN_BACKGROUND, false); + boolean dismissed = getIntent().getExtras().getBoolean(DISMISSED, false); + Log.d(LOG_TAG, "dismissed = " + dismissed); if(!startOnBackground){ NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancel(GCMIntentService.getAppName(this), notId); + notificationManager.cancel(FCMService.getAppName(this), notId); } boolean isPushPluginActive = PushPlugin.isActive(); boolean inline = processPushBundle(isPushPluginActive, intent); - if(inline && android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N){ + if(inline && android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N && !startOnBackground){ foreground = true; } @@ -51,15 +53,17 @@ public class PushHandlerActivity extends Activity implements PushConstants { finish(); - Log.d(LOG_TAG, "isPushPluginActive = " + isPushPluginActive); - if (!isPushPluginActive && foreground && inline) { - Log.d(LOG_TAG, "forceMainActivityReload"); - forceMainActivityReload(false); - } else if(startOnBackground) { - Log.d(LOG_TAG, "startOnBackgroundTrue"); - forceMainActivityReload(true); - } else { - Log.d(LOG_TAG, "don't want main activity"); + if(!dismissed) { + Log.d(LOG_TAG, "isPushPluginActive = " + isPushPluginActive); + if (!isPushPluginActive && foreground && inline) { + Log.d(LOG_TAG, "forceMainActivityReload"); + forceMainActivityReload(false); + } else if(startOnBackground) { + Log.d(LOG_TAG, "startOnBackgroundTrue"); + forceMainActivityReload(true); + } else { + Log.d(LOG_TAG, "don't want main activity"); + } } } @@ -76,7 +80,9 @@ public class PushHandlerActivity extends Activity implements PushConstants { originalExtras.putBoolean(FOREGROUND, false); originalExtras.putBoolean(COLDSTART, !isPushPluginActive); + originalExtras.putBoolean(DISMISSED, extras.getBoolean(DISMISSED)); originalExtras.putString(ACTION_CALLBACK, extras.getString(CALLBACK)); + originalExtras.remove(NO_CACHE); remoteInput = RemoteInput.getResultsFromIntent(intent); if (remoteInput != null) { diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.java index eaa39a48..176b7419 100644 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.java +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.java @@ -5,23 +5,22 @@ 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 com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.FirebaseInstanceIdService; import org.json.JSONException; import java.io.IOException; -public class PushInstanceIDListenerService extends InstanceIDListenerService implements PushConstants { - public static final String LOG_TAG = "PushPlugin_PushInstanceIDListenerService"; +public class PushInstanceIDListenerService extends FirebaseInstanceIdService implements PushConstants { + public static final String LOG_TAG = "Push_InsIdService"; @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); - } + // Get updated InstanceID token. + String refreshedToken = FirebaseInstanceId.getInstance().getToken(); + Log.d(LOG_TAG, "Refreshed token: " + refreshedToken); + // TODO: Implement this method to send any registration to your app's servers. + //sendRegistrationToServer(refreshedToken); } } diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java index f6faaa2b..32f72bf3 100644 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java @@ -1,13 +1,14 @@ package com.adobe.phonegap.push; +import android.app.Activity; 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.gcm.GcmPubSub; -import com.google.android.gms.iid.InstanceID; +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.messaging.FirebaseMessaging; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaInterface; @@ -29,7 +30,7 @@ import me.leolin.shortcutbadger.ShortcutBadger; public class PushPlugin extends CordovaPlugin implements PushConstants { - public static final String LOG_TAG = "PushPlugin"; + public static final String LOG_TAG = "Push_Plugin"; private static CallbackContext pushContext; private static CordovaWebView gWebView; @@ -59,6 +60,7 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { 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 { @@ -66,15 +68,19 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { Log.v(LOG_TAG, "execute: jo=" + jo.toString()); - senderID = jo.getString(SENDER_ID); + senderID = getStringResourceByName(GCM_DEFAULT_SENDER_ID); Log.v(LOG_TAG, "execute: senderID=" + senderID); - String savedSenderID = sharedPref.getString(SENDER_ID, ""); - registration_id = InstanceID.getInstance(getApplicationContext()).getToken(senderID, GCM); + token = FirebaseInstanceId.getInstance().getToken(); - if (!"".equals(registration_id)) { - JSONObject json = new JSONObject().put(REGISTRATION_ID, registration_id); + if (token == null) { + token = FirebaseInstanceId.getInstance().getToken(senderID,FCM); + } + + if (!"".equals(token)) { + JSONObject json = new JSONObject().put(REGISTRATION_ID, token); + json.put(REGISTRATION_TYPE, FCM); Log.v(LOG_TAG, "onRegistered: " + json.toString()); @@ -83,14 +89,14 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { PushPlugin.sendEvent( json ); } else { - callbackContext.error("Empty registration ID received from GCM"); + callbackContext.error("Empty registration ID received from FCM"); 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()); + Log.e(LOG_TAG, "execute: Got IO Exception " + e.getMessage()); callbackContext.error(e.getMessage()); } @@ -118,6 +124,8 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { 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(MESSAGE_KEY, jo.optString(MESSAGE_KEY)); + editor.putString(TITLE_KEY, jo.optString(TITLE_KEY)); editor.commit(); } @@ -143,7 +151,7 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { if (topics != null && !"".equals(registration_id)) { unsubscribeFromTopics(topics, registration_id); } else { - InstanceID.getInstance(getApplicationContext()).deleteInstanceID(); + FirebaseInstanceId.getInstance().deleteInstanceId(); Log.v(LOG_TAG, "UNREGISTER"); // Remove shared prefs @@ -194,6 +202,13 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { callbackContext.success(); } }); + } else if (GET_APPLICATION_ICON_BADGE_NUMBER.equals(action)) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + Log.v(LOG_TAG, "getApplicationIconBadgeNumber"); + callbackContext.success(getApplicationIconBadgeNumber(getApplicationContext())); + } + }); } else if (CLEAR_ALL_NOTIFICATIONS.equals(action)) { cordova.getThreadPool().execute(new Runnable() { public void run() { @@ -212,8 +227,6 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { callbackContext.success(); } catch (JSONException e) { callbackContext.error(e.getMessage()); - } catch (IOException e) { - callbackContext.error(e.getMessage()); } } }); @@ -227,8 +240,6 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { callbackContext.success(); } catch (JSONException e) { callbackContext.error(e.getMessage()); - } catch (IOException e) { - callbackContext.error(e.getMessage()); } } }); @@ -259,25 +270,41 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { /* * Sends the pushbundle extras to the client application. - * If the client application isn't currently active, it is cached for later processing. + * If the client application isn't currently active and the no-cache flag is not set, it is cached for later processing. */ public static void sendExtras(Bundle extras) { if (extras != null) { + String noCache = extras.getString(NO_CACHE); if (gWebView != null) { sendEvent(convertBundleToJson(extras)); - } else { + } else if(!"1".equals(noCache)){ Log.v(LOG_TAG, "sendExtras: caching extras to send at a later time."); gCachedExtras.add(extras); } } } + /* + * Retrives badge count from SharedPreferences + */ + public static int getApplicationIconBadgeNumber(Context context){ + SharedPreferences settings = context.getSharedPreferences(BADGE, Context.MODE_PRIVATE); + return settings.getInt(BADGE, 0); + } + + /* + * Sets badge count on application icon and in SharedPreferences + */ public static void setApplicationIconBadgeNumber(Context context, int badgeCount) { if (badgeCount > 0) { ShortcutBadger.applyCount(context, badgeCount); - } else { + }else{ ShortcutBadger.removeCount(context); } + + SharedPreferences.Editor editor = context.getSharedPreferences(BADGE, Context.MODE_PRIVATE).edit(); + editor.putInt(BADGE, Math.max(badgeCount, 0)); + editor.apply(); } @Override @@ -315,23 +342,7 @@ public class PushPlugin extends CordovaPlugin implements PushConstants { notificationManager.cancelAll(); } - /** - * Transform `topic name` to `topic path` - * Normally, the `topic` inputed from end-user is `topic name` only. - * We should convert them to GCM `topic path` - * Example: - * when topic name = 'my-topic' - * then topic path = '/topics/my-topic' - * - * @param String topic The topic name - * @return The topic path - */ - private String getTopicPath(String topic) - { - return "/topics/" + topic; - } - - private void subscribeToTopics(JSONArray topics, String registrationToken) throws IOException { + private void subscribeToTopics(JSONArray topics, String registrationToken) { if (topics != null) { String topic = null; for (int i=0; i