Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

notifee onBackgroundEvent no listen when notification is clicked #1146

Open
kabitacode opened this issue Nov 15, 2024 · 8 comments
Open

notifee onBackgroundEvent no listen when notification is clicked #1146

kabitacode opened this issue Nov 15, 2024 · 8 comments

Comments

@kabitacode
Copy link

I have a problem using notifee & firebase.
When the notification appears in the background (app is closed) when clicked the notification is not handled in onBackgroundEvent.

so the case is if the pressAction is changed to something other than the default, when clicked the log is in onBackgroundEvent, but the problem is the application does not open, while the pressAction is the default, when clicked the log is not handled in onBackgroundEvent the application also opens directly.

only type 3 is the same as DELIVERED which is heard in onBackgroundEvent.

Thank you.

My package.json :

"dependencies": {
"@notifee/react-native": "^9.1.2",
"@react-native-firebase/app": "^21.3.0",
"@react-native-firebase/messaging": "^21.3.0",
"react": "18.3.1",
"react-native": "0.76.1"
}

Screenshot 2024-11-15 at 10 16 29 Screenshot 2024-11-15 at 10 17 17
@lean098
Copy link

lean098 commented Nov 17, 2024

Same problem here!

In my case, I'm using trigger notifications, local, without firebase, closed application, the notification is shown, but when clicking the App it doesn't open.

Copy link

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

@stefanab
Copy link

I am no Android expert, but seems it might be related to PendingIntent changes in Android 14 here or here?

If anybody can give me some pointers where to look, I can have a go at resolving this issue

@spaceod
Copy link

spaceod commented Jan 4, 2025

There is the same issue with iOS. We receive the notification, but the PRESS function is not being called.

Copy link

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

@Thanaen
Copy link

Thanaen commented Feb 23, 2025

This is still an issue for me. Background events are never triggered on iOS.

@evd1ser
Copy link

evd1ser commented Mar 3, 2025

Same problem, since @notifee/[email protected] in the older versions all work fine

@jquezada19
Copy link

`/**

  • Copyright (c) 2016-present Invertase Limited & Contributors
  • Licensed under the Apache License, Version 2.0 (the "License");
  • you may not use this library except in compliance with the License.
  • You may obtain a copy of the License at
  • http://www.apache.org/licenses/LICENSE-2.0
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.

*/

#import "NotifeeCore+UNUserNotificationCenter.h"

#import "NotifeeCoreDelegateHolder.h"
#import "NotifeeCoreUtil.h"

@implementation NotifeeCoreUNUserNotificationCenter

struct {
unsigned int willPresentNotification : 1;
unsigned int didReceiveNotificationResponse : 1;
unsigned int openSettingsForNotification : 1;
} originalUNCDelegateRespondsTo;

  • (instancetype)instance {
    static dispatch_once_t once;
    __strong static NotifeeCoreUNUserNotificationCenter *sharedInstance;
    dispatch_once(&once, ^{
    sharedInstance = [[NotifeeCoreUNUserNotificationCenter alloc] init];
    sharedInstance.initialNotification = nil;
    sharedInstance.initialNotificationGathered = false;
    sharedInstance.initialNotificationBlock = nil;
    });
    return sharedInstance;
    }
  • (void)observe {
    static dispatch_once_t once;
    __weak NotifeeCoreUNUserNotificationCenter *weakSelf = self;
    dispatch_once(&once, ^{
    NotifeeCoreUNUserNotificationCenter *strongSelf = weakSelf;
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    if (center.delegate != nil) {
    _originalDelegate = center.delegate;
    originalUNCDelegateRespondsTo.openSettingsForNotification = (unsigned int)[_originalDelegate
    respondsToSelector:@selector(userNotificationCenter:openSettingsForNotification:)];
    originalUNCDelegateRespondsTo.willPresentNotification = (unsigned int)[_originalDelegate
    respondsToSelector:@selector(userNotificationCenter:
    willPresentNotification:withCompletionHandler:)];
    originalUNCDelegateRespondsTo.didReceiveNotificationResponse =
    (unsigned int)[_originalDelegate
    respondsToSelector:@selector(userNotificationCenter:
    didReceiveNotificationResponse:withCompletionHandler:)];
    }
    center.delegate = strongSelf;
    NSLog(@"[NOTIFEE] Notification center delegate set to Notifee");
    });
    }

  • (void)onDidFinishLaunchingNotification:(nonnull NSDictionary *)notifUserInfo {
    NSLog(@"[NOTIFEE] onDidFinishLaunchingNotification: %@", notifUserInfo);

    if (notifUserInfo != nil) {
    NSDictionary *notifeeNotification = notifUserInfo[kNotifeeUserInfoNotification];
    _initialNoticationID = notifeeNotification[@"id"];
    NSLog(@"[NOTIFEE] Initial notification ID: %@", _initialNoticationID);
    }

    _initialNotificationGathered = YES;
    }

  • (nullable NSDictionary *)getInitialNotification {
    NSLog(@"[NOTIFEE] getInitialNotification called, gathered: %@, block: %@",
    _initialNotificationGathered ? @"YES" : @"NO",
    _initialNotificationBlock != nil ? @"EXISTS" : @"NIL");

    if (_initialNotificationGathered && _initialNotificationBlock != nil) {
    // copying initial notification
    if (_initialNotification != nil &&
    [_initialNoticationID isEqualToString:_notificationOpenedAppID]) {
    NSDictionary *initialNotificationCopy = [_initialNotification copy];
    NSLog(@"[NOTIFEE] Returning initial notification: %@", initialNotificationCopy);
    _initialNotification = nil;
    _initialNotificationBlock(nil, initialNotificationCopy);
    } else {
    NSLog(@"[NOTIFEE] No initial notification to return");
    _initialNotificationBlock(nil, nil);
    }

    _initialNotificationBlock = nil;
    }

    return nil;
    }

#pragma mark - UNUserNotificationCenter Delegate Methods

// The method will be called on the delegate only if the application is in the
// foreground. If the the handler is not called in a timely manner then the
// notification will not be presented. The application can choose to have the
// notification presented as a sound, badge, alert and/or in the notification
// list. This decision should be based on whether the information in the
// notification is otherwise visible to the user.

  • (void)userNotificationCenter:(UNUserNotificationCenter *)center
    willPresentNotification:(UNNotification *)notification
    withCompletionHandler:
    (void (^)(UNNotificationPresentationOptions options))completionHandler {
    NSLog(@"[NOTIFEE] willPresentNotification: %@", notification.request.content.userInfo);

    NSDictionary *notifeeNotification =
    notification.request.content.userInfo[kNotifeeUserInfoNotification];

    // Handle both Notifee and non-Notifee notifications
    if (notifeeNotification != nil) {
    NSLog(@"[NOTIFEE] Processing Notifee notification");
    UNNotificationPresentationOptions presentationOptions = UNNotificationPresentationOptionNone;
    NSDictionary *foregroundPresentationOptions =
    notifeeNotification[@"ios"][@"foregroundPresentationOptions"];

    BOOL alert = [foregroundPresentationOptions[@"alert"] boolValue];
    BOOL badge = [foregroundPresentationOptions[@"badge"] boolValue];
    BOOL sound = [foregroundPresentationOptions[@"sound"] boolValue];
    BOOL banner = [foregroundPresentationOptions[@"banner"] boolValue];
    BOOL list = [foregroundPresentationOptions[@"list"] boolValue];

    if (badge) {
    presentationOptions |= UNNotificationPresentationOptionBadge;
    }

    if (sound) {
    presentationOptions |= UNNotificationPresentationOptionSound;
    }

    // if list or banner is true, ignore alert property
    if (banner || list) {
    if (banner) {
    if (@available(iOS 14, *)) {
    presentationOptions |= UNNotificationPresentationOptionBanner;
    } else {
    // for iOS 13 we need to set alert
    presentationOptions |= UNNotificationPresentationOptionAlert;
    }
    }

    if (list) {
      if (@available(iOS 14, *)) {
        presentationOptions |= UNNotificationPresentationOptionList;
      } else {
        // for iOS 13 we need to set alert
        presentationOptions |= UNNotificationPresentationOptionAlert;
      }
    }
    

    } else if (alert) {
    // TODO: remove alert once it has been fully removed from the notifee API
    presentationOptions |= UNNotificationPresentationOptionAlert;
    }

    NSDictionary *notifeeTrigger = notification.request.content.userInfo[kNotifeeUserInfoTrigger];
    if (notifeeTrigger != nil) {
    // post DELIVERED event
    [[NotifeeCoreDelegateHolder instance] didReceiveNotifeeCoreEvent:@{
    @"type" : @(NotifeeCoreEventTypeDelivered),
    @"detail" : @{
    @"notification" : notifeeNotification,
    }
    }];
    NSLog(@"[NOTIFEE] Posted DELIVERED event for notification with trigger");
    }

    completionHandler(presentationOptions);
    } else {
    NSLog(@"[NOTIFEE] Processing non-Notifee notification");
    // For non-Notifee notifications, show them with all options
    UNNotificationPresentationOptions presentationOptions = UNNotificationPresentationOptionBadge |
    UNNotificationPresentationOptionSound;

    if (@available(iOS 14, *)) {
    presentationOptions |= UNNotificationPresentationOptionBanner | UNNotificationPresentationOptionList;
    } else {
    presentationOptions |= UNNotificationPresentationOptionAlert;
    }

    // Pass to original delegate if available
    if (_originalDelegate != nil && originalUNCDelegateRespondsTo.willPresentNotification) {
    NSLog(@"[NOTIFEE] Passing to original delegate");
    [_originalDelegate userNotificationCenter:center
    willPresentNotification:notification
    withCompletionHandler:completionHandler];
    } else {
    NSLog(@"[NOTIFEE] No original delegate, handling ourselves");
    completionHandler(presentationOptions);
    }
    }
    }

// The method will be called when the user responded to the notification by
// opening the application, dismissing the notification or choosing a
// UNNotificationAction. The delegate must be set before the application returns
// from application:didFinishLaunchingWithOptions:.

  • (void)userNotificationCenter:(UNUserNotificationCenter *)center
    didReceiveNotificationResponse:(UNNotificationResponse *)response
    withCompletionHandler:(void (^)(void))completionHandler {
    NSLog(@"[NOTIFEE] didReceiveNotificationResponse: %@", response.notification.request.content.userInfo);

    NSDictionary *notifeeNotification =
    response.notification.request.content.userInfo[kNotifeeUserInfoNotification];

    NSDictionary *notificationData = response.notification.request.content.userInfo;

    BOOL isNotifeeNotification = (notifeeNotification != nil);
    NSLog(@"[NOTIFEE] Is Notifee notification: %@", isNotifeeNotification ? @"YES" : @"NO");

    // Keep track of notification ID for both Notifee and non-Notifee notifications
    if (isNotifeeNotification) {
    _notificationOpenedAppID = notifeeNotification[@"id"];
    NSLog(@"[NOTIFEE] Notification opened app ID: %@", _notificationOpenedAppID);
    } else {
    // For non-Notifee notifications, try to create a unique ID
    _notificationOpenedAppID = response.notification.request.identifier;
    NSLog(@"[NOTIFEE] Using request identifier as notification ID: %@", _notificationOpenedAppID);
    }

    // If it's not a Notifee notification but we should handle it as one
    if (!isNotifeeNotification) {
    NSLog(@"[NOTIFEE] Converting non-Notifee notification to Notifee format");
    // First pass to original delegate if available
    if (_originalDelegate != nil && originalUNCDelegateRespondsTo.didReceiveNotificationResponse) {
    NSLog(@"[NOTIFEE] Passing to original delegate first");
    [_originalDelegate userNotificationCenter:center
    didReceiveNotificationResponse:response
    withCompletionHandler:^{
    // Continue processing as a Notifee notification after original delegate completes
    [self processAsNotifeeNotification:response withCompletionHandler:completionHandler];
    }];
    return;
    } else {
    // No original delegate, process as Notifee notification directly
    [self processAsNotifeeNotification:response withCompletionHandler:completionHandler];
    return;
    }
    }

    // For actual Notifee notifications or when we want to process all as Notifee
    [self processNotifeeNotification:notifeeNotification
    response:response
    withCompletionHandler:completionHandler];
    }

// Process any notification as if it were a Notifee notification

  • (void)processAsNotifeeNotification:(UNNotificationResponse *)response
    withCompletionHandler:(void (^)(void))completionHandler {
    NSLog(@"[NOTIFEE] Processing as Notifee notification");

    // Create a Notifee-compatible notification structure from the original notification
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    NSMutableDictionary *notifeeNotification = [NSMutableDictionary dictionary];

    // Generate an ID for the notification
    NSString *notificationId = response.notification.request.identifier;
    notifeeNotification[@"id"] = notificationId;

    // Copy notification content
    notifeeNotification[@"title"] = response.notification.request.content.title;
    notifeeNotification[@"body"] = response.notification.request.content.body;

    // Copy data payload if available
    if (userInfo[@"data"]) {
    notifeeNotification[@"data"] = userInfo[@"data"];
    } else {
    // Use the entire userInfo as data
    NSMutableDictionary *dataDict = [userInfo mutableCopy];
    [dataDict removeObjectForKey:@"aps"]; // Remove APNs specific content
    notifeeNotification[@"data"] = dataDict;
    }

    // Set platform-specific options
    notifeeNotification[@"ios"] = @{
    @"foregroundPresentationOptions": @{
    @"alert": @yES,
    @"badge": @yES,
    @"sound": @yES,
    @"banner": @yES,
    @"list": @yES,
    }
    };

    NSLog(@"[NOTIFEE] Created Notifee notification: %@", notifeeNotification);

    // Process the constructed Notifee notification
    [self processNotifeeNotification:notifeeNotification
    response:response
    withCompletionHandler:completionHandler];
    }

  • (void)processNotifeeNotification:(NSDictionary *)notifeeNotification
    response:(UNNotificationResponse *)response
    withCompletionHandler:(void (^)(void))completionHandler {
    NSLog(@"[NOTIFEE] Processing notification: %@", notifeeNotification);

    if ([response.actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier]) {
    // post DISMISSED event, only triggers if notification has a categoryId
    [[NotifeeCoreDelegateHolder instance] didReceiveNotifeeCoreEvent:@{
    @"type" : @(NotifeeCoreEventTypeDismissed),
    @"detail" : @{
    @"notification" : notifeeNotification,
    }
    }];
    NSLog(@"[NOTIFEE] Posted DISMISSED event");
    completionHandler();
    return;
    }

    NSNumber *eventType;
    NSMutableDictionary *event = [NSMutableDictionary dictionary];
    NSMutableDictionary *eventDetail = [NSMutableDictionary dictionary];
    NSMutableDictionary *eventDetailPressAction = [NSMutableDictionary dictionary];

    if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
    eventType = @1; // PRESS
    // event.detail.pressAction.id
    eventDetailPressAction[@"id"] = @"default";
    NSLog(@"[NOTIFEE] Detected DEFAULT action press");
    } else {
    eventType = @2; // ACTION_PRESS
    // event.detail.pressAction.id
    eventDetailPressAction[@"id"] = response.actionIdentifier;
    NSLog(@"[NOTIFEE] Detected CUSTOM action press: %@", response.actionIdentifier);
    }

    if ([response isKindOfClass:UNTextInputNotificationResponse.class]) {
    // event.detail.input
    eventDetail[@"input"] = [(UNTextInputNotificationResponse *)response userText];
    NSLog(@"[NOTIFEE] Detected text input: %@", eventDetail[@"input"]);
    }

    // event.type
    event[@"type"] = eventType;

    // event.detail.notification
    eventDetail[@"notification"] = notifeeNotification;

    // event.detail.pressAction
    eventDetail[@"pressAction"] = eventDetailPressAction;

    // event.detail
    event[@"detail"] = eventDetail;

    // store notification for getInitialNotification
    _initialNotification = [eventDetail copy];
    NSLog(@"[NOTIFEE] Stored notification for getInitialNotification");

    // Set is initial notification flag
    if (_notificationOpenedAppID != nil &&
    [_initialNoticationID isEqualToString:_notificationOpenedAppID]) {
    eventDetail[@"initialNotification"] = @1;
    NSLog(@"[NOTIFEE] Marked as initial notification");
    }

    // post PRESS/ACTION_PRESS event
    [[NotifeeCoreDelegateHolder instance] didReceiveNotifeeCoreEvent:event];
    NSLog(@"[NOTIFEE] Posted %@ event", eventType.intValue == 1 ? @"PRESS" : @"ACTION_PRESS");

    // Complete after a short delay to ensure event is processed
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)),
    dispatch_get_main_queue(), ^{
    NSLog(@"[NOTIFEE] Calling completion handler");
    completionHandler();
    });
    }

  • (void)userNotificationCenter:(UNUserNotificationCenter *)center
    openSettingsForNotification:(nullable UNNotification *)notification {
    NSLog(@"[NOTIFEE] openSettingsForNotification: %@", notification.request.content.userInfo);

    if (_originalDelegate != nil && originalUNCDelegateRespondsTo.openSettingsForNotification) {
    if (@available(iOS 12.0, macOS 10.14, macCatalyst 13.0, *)) {
    [_originalDelegate userNotificationCenter:center openSettingsForNotification:notification];
    } else {
    // Fallback on earlier versions
    }
    }
    }

@end`

Here is a update to NotifeeCore+UNUserNotificationCenter.m
It treats all notifications as Notifee notifications and it fixed my onPress notification issues for iOS
you can update the file with patch-package

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

No branches or pull requests

7 participants