Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.

cancelLocalNotifications() does not work on Android #2100

Closed
jamesxabregas opened this issue Jul 21, 2021 · 7 comments
Closed

cancelLocalNotifications() does not work on Android #2100

jamesxabregas opened this issue Jul 21, 2021 · 7 comments

Comments

@jamesxabregas
Copy link

jamesxabregas commented Jul 21, 2021

I have tested this extensively to see if there was something wrong with the way I was excuting cancelLocalNotification() but it does not appear that this works when providing an id on Android. I am executing it exactly per the documentation.

After adding debug logging into the Anrdoid pacakge I believe I have found the root cause of the issue. In RNPushNotificationHelper.java the method cancelScheduledNotification(ReadableMap userInfo) tries to extract the id from the provided JSON map and then find the correct notification to cancel.

RNPushNotificationAttributes notificationAttributes = fromJson(notificationAttributesJson);
if (notificationAttributes.matches(userInfo)) {
cancelScheduledNotification(id);
}

The problem here is that the matches method in RNPushNotificationAttributes.java is being used incorrectly in this case. That method tries to match every element of the userInfo object with the notification it is iterating on which contains additional info such as the title, message etc. If the user has only provided the id attribute this always returns false.

public boolean matches(ReadableMap userInfo) {
try {
if(this.userInfo == null) {
return false;
}
JSONObject jsonObject = new JSONObject(this.userInfo);
ReadableMapKeySetIterator iterator = userInfo.keySetIterator();
while (iterator.hasNextKey()) {
String key = iterator.nextKey();
if (!jsonObject.has(key))
return false;
switch (userInfo.getType(key)) {
case Null: {
if (jsonObject.get(key) != null)
return false;
break;
}
case Boolean: {
if (userInfo.getBoolean(key) != jsonObject.getBoolean(key))
return false;
break;
}
case Number: {
if ((userInfo.getDouble(key) != jsonObject.getDouble(key)) && (userInfo.getInt(key) != jsonObject.getInt(key)))
return false;
break;
}
case String: {
if (!userInfo.getString(key).equals(jsonObject.getString(key)))
return false;
break;
}
case Map:
return false;//there are no maps in the jsonObject
case Array:
return false;//there are no arrays in the jsonObject
}
}
} catch(JSONException e) {
return false;
}
return true;
}

What is needed in this check is a simple method that matches the id's only.

For instance something like this in RNPushNotificationHelper.java:

RNPushNotificationAttributes notificationAttributes = fromJson(notificationAttributesJson);
if (notificationAttributes.idMatches(userInfo)) {
    cancelScheduledNotification(id);
}

and this in RNPushNotificationAttributes.java

public boolean idMatches(ReadableMap userInfo) {
try {
    if(this.userInfo == null || userInfo == null) {
        return false;
    }
        return this.id.equals(userInfo.getString("id"));
    } catch(Exception e) {
        return false;
    }
}

I am happy to submit a pull request for this issue. I am working on my own fork at the moment.

jamesxabregas added a commit to sparkello/react-native-push-notification that referenced this issue Jul 21, 2021
…droid that meant notifications were not being cancelled. Changed matching logic to compare ids only.
@Dallas62
Copy link
Collaborator

Hi @jamesxabregas
Did you cross check cases on iOS?
With multiple data in userInfo?

There is another method on Android which allow remove a scheduled notification only with the id.

@jamesxabregas jamesxabregas changed the title cancelLocalNotification does not work on Android cancelLocalNotifications does not work on Android Jul 21, 2021
@jamesxabregas jamesxabregas changed the title cancelLocalNotifications does not work on Android cancelLocalNotifications() does not work on Android Jul 21, 2021
@jamesxabregas
Copy link
Author

I've tested this on iOS and it is not an issue. The issue only occurs on Android, and as explained it is due to an error in the Android implementation. I have also tested this with other data in the userInfo object but that doesn't make a difference.

The other method within the Android implementation is a private method. It is not accessible from the JavaScript interface, it is used internally by the public method of the same name that accepts the userInfo map.

I actually did wonder why cancelLocalNotifications() is implemented the way that it is. It would be far easier to just pass it a string with the id instead of having to parse the JSON object and extract the id.

@Dallas62
Copy link
Collaborator

I was thinking of:

But I will take a look ASAP.

@jamesxabregas
Copy link
Author

I believe clearNotification has a different purpose as it removes a delivered notification from the Notification Center.

@garrettmaring
Copy link

I've also observed a difference in cancelLocalNotifications() between iOS & Android. While cancelling in this manner works for iOS, it seems as though calls to the method silently fail on Android causing the list of scheduled notifications to continue to grow.

Is it possible that we need to pass channelId to this cancel method?

big
bigger

@Dallas62
Copy link
Collaborator

Fixed in 8.0.0.
Regards

@dimadeveatii
Copy link
Contributor

@Dallas62 this is still not working in latest v8.0.0.
Please see #2122

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants