Skip to content
This repository has been archived by the owner on Sep 4, 2020. It is now read-only.

Issue 2585 - Alllowing to clear notification when the app is not running #2619

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/android/com/adobe/phonegap/push/FCMService.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,13 @@ public void onMessageReceived(RemoteMessage message) {
PushPlugin.setApplicationIconBadgeNumber(getApplicationContext(), 0);
}

int clearNotificationId = getClearNotificationId(extras);

// if the notification has a `clearNotification`, then clear it.
if(clearNotificationId != -1) {
PushPlugin.clearNotification(getApplicationContext(), clearNotificationId);
// if we are in the foreground and forceShow is `false` only send data
if (!forceShow && PushPlugin.isInForeground()) {
} else if (!forceShow && PushPlugin.isInForeground()) {
Copy link
Collaborator

@fredgalvao fredgalvao Nov 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way this is right now, and considering the example you used on the OP, I can still use the clearNotification attribute on the payload to clear said id if the application is in foreground, however the scenario on this line won't trigger and it'll fall through to the last else {, which will consider foreground:false even though we're in foreground, therefore creating a very inconsistent payload for the js to handle.

So, we have a few options:

  • we can consider that the clearNotification attribute represents a separate and independent feature on the payload, and a single payload can be {an actual notification with all the other payload attributes available} and {a request to clear a specific notification} at the same time. This would need the first if statement here to be isolated as to not race against the existing ones. Check the clearBadge feature, as that's the closest we have to this option.
  • we can consider that the clearNotification attribute represents the whole feature, and whenever it is present it will skip all other cases (if/else statements). This would need the first if statement to actually return from the method, or make the last else statement do nothing if it did clear a notification before. This would also make the example used on the OP invalid, as the title and body attributes on the payload mean nothing. This would also make it useful to move this feature to as early as possible on the method to avoid useless work (if we're gonna clear a notification and return, why waste resources preping the extras?) This would also make it needed to solve the question "who has the highest priority on the feature order: clearBadge or clearNotification?".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will take a look at it tonight or tomorrow! Thanks for taking the time! Will also update the docs :-)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider going for the first option, I would consider that the most likely use-case for people. And that way you don't force people. Will change and test it :-)

Log.d(LOG_TAG, "foreground");
extras.putBoolean(FOREGROUND, true);
extras.putBoolean(COLDSTART, false);
Expand Down Expand Up @@ -302,6 +307,20 @@ private Bundle normalizeExtras(Context context, Bundle extras, String messageKey
return newExtras;
}

private int getClearNotificationId(Bundle extras) {
int clearNotificationId = -1;
String msgcnid = extras.getString(CLEAR_NOTIFICATION);

try {
if (msgcnid != null) {
clearNotificationId = Integer.parseInt(msgcnid);
}
} catch (NumberFormatException e) {
Log.e(LOG_TAG, e.getLocalizedMessage(), e);
}
return clearNotificationId;
}

private int extractBadgeCount(Bundle extras) {
int count = -1;
String msgcnt = extras.getString(COUNT);
Expand Down
11 changes: 7 additions & 4 deletions src/android/com/adobe/phonegap/push/PushPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

public 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);
}

Expand Down
10 changes: 8 additions & 2 deletions src/ios/AppDelegate+notification.m
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N

// app is in the background or inactive, so only call notification callback if this is a silent push
if (application.applicationState != UIApplicationStateActive) {

NSLog(@"app in-active");

// do some convoluted logic to find out if this should be a silent push.
Expand All @@ -110,6 +109,13 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N
pushHandler.handlerObj = [NSMutableDictionary dictionaryWithCapacity:2];
}

// Check if this is a clear notification.
id clearNotification = [userInfo objectForKey:@"clearNotification"];
if ([clearNotification isKindOfClass:[NSString class]]) {
NSNumber *clearNotificationId = @([clearNotification integerValue]);
[pushHandler clearRealNotification: clearNotificationId];
}

id notId = [userInfo objectForKey:@"notId"];
if (notId != nil) {
NSLog(@"Push Plugin notId %@", notId);
Expand Down Expand Up @@ -154,7 +160,7 @@ - (void)checkUserHasRemoteNotificationsEnabledWithCompletionHandler:(nonnull voi
- (void)pushPluginOnApplicationDidBecomeActive:(NSNotification *)notification {

NSLog(@"active");

NSString *firstLaunchKey = @"firstLaunchKey";
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"phonegap-plugin-push"];
if (![defaults boolForKey:firstLaunchKey]) {
Expand Down
2 changes: 2 additions & 0 deletions src/ios/PushPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
- (void)unsubscribe:(CDVInvokedUrlCommand*)command;
- (void)clearNotification:(CDVInvokedUrlCommand*)command;

- (void)clearRealNotification:(NSNumber*)notId;

- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;

Expand Down
17 changes: 11 additions & 6 deletions src/ios/PushPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -466,9 +466,8 @@ - (void)notificationReceived {
}
}

- (void)clearNotification:(CDVInvokedUrlCommand *)command
- (void)clearRealNotification:(NSNumber *)notId
{
NSNumber *notId = [command.arguments objectAtIndex:0];
[[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _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
Expand All @@ -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];
Expand Down