3131import java .net .URL ;
3232import java .util .ArrayList ;
3333import java .util .HashMap ;
34+ import java .util .Iterator ;
3435import java .util .Random ;
3536
3637@ SuppressLint ("NewApi" )
@@ -62,6 +63,8 @@ public void onMessageReceived(String from, Bundle extras) {
6263 SharedPreferences prefs = getApplicationContext ().getSharedPreferences (PushPlugin .COM_ADOBE_PHONEGAP_PUSH , Context .MODE_PRIVATE );
6364 boolean forceShow = prefs .getBoolean (FORCE_SHOW , false );
6465
66+ normalizeExtras (extras );
67+
6568 // if we are in the foreground and forceShow is `false` only send data
6669 if (!forceShow && PushPlugin .isInForeground ()) {
6770 extras .putBoolean (FOREGROUND , true );
@@ -81,12 +84,103 @@ else if (forceShow && PushPlugin.isInForeground()) {
8184 }
8285 }
8386 }
84-
87+
88+ /*
89+ * Change a values key in the extras bundle
90+ */
91+ private void replaceKey (String oldKey , String newKey , Bundle extras ) {
92+ Object value = extras .get (oldKey );
93+ if ( value != null ) {
94+ extras .remove (oldKey );
95+ if (value instanceof String ) {
96+ extras .putString (newKey , (String ) value );
97+ } else if (value instanceof Boolean ) {
98+ extras .putBoolean (newKey , (Boolean ) value );
99+ } else if (value instanceof Number ) {
100+ extras .putDouble (newKey , ((Number ) value ).doubleValue ());
101+ } else {
102+ extras .putString (newKey , String .valueOf (value ));
103+ }
104+ }
105+ }
106+
107+ /*
108+ * Replace alternate keys with our canonical value
109+ */
110+ private String normalizeKey (String key ) {
111+ if (key .equals (BODY ) || key .equals (ALERT )) {
112+ return MESSAGE ;
113+ } else if (key .equals (MSGCNT ) || key .equals (BADGE )) {
114+ return COUNT ;
115+ } else if (key .equals (SOUNDNAME )) {
116+ return SOUND ;
117+ } else if (key .startsWith (GCM_NOTIFICATION )) {
118+ return key .substring (GCM_NOTIFICATION .length ()+1 , key .length ());
119+ } else if (key .startsWith (GCM_N )) {
120+ return key .substring (GCM_N .length ()+1 , key .length ());
121+ } else if (key .startsWith (UA_PREFIX )) {
122+ key = key .substring (UA_PREFIX .length ()+1 , key .length ());
123+ return key .toLowerCase ();
124+ } else {
125+ return key ;
126+ }
127+ }
128+
129+ /*
130+ * Parse bundle into normalized keys.
131+ */
132+ private void normalizeExtras (Bundle extras ) {
133+ Log .d (LOG_TAG , "mormalize extras" );
134+ Iterator <String > it = extras .keySet ().iterator ();
135+ while (it .hasNext ()) {
136+ String key = it .next ();
137+
138+ Log .d (LOG_TAG , "key = " + key );
139+
140+ // If the key is "data" or "message" and the value is a json object extract
141+ // This is to support parse.com and other services. Issue #147 and pull #218
142+ if (key .equals (PARSE_COM_DATA ) || key .equals (MESSAGE )) {
143+ Object json = extras .get (key );
144+ // Make sure data is json object stringified
145+ if ( json instanceof String && ((String ) json ).startsWith ("{" ) ) {
146+ Log .d (LOG_TAG , "extracting nested message data from key = " + key );
147+ try {
148+ // If object contains message keys promote each value to the root of the bundle
149+ JSONObject data = new JSONObject ((String ) json );
150+ if ( data .has (ALERT ) || data .has (MESSAGE ) || data .has (BODY ) || data .has (TITLE ) ) {
151+ Iterator <String > jsonIter = data .keys ();
152+ while (jsonIter .hasNext ()) {
153+ String jsonKey = jsonIter .next ();
154+
155+ Log .d (LOG_TAG , "key = data/" + jsonKey );
156+
157+ String value = data .getString (jsonKey );
158+ jsonKey = normalizeKey (jsonKey );
159+ extras .putString (jsonKey , value );
160+ }
161+
162+ extras .remove (key );
163+ }
164+ } catch ( JSONException e ) {
165+ Log .e (LOG_TAG , "normalizeExtras: JSON exception" );
166+ }
167+ }
168+ }
169+
170+ String newKey = normalizeKey (key );
171+ if ( !key .equals (newKey ) ) {
172+ Log .d (LOG_TAG , "replace key " + key + " with " + newKey );
173+ replaceKey (key , newKey , extras );
174+ }
175+ } // while
176+
177+ }
178+
85179 private void showNotificationIfPossible (Context context , Bundle extras ) {
86180
87181 // Send a notification if there is a message or title, otherwise just send data
88- String message = this . getMessageText ( extras );
89- String title = getString (extras , TITLE , "" );
182+ String message = extras . getString ( MESSAGE );
183+ String title = extras . getString (TITLE );
90184 if ((message != null && message .length () != 0 ) ||
91185 (title != null && title .length () != 0 )) {
92186 createNotification (context , extras );
@@ -113,8 +207,8 @@ public void createNotification(Context context, Bundle extras) {
113207 NotificationCompat .Builder mBuilder =
114208 new NotificationCompat .Builder (context )
115209 .setWhen (System .currentTimeMillis ())
116- .setContentTitle (getString (extras , TITLE ))
117- .setTicker (getString (extras , TITLE ))
210+ .setContentTitle (extras . getString (TITLE ))
211+ .setTicker (extras . getString (TITLE ))
118212 .setContentIntent (contentIntent )
119213 .setAutoCancel (true );
120214
@@ -141,7 +235,7 @@ public void createNotification(Context context, Bundle extras) {
141235 * To use, add the `iconColor` key to plugin android options
142236 *
143237 */
144- setNotificationIconColor (getString (extras , "color" ), mBuilder , localIconColor );
238+ setNotificationIconColor (extras . getString ("color" ), mBuilder , localIconColor );
145239
146240 /*
147241 * Notification Icon
@@ -208,7 +302,7 @@ public void createNotification(Context context, Bundle extras) {
208302
209303 private void createActions (Bundle extras , NotificationCompat .Builder mBuilder , Resources resources , String packageName ) {
210304 Log .d (LOG_TAG , "create actions" );
211- String actions = getString (extras , ACTIONS );
305+ String actions = extras . getString (ACTIONS );
212306 if (actions != null ) {
213307 try {
214308 JSONArray actionsArray = new JSONArray (actions );
@@ -231,17 +325,17 @@ private void createActions(Bundle extras, NotificationCompat.Builder mBuilder, R
231325 }
232326
233327 private void setNotificationCount (Bundle extras , NotificationCompat .Builder mBuilder ) {
234- String msgcnt = getString (extras , MSGCNT );
328+ String msgcnt = extras . getString (MSGCNT );
235329 if (msgcnt == null ) {
236- msgcnt = getString (extras , BADGE );
330+ msgcnt = extras . getString (BADGE );
237331 }
238332 if (msgcnt != null ) {
239333 mBuilder .setNumber (Integer .parseInt (msgcnt ));
240334 }
241335 }
242336
243337 private void setNotificationVibration (Bundle extras , Boolean vibrateOption , NotificationCompat .Builder mBuilder ) {
244- String vibrationPattern = getString (extras , VIBRATION_PATTERN );
338+ String vibrationPattern = extras . getString (VIBRATION_PATTERN );
245339 if (vibrationPattern != null ) {
246340 String [] items = vibrationPattern .replaceAll ("\\ [" , "" ).replaceAll ("\\ ]" , "" ).split ("," );
247341 long [] results = new long [items .length ];
@@ -259,9 +353,9 @@ private void setNotificationVibration(Bundle extras, Boolean vibrateOption, Noti
259353 }
260354
261355 private void setNotificationMessage (int notId , Bundle extras , NotificationCompat .Builder mBuilder ) {
262- String message = getMessageText ( extras );
356+ String message = extras . getString ( MESSAGE );
263357
264- String style = getString (extras , STYLE , STYLE_TEXT );
358+ String style = extras . getString (STYLE , STYLE_TEXT );
265359 if (STYLE_INBOX .equals (style )) {
266360 setNotification (notId , message );
267361
@@ -272,12 +366,12 @@ private void setNotificationMessage(int notId, Bundle extras, NotificationCompat
272366 if (sizeList > 1 ) {
273367 String sizeListMessage = sizeList .toString ();
274368 String stacking = sizeList + " more" ;
275- if (getString (extras , SUMMARY_TEXT ) != null ) {
276- stacking = getString (extras , SUMMARY_TEXT );
369+ if (extras . getString (SUMMARY_TEXT ) != null ) {
370+ stacking = extras . getString (SUMMARY_TEXT );
277371 stacking = stacking .replace ("%n%" , sizeListMessage );
278372 }
279373 NotificationCompat .InboxStyle notificationInbox = new NotificationCompat .InboxStyle ()
280- .setBigContentTitle (getString (extras , TITLE ))
374+ .setBigContentTitle (extras . getString (TITLE ))
281375 .setSummaryText (stacking );
282376
283377 for (int i = messageList .size () - 1 ; i >= 0 ; i --) {
@@ -289,19 +383,19 @@ private void setNotificationMessage(int notId, Bundle extras, NotificationCompat
289383 NotificationCompat .BigTextStyle bigText = new NotificationCompat .BigTextStyle ();
290384 if (message != null ) {
291385 bigText .bigText (message );
292- bigText .setBigContentTitle (getString (extras , TITLE ));
386+ bigText .setBigContentTitle (extras . getString (TITLE ));
293387 mBuilder .setStyle (bigText );
294388 }
295389 }
296390 } else if (STYLE_PICTURE .equals (style )) {
297391 setNotification (notId , "" );
298392
299393 NotificationCompat .BigPictureStyle bigPicture = new NotificationCompat .BigPictureStyle ();
300- bigPicture .bigPicture (getBitmapFromURL (getString (extras , PICTURE )));
301- bigPicture .setBigContentTitle (getString (extras , TITLE ));
302- bigPicture .setSummaryText (getString (extras , SUMMARY_TEXT ));
394+ bigPicture .bigPicture (getBitmapFromURL (extras . getString (PICTURE )));
395+ bigPicture .setBigContentTitle (extras . getString (TITLE ));
396+ bigPicture .setSummaryText (extras . getString (SUMMARY_TEXT ));
303397
304- mBuilder .setContentTitle (getString (extras , TITLE ));
398+ mBuilder .setContentTitle (extras . getString (TITLE ));
305399 mBuilder .setContentText (message );
306400
307401 mBuilder .setStyle (bigPicture );
@@ -314,9 +408,9 @@ private void setNotificationMessage(int notId, Bundle extras, NotificationCompat
314408 mBuilder .setContentText (Html .fromHtml (message ));
315409
316410 bigText .bigText (message );
317- bigText .setBigContentTitle (getString (extras , TITLE ));
411+ bigText .setBigContentTitle (extras . getString (TITLE ));
318412
319- String summaryText = getString (extras , SUMMARY_TEXT );
413+ String summaryText = extras . getString (SUMMARY_TEXT );
320414 if (summaryText != null ) {
321415 bigText .setSummaryText (summaryText );
322416 }
@@ -331,34 +425,10 @@ private void setNotificationMessage(int notId, Bundle extras, NotificationCompat
331425 }
332426 }
333427
334- private String getString (Bundle extras ,String key ) {
335- String message = extras .getString (key );
336- if (message == null ) {
337- message = extras .getString (GCM_NOTIFICATION +"." +key );
338- }
339- return message ;
340- }
341-
342- private String getString (Bundle extras ,String key , String defaultString ) {
343- String message = extras .getString (key );
344- if (message == null ) {
345- message = extras .getString (GCM_NOTIFICATION +"." +key , defaultString );
346- }
347- return message ;
348- }
349-
350- private String getMessageText (Bundle extras ) {
351- String message = getString (extras , MESSAGE );
352- if (message == null ) {
353- message = getString (extras , BODY );
354- }
355- return message ;
356- }
357-
358428 private void setNotificationSound (Context context , Bundle extras , NotificationCompat .Builder mBuilder ) {
359- String soundname = getString (extras , SOUNDNAME );
429+ String soundname = extras . getString (SOUNDNAME );
360430 if (soundname == null ) {
361- soundname = getString (extras , SOUND );
431+ soundname = extras . getString (SOUND );
362432 }
363433 if (soundname != null ) {
364434 Uri sound = Uri .parse (ContentResolver .SCHEME_ANDROID_RESOURCE
@@ -371,7 +441,7 @@ private void setNotificationSound(Context context, Bundle extras, NotificationCo
371441 }
372442
373443 private void setNotificationLedColor (Bundle extras , NotificationCompat .Builder mBuilder ) {
374- String ledColor = getString (extras , LED_COLOR );
444+ String ledColor = extras . getString (LED_COLOR );
375445 if (ledColor != null ) {
376446 // Converts parse Int Array from ledColor
377447 String [] items = ledColor .replaceAll ("\\ [" , "" ).replaceAll ("\\ ]" , "" ).split ("," );
@@ -390,7 +460,7 @@ private void setNotificationLedColor(Bundle extras, NotificationCompat.Builder m
390460 }
391461
392462 private void setNotificationPriority (Bundle extras , NotificationCompat .Builder mBuilder ) {
393- String priorityStr = getString (extras , PRIORITY );
463+ String priorityStr = extras . getString (PRIORITY );
394464 if (priorityStr != null ) {
395465 try {
396466 Integer priority = Integer .parseInt (priorityStr );
@@ -406,7 +476,7 @@ private void setNotificationPriority(Bundle extras, NotificationCompat.Builder m
406476 }
407477
408478 private void setNotificationLargeIcon (Bundle extras , String packageName , Resources resources , NotificationCompat .Builder mBuilder ) {
409- String gcmLargeIcon = getString (extras , IMAGE ); // from gcm
479+ String gcmLargeIcon = extras . getString (IMAGE ); // from gcm
410480 if (gcmLargeIcon != null ) {
411481 if (gcmLargeIcon .startsWith ("http://" ) || gcmLargeIcon .startsWith ("https://" )) {
412482 mBuilder .setLargeIcon (getBitmapFromURL (gcmLargeIcon ));
@@ -436,7 +506,7 @@ private void setNotificationLargeIcon(Bundle extras, String packageName, Resourc
436506
437507 private void setNotificationSmallIcon (Context context , Bundle extras , String packageName , Resources resources , NotificationCompat .Builder mBuilder , String localIcon ) {
438508 int iconId = 0 ;
439- String icon = getString (extras , ICON );
509+ String icon = extras . getString (ICON );
440510 if (icon != null ) {
441511 iconId = resources .getIdentifier (icon , DRAWABLE , packageName );
442512 Log .d (LOG_TAG , "using icon from plugin options" );
@@ -496,7 +566,7 @@ private int parseInt(String value, Bundle extras) {
496566 int retval = 0 ;
497567
498568 try {
499- retval = Integer .parseInt (getString (extras , value ));
569+ retval = Integer .parseInt (extras . getString (value ));
500570 }
501571 catch (NumberFormatException e ) {
502572 Log .e (LOG_TAG , "Number format exception - Error parsing " + value + ": " + e .getMessage ());
0 commit comments