From 789e1ae825887e15577cfb56eac16d06323895b0 Mon Sep 17 00:00:00 2001 From: menelike Date: Sat, 24 Feb 2018 16:19:19 +0100 Subject: [PATCH 1/4] - be able to add lines from the payload when using inbox style - use separate inbox per notId --- .../com/adobe/phonegap/push/FCMService.java | 38 +++++++++++++++---- .../adobe/phonegap/push/PushConstants.java | 1 + 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/android/com/adobe/phonegap/push/FCMService.java b/src/android/com/adobe/phonegap/push/FCMService.java index db1738a72..f96f4e36f 100644 --- a/src/android/com/adobe/phonegap/push/FCMService.java +++ b/src/android/com/adobe/phonegap/push/FCMService.java @@ -55,15 +55,15 @@ public class FCMService extends FirebaseMessagingService implements PushConstant 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(); + messageMap.remove(notId); } else { + ArrayList messageList = messageMap.get(notId); + if (messageList == null) { + messageList = new ArrayList(); + messageMap.put(notId, messageList); + } messageList.add(message); } } @@ -659,13 +659,35 @@ private void setNotificationOngoing(Bundle extras, NotificationCompat.Builder mB private void setNotificationMessage(int notId, Bundle extras, NotificationCompat.Builder mBuilder) { String message = extras.getString(MESSAGE); + String lines = extras.getString(LINES); String style = extras.getString(STYLE, STYLE_TEXT); if (STYLE_INBOX.equals(style)) { setNotification(notId, message); mBuilder.setContentText(fromHtml(message)); - ArrayList messageList = messageMap.get(notId); + ArrayList messageList = new ArrayList(); + if (lines != null) { + setNotification(notId, ""); + try { + JSONArray linesList = new JSONArray(lines); + if (linesList.length() != 0) { + for (int i = 0; i < linesList.length(); i++) { + messageList.add(linesList.optString(i)); + setNotification(notId, linesList.optString(i)); + } + } + } catch (JSONException e) { + // nope + } + } else { + ArrayList cachedMessages = messageMap.get(notId); + messageList.add(message); + for (int i = 0; i < cachedMessages.size(); i++) { + messageList.addAll(cachedMessages); + } + } + Integer sizeList = messageList.size(); if (sizeList > 1) { String sizeListMessage = sizeList.toString(); @@ -677,7 +699,7 @@ private void setNotificationMessage(int notId, Bundle extras, NotificationCompat NotificationCompat.InboxStyle notificationInbox = new NotificationCompat.InboxStyle() .setBigContentTitle(fromHtml(extras.getString(TITLE))).setSummaryText(fromHtml(stacking)); - for (int i = messageList.size() - 1; i >= 0; i--) { + for (int i=0; i Date: Sat, 24 Feb 2018 17:15:29 +0100 Subject: [PATCH 2/4] be able to clear notifications: data: {clearNotifications: [int notId]} props to https://github.com/phonegap/phonegap-plugin-push/pull/2619 --- .../com/adobe/phonegap/push/FCMService.java | 35 +++++++++++++++++++ .../com/adobe/phonegap/push/PushPlugin.java | 11 +++--- src/ios/AppDelegate+notification.m | 35 +++++++++++++++++-- src/ios/PushPlugin.h | 1 + src/ios/PushPlugin.m | 17 +++++---- 5 files changed, 87 insertions(+), 12 deletions(-) diff --git a/src/android/com/adobe/phonegap/push/FCMService.java b/src/android/com/adobe/phonegap/push/FCMService.java index f96f4e36f..d29ca9915 100644 --- a/src/android/com/adobe/phonegap/push/FCMService.java +++ b/src/android/com/adobe/phonegap/push/FCMService.java @@ -98,11 +98,28 @@ public void onMessageReceived(RemoteMessage message) { String titleKey = prefs.getString(TITLE_KEY, TITLE); extras = normalizeExtras(applicationContext, extras, messageKey, titleKey); + String clearNotifications = extras.getString(CLEAR_NOTIFICATIONS); if (clearBadge) { PushPlugin.setApplicationIconBadgeNumber(getApplicationContext(), 0); } + if (clearNotifications != null) { + Log.d(LOG_TAG, clearNotifications); + try { + Log.d(LOG_TAG, "cancel notifications " + clearNotifications); + JSONArray notificationIds = new JSONArray(clearNotifications); + if (notificationIds.length() != 0) { + for (int i = 0; i < notificationIds.length(); i++) { + int clearNotificationId = notificationIds.getInt(i); + PushPlugin.clearNotification(getApplicationContext(), clearNotificationId); + } + } + } catch (JSONException e) { + Log.e(LOG_TAG, "malformed clear notifications =[" + clearNotifications + "]"); + } + } + // if we are in the foreground and forceShow is `false` only send data if (!forceShow && PushPlugin.isInForeground()) { Log.d(LOG_TAG, "foreground"); @@ -128,6 +145,24 @@ else if (forceShow && PushPlugin.isInForeground()) { } } } + /* + * Cancel a notification + */ + private void cancelNotification(int notificationId) { + NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + String appName = getAppName(this); + + if (notificationId != 0) { + Log.d(LOG_TAG, "cancel notification id: " + notificationId); + setNotification(notificationId, ""); + try { + notificationManager.cancel(appName, notificationId); + } catch (NullPointerException e) { + Log.e(LOG_TAG, "could not cancel notification id: " + notificationId); + } + } + } + /* * Change a values key in the extras bundle diff --git a/src/android/com/adobe/phonegap/push/PushPlugin.java b/src/android/com/adobe/phonegap/push/PushPlugin.java index 690b37776..98b7c92ce 100644 --- a/src/android/com/adobe/phonegap/push/PushPlugin.java +++ b/src/android/com/adobe/phonegap/push/PushPlugin.java @@ -534,10 +534,13 @@ private void clearAllNotifications() { } private void clearNotification(int id) { - final NotificationManager notificationManager = (NotificationManager) cordova.getActivity() - .getSystemService(Context.NOTIFICATION_SERVICE); - String appName = (String) this.cordova.getActivity().getPackageManager() - .getApplicationLabel(this.cordova.getActivity().getApplicationInfo()); + PushPlugin.clearNotification(cordova.getActivity(), id); + } + + static void clearNotification(Context context, int id) { + final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + String appName = (String) context.getPackageManager() + .getApplicationLabel(context.getApplicationInfo()); notificationManager.cancel(appName, id); } diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m index b04c47687..0816cd465 100644 --- a/src/ios/AppDelegate+notification.m +++ b/src/ios/AppDelegate+notification.m @@ -96,7 +96,9 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N silent = [contentAvailable integerValue]; } - if (silent == 1) { + NSString * clearNotificationsString = [userInfo objectForKey:@"clearNotifications"]; + // don't wakeup the app on clearNotifications - this is a decision based on performance + if (silent == 1 && clearNotificationsString == nil) { NSLog(@"this should be a silent push"); void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){ dispatch_async(dispatch_get_main_queue(), ^{ @@ -123,6 +125,7 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N pushHandler.isInline = NO; [pushHandler notificationReceived]; } else { + [self clearNotifications:userInfo]; NSLog(@"just put it in the shade"); //save it for later self.launchNotification = userInfo; @@ -130,6 +133,7 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N } } else { + [self clearNotifications:userInfo]; completionHandler(UIBackgroundFetchResultNoData); } } @@ -186,6 +190,33 @@ - (void)pushPluginOnApplicationDidBecomeActive:(NSNotification *)notification { [[NSNotificationCenter defaultCenter] postNotificationName:pushPluginApplicationDidBecomeActiveNotification object:nil]; } +- (void)clearNotifications:(NSDictionary *)userInfo +{ + PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; + + @try { + NSString * clearNotificationsString = [userInfo objectForKey:@"clearNotifications"]; + if (clearNotificationsString != nil) { + clearNotificationsString = [clearNotificationsString stringByReplacingOccurrencesOfString:@"[" withString:@""]; + clearNotificationsString = [clearNotificationsString stringByReplacingOccurrencesOfString:@"]" withString:@""]; + + NSArray * clearNotificationsArray = [clearNotificationsString componentsSeparatedByString:@","]; + + for (NSString *notId in clearNotificationsArray){ + if ([notId isKindOfClass:[NSString class]]) { + NSNumber *clearNotificationId = @([notId integerValue]); + if (clearNotificationId > 0) { + NSLog(@"Push Plugin clearing notId %@", clearNotificationId); + [pushHandler clearRealNotification:clearNotificationId]; + } + } + } + } + } @catch (NSException *exception) { + NSLog(@"Push Plugin could not parse clearNotifications array"); + } +} + - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler @@ -197,7 +228,7 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center pushHandler.isInline = YES; [pushHandler notificationReceived]; - completionHandler(UNNotificationPresentationOptionNone); + completionHandler(UNNotificationPresentationOptionBadge); } - (void)userNotificationCenter:(UNUserNotificationCenter *)center diff --git a/src/ios/PushPlugin.h b/src/ios/PushPlugin.h index 4b6ec930a..226dc8d9c 100644 --- a/src/ios/PushPlugin.h +++ b/src/ios/PushPlugin.h @@ -60,6 +60,7 @@ - (void)subscribe:(CDVInvokedUrlCommand*)command; - (void)unsubscribe:(CDVInvokedUrlCommand*)command; - (void)clearNotification:(CDVInvokedUrlCommand*)command; +- (void)clearRealNotification:(NSNumber*)notId; - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index 0290c8ecc..01e444ea5 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -466,9 +466,8 @@ - (void)notificationReceived { } } -- (void)clearNotification:(CDVInvokedUrlCommand *)command +- (void)clearRealNotification:(NSNumber *)notId { - NSNumber *notId = [command.arguments objectAtIndex:0]; [[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray * _Nonnull notifications) { /* * If the server generates a unique "notId" for every push notification, there should only be one match in these arrays, but if not, it will delete @@ -481,13 +480,19 @@ - (void)clearNotification:(CDVInvokedUrlCommand *)command [matchingNotificationIdentifiers addObject:notification.request.identifier]; } [[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:matchingNotificationIdentifiers]; - - NSString *message = [NSString stringWithFormat:@"Cleared notification with ID: %@", notId]; - CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message]; - [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; }]; } +- (void)clearNotification:(CDVInvokedUrlCommand *)command +{ + NSNumber *notId = [command.arguments objectAtIndex:0]; + [self clearRealNotification: notId]; + + NSString *message = [NSString stringWithFormat:@"Cleared notification with ID: %@", notId]; + CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message]; + [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; +} + - (void)setApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command { NSMutableDictionary* options = [command.arguments objectAtIndex:0]; From d847ce4278d0cd5d66cdf20a99f4cb54f9b41481 Mon Sep 17 00:00:00 2001 From: menelike Date: Mon, 27 May 2019 17:42:38 +0200 Subject: [PATCH 3/4] fix min/max values for clearNotification ids --- www/push.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/www/push.js b/www/push.js index 7aea0c648..e1ef8ad9f 100644 --- a/www/push.js +++ b/www/push.js @@ -1,8 +1,8 @@ /** * This file has been generated by Babel. -* +* * DO NOT EDIT IT DIRECTLY -* +* * Edit the JS source file src/js/push.js **/'use strict'; @@ -240,7 +240,7 @@ var PushNotification = function () { var id = arguments[2]; var idNumber = parseInt(id, 10); - if (isNaN(idNumber) || idNumber > Number.MAX_SAFE_INTEGER || idNumber < 0) { + if (isNaN(idNumber) || idNumber > 2147483647 || idNumber < -2147483648) { console.log('PushNotification.clearNotification failure: id parameter must' + 'be a valid integer.'); return; } @@ -390,4 +390,4 @@ module.exports = { * .init helper method. */ PushNotification: PushNotification -}; \ No newline at end of file +}; From 5b23bbbb1467e9416d6cdba432079914102f52e2 Mon Sep 17 00:00:00 2001 From: menelike Date: Thu, 23 May 2019 16:35:42 +0200 Subject: [PATCH 4/4] be able to distinguish tapped messages in iOS (added tapped (boolean) property to additionalData) --- src/ios/AppDelegate+notification.m | 3 +++ src/ios/PushPlugin.h | 2 ++ src/ios/PushPlugin.m | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/src/ios/AppDelegate+notification.m b/src/ios/AppDelegate+notification.m index 0816cd465..c18e05be0 100644 --- a/src/ios/AppDelegate+notification.m +++ b/src/ios/AppDelegate+notification.m @@ -123,6 +123,7 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N pushHandler.notificationMessage = userInfo; pushHandler.isInline = NO; + pushHandler.tapped = false; [pushHandler notificationReceived]; } else { [self clearNotifications:userInfo]; @@ -180,6 +181,7 @@ - (void)pushPluginOnApplicationDidBecomeActive:(NSNotification *)notification { if (self.launchNotification) { pushHandler.isInline = NO; + pushHandler.tapped = true; pushHandler.coldstart = [self.coldstart boolValue]; pushHandler.notificationMessage = self.launchNotification; self.launchNotification = nil; @@ -226,6 +228,7 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; pushHandler.notificationMessage = notification.request.content.userInfo; pushHandler.isInline = YES; + pushHandler.tapped = false; [pushHandler notificationReceived]; completionHandler(UNNotificationPresentationOptionBadge); diff --git a/src/ios/PushPlugin.h b/src/ios/PushPlugin.h index 226dc8d9c..a2bc25c58 100644 --- a/src/ios/PushPlugin.h +++ b/src/ios/PushPlugin.h @@ -35,6 +35,7 @@ { NSDictionary *notificationMessage; BOOL isInline; + BOOL tapped; NSString *notificationCallbackId; NSString *callback; BOOL clearBadge; @@ -51,6 +52,7 @@ @property (nonatomic, strong) NSDictionary *notificationMessage; @property BOOL isInline; +@property BOOL tapped; @property BOOL coldstart; @property BOOL clearBadge; @property (nonatomic, strong) NSMutableDictionary *handlerObj; diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index 01e444ea5..a613c81c5 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -36,6 +36,7 @@ @implementation PushPlugin : CDVPlugin @synthesize notificationMessage; @synthesize isInline; +@synthesize tapped; @synthesize coldstart; @synthesize callbackId; @@ -454,6 +455,12 @@ - (void)notificationReceived { [additionalData setObject:[NSNumber numberWithBool:NO] forKey:@"coldstart"]; } + if (tapped) { + [additionalData setObject:[NSNumber numberWithBool:YES] forKey:@"tapped"]; + } else { + [additionalData setObject:[NSNumber numberWithBool:NO] forKey:@"tapped"]; + } + [message setObject:additionalData forKey:@"additionalData"]; // send notification message @@ -463,6 +470,7 @@ - (void)notificationReceived { self.coldstart = NO; self.notificationMessage = nil; + self.tapped = false; } }