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

Notification Event Callbacks are not Firing on iOS #561

Closed
ryanpatk opened this issue Apr 8, 2020 · 55 comments
Closed

Notification Event Callbacks are not Firing on iOS #561

ryanpatk opened this issue Apr 8, 2020 · 55 comments

Comments

@ryanpatk
Copy link

ryanpatk commented Apr 8, 2020

Thanks for picking up the task of being the only free and maintained PN library for react-native 🙏

react-native: 61.0
react-native-notifications: 3.1.4

I have followed the installation instructions exactly as outlined, and have picked up a few additional snippets from other github issues that have helped me get to a perfectly functioning Android implementation for foreground, background (warm) and background (cold) notifications.

Im having some issues on iOS though, namely none of the native event callbacks are firing:
registerNotificationOpened
registerNotificationReceivedBackground
registerNotificationReceivedForeground

I am receiving push notifications on iOS and when I press the notification banner, none of those callbacks are triggered.

It may be worth noting that getInitialNotification is working on iOS.

I've searched every issue and am at a loss. Any ideas what I may have improperly configured, or is anyone else experiencing this?

I'm using firebase to send the actual remote notifications.

@ryanpatk
Copy link
Author

ryanpatk commented Apr 8, 2020

My NotificationService code:

export class NotificationsService {
  constructor() {
    this.messaging = messaging();
  }

  /**
   * FCM-based notification permission function for iOS. Android automatically resolves to true.
   * Potentially unused in lieu of RNNotifications permissions.
   */
  requestFCMPermission = async (): Promise<string> => {
    const granted = this.messaging.requestPermission();

    if (granted) {
      console.log('User granted messaging permissions!');
    } else {
      console.log('User declined messaging permissions :(');
    }

    return granted;
  };

  /**
   * Apps using iOS must first register the app with FCM before being able to receive messages.
   * Calling this method allows FCM to send messages to your device, however if you wish to display a
   * visible notification further steps are required.
   * On Android, no registration is required and this method successfully resolves instantly.
   */
  registerAppWithFCM = async (): Promise<void> => {
    try {
      // updated from messaging().registerForRemoteNotifications to comply with v7 deprecation warning
      const register = await this.messaging.registerDeviceForRemoteMessages();

      if (!register) {
        return;
      }
    } catch (err) {
      console.log(err);

      return;
    }
  };

  /**
   * Initial setup functions required before attaching RNN event handlers
   */
  configureRNNotifications = async (): Promise<void> => {
    Notifications.events().registerRemoteNotificationsRegistered((event: Registered) => {
      // NOTE: this token does not resemble a fcmToken on iOS! it is returning an APNS
      // token which must be converted to an fcm token via an additional POST to another service.
      // see: https://github.com/wix/react-native-notifications/issues/408#issuecomment-591734138
      // On Android this will be identical to the fcm token returned in the function above.
      console.log('(RNN) Token Received', event.deviceToken);
    });

    Notifications.events().registerRemoteNotificationsRegistrationFailed(
      (event: RegistrationError) => {
        console.log(event);
      }
    );

    // Request permissions on iOS, refresh token on Android
    await Notifications.registerRemoteNotifications();
  };

  /**
   * This method attaches all of the RNN event handlers (the notification UI elements).
   * Note: I am adding them as class properties to prevent any possible duplicate instantiations.
   */
  attachRNNotificationHandlers(): void {
    this.getInitialNotification = Notifications.getInitialNotification()
      .then(notification => {
        // parse data and do something

        console.log(`initial notification opened: ${JSON.stringify(notification)}`);
      })
      .catch(() => {
        // empty
      });

    /* This triggers when the notification is received, not opened */
    this.registerNotificationReceivedForeground = Notifications.events().registerNotificationReceivedForeground(
      (notification: Notification, completion) => {
        console.log(
          `Notification received in foreground: ${notification.title} : ${notification.body}`
        );

        completion({ alert: true, sound: true, badge: true });
      }
    );

    /* This triggers when the notification is received, not opened */
    this.registerNotificationReceivedBackground = Notifications.events().registerNotificationReceivedBackground(
      (_notification: Notification, completion) => {
        console.log('registerNotificationReceivedBackground');

        completion({ alert: true, sound: true, badge: true });
      }
    );

    /* This triggers when the notification is opened, not received */
    this.registerNotificationOpened = Notifications.events().registerNotificationOpened(
      (notification: Notification, completion: () => void): void => {
        const { payload } = notification;

        // NOTE: the docs suggest some boilerplate that throws TS errors
        console.log(`Notification opened: ${payload}`);

        completion();
      }
    );
  }

  /**
   * This is the main function for registering for push notification services which invloves
   * initializing first with react-native-firebase (FCM) and then react-native-notifications (RNN).
   *
   * Steps:
   * 1. permissions (FCM)
   * 2. FCM registration (FCM)
   * 3. getting token (FCM)
   * 4. setting up messaging handlers (RNN)
   *
   * @param saveFcmToken - the callback function for saving the fcmToken to the server
   */
  initialize = async (saveFcmToken): Promise<void> => {
    let fcmToken;

    // saving the token api call onto the class instance
    this.saveFcmToken = saveFcmToken;

    // Using the permissions util from FCM. Alternatively react-native-permissions could be used.
    const hasPermission = await this.requestFCMPermission();

    if (!hasPermission) return;

    await this.registerAppWithFCM();

    try {
      // There are reports of this not working on the first run...
      // We are using this token from FCM in lieu of the deviceToken from RNN
      fcmToken = await this.messaging.getToken();

      console.log(`(FCM) Token Received: ${fcmToken}`);
    } catch (e) {
      console.log('No Token Received Error:', e);

      return;
    }

    if (fcmToken) {
      // ... send to api
    }

    await this.configureRNNotifications();

    this.attachRNNotificationHandlers();
  };
}

and my AppDelegate.m contains:

if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }

  [RNNotifications startMonitorNotifications];
  
  return YES;

and

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [RNNotifications didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  [RNNotifications didFailToRegisterForRemoteNotificationsWithError:error];
}

@jwarrencedro
Copy link

Did find a way to solve this issue? I was experiencing almost the same thing in iOS. But mine doesn't receive any notification at all. But on the Android side it works as expected.

@AlexD10S
Copy link

I am having the same issue

@ryanpatk
Copy link
Author

ryanpatk commented Apr 10, 2020

@jwarrencedro still no solution from me :(

I am able to actually receive notifications on iOS though. Its worth noting that Im using a firebase cloud messaging (fcm) token to send notifications to the device.

You can also utilize the APNS token returned from react-native-notifications to send the notifications by manually converting it into an fcm token as outlined in this comment: #408 (comment)

I have also tried using the curl method of sending a push notification directly via the APNS token (as outlined in this post: https://dev.to/jakubkoci/react-native-push-notifications-313i) to rule out firebase as the culprit of the event handlers not triggering.

I am able to successfully receive push notifications via both methods, however none of the event handler callbacks are ever invoked. I've set a bunch of log statements in the native code itself and nothing seems to trigger there either.

@AlexD10S
Copy link

Yes, the same for me, I have tried manually with Firebase Cloud Messaging and I am getting the notification (Just when the app is on background, not on foreground). However as you mention none of the handling methods are executed.

The same logic works perfectly with Android

@ryanpatk
Copy link
Author

@AlexD10S let me know if you ever figure anything out. This is really frustrating and I don't understand the native iOS side well enough to even conceptually grasp what's missing.

A lot of people report that the iOS notifications do work so I have been thinking about what kind of environment or configuration setting might be causing this difference in observed behavior.

@ryanpatk
Copy link
Author

Bumping this so that the inactivity bot doesn't get any ideas 😅

I feel like this is a serious issue and is impacting the ability to use this library at all.

Would love to hear even some quick thoughts from the maintainers about just generally what might be causing this.

@ryanpatk
Copy link
Author

@AlexD10S
I found a way to leverage FCM event handlers for iOS notifications... only thing is they don't work for Android 😅

So basically Im going to be using platform checks to instantiate Android event handlers using RNN, or ios event handlers using FCM. Its hacky, but thats react-native for you.

@aprilzero
Copy link

Seeing same exact issue here, wanted to try out this library to use those callbacks but using same code as the docs they don't seem to work

@EIrwin
Copy link

EIrwin commented Apr 28, 2020

Experiencing the same issue as well here. Really want to avoid having to piece together th implementing with FCM since it works really well for Android.

@saczuac
Copy link

saczuac commented Apr 29, 2020

Same issue

@ryanpatk
Copy link
Author

ryanpatk commented Apr 30, 2020

I know its poor form to reference another lib in the GH issues of another, but I just want to share what ended up working for me because I spent weeks dead in the water because of this problem.

Here is my implementation that uses the FCM event handler (which is semi-undocumented, make sure you're on the latest version release candidate) or the RNN event handler based on the Platform:

/*
     * This triggers when the notification is opened (foreground or background), not received.
     * Note for iOS, we are using the FCM event handler. For Android, we are using the RNN event handler.
     * TODO: If the FCM-based event handler is fixed to support android, remove the ternary here and
     * all RNN-based logic and dependencies.
     */
    this.onNotificationOpened = IS_ANDROID
      ? Notifications.events().registerNotificationOpened(
          // NOTE: the docs suggest some boilerplate that throws TS errors, see: https://github.com/wix/react-native-notifications/pull/499
          (notification: Notification, completion: () => void): void => {
            const { payload } = notification;

            // do your stuff

            completion();
          }
        )
      : this.messaging.onNotificationOpenedApp(remoteMessage => {

          // do your stuff

        });

And for the record I harbor no ill feelings toward any lib. React Native is such a complicated and community-driven ecosystem that anyone whose ever spent any time working on its open-source tooling deserves a medal and a cup of coffee :)

@bfaulk96
Copy link

bfaulk96 commented May 18, 2020

I'm experiencing the exact same behavior as you described. I guess I'll go with your "fix" described for now. It might be worth noting that this.messaging.onNotificationOpenedApp(...) worked fine for both iOS and Android in my project, so I'm just going to use that for now entirely in place of Notifications.events().registerNotificationOpened(...)

@winzazx
Copy link

winzazx commented May 29, 2020

I'm having the same issue.

@mrarlloyd
Copy link

mrarlloyd commented Jun 5, 2020

@rynatk Thanks so much for finding a work around for this, really helped me a lot!

As an addendum for anyone else finding this thread:

messaging().onNotificationOpenedApp(...)

is the workaround for BACKGROUND notifications

messaging().onMessage((remoteMessage) => {
   console.log(remoteMessage);
});

is the workaround for FOREGROUND notifications

@stale
Copy link

stale bot commented Jul 5, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the 🏚 stale label Jul 5, 2020
@bfaulk96
Copy link

bfaulk96 commented Jul 6, 2020

This is certainly still an issue and should not be closed

@stale stale bot removed the 🏚 stale label Jul 6, 2020
@tomriddle7
Copy link

Me too. I can use only three event methods.

  • registerRemoteNotificationsRegistered
  • registerRemoteNotificationsRegistrationFailed
  • getInitialNotification

@stale
Copy link

stale bot commented Aug 9, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the 🏚 stale label Aug 9, 2020
@ryanpatk
Copy link
Author

go away stalebot

@stale stale bot removed the 🏚 stale label Aug 12, 2020
@ttkien
Copy link
Contributor

ttkien commented Aug 14, 2020

I was experiencing this issue. And I found out the cause is from react-native-firebase/messaging. This issue was fixed at this commit invertase/react-native-firebase@b17df84

I also fixed the issue related to notification not called in foreground here. Please approve it invertase/react-native-firebase#4088

@stale
Copy link

stale bot commented Sep 13, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the 🏚 stale label Sep 13, 2020
@pchvramesh
Copy link

I'm facing the same issue

@stale stale bot added the 🏚 stale label Jan 29, 2021
@erkie
Copy link
Contributor

erkie commented Jan 29, 2021

I was having similar issues and for some reason because I was using yarn link react-native-notifications. Apparently there is a bug in yarn that can cause duplicate imports of React and React Native:

https://stackoverflow.com/questions/57871715/duplicate-reactjs-import-issue-when-using-npm-link-to-test-component-before-publ

This caused the NativeEventEmitter instance to use a duplicate copy of the sharedSubscriber store.

https://github.com/wix/react-native-notifications/blob/master/lib/src/adapters/NativeEventsReceiver.ts#L12
https://github.com/facebook/react-native/blob/4421a64ac1ea9df3827fb99194c8576a0750beab/Libraries/EventEmitter/NativeEventEmitter.js#L45

I think it might be worth checking into if people are running into this issue, because it seems like it can happen quite often in the wild.

@stale stale bot removed the 🏚 stale label Jan 29, 2021
@kgsachinthaudara
Copy link

I have same issue, not any event get trigger, tested in real devices as well

@zkwentz
Copy link

zkwentz commented Mar 13, 2021

I had this issue after migrating from PushNotificationIOS.

One thing I didn't do, that brought me to this issue, was remove the UNUserNotificationCenter delegate that I added to my AppDelegate.h file as part of PushNotificationIOS setup.

Removing that allowed this library to start firing callbacks in IOS. So if you're in a similar situation as me, be sure to remove that delegate.

@goldqwert
Copy link

goldqwert commented Mar 25, 2021

Same problem on iOS and mine

registerNotificationOpened
registerNotificationReceivedBackground
registerNotificationReceivedForeground

Does not work

@anisimov74
Copy link
Contributor

anisimov74 commented Apr 20, 2021

Do not forget to Enable the Remote Notifications Capability as it mentioned in the handling notifications section

@andreialecu
Copy link

@anisimov74 I think the problem is that everything works except for the three events noted in the comment above you.

I can receive notifications, just in the background.

  useEffect(() => {
    const sub = Notifications.events().registerNotificationReceivedForeground(
      (notification: Notification, completion) => {
        console.log(
          `Notification received in foreground: ${notification.title} : ${notification.body}`,
        );
        completion({alert: true, sound: false, badge: false});
      },
    );

    return () => {
      sub.remove();
    };
  }, []);

For example, the above never fires, I cannot see that console.log. I do get a valid token in registerRemoteNotificationsRegistered which works. The notifications are delivered if the app is backgrounded, I can see them on the lock screen.

@andreialecu
Copy link

andreialecu commented Apr 22, 2021

I was able to get this resolved. It appears that another dependency was hijacking the notification center delegate.

I found this by searching for UNUserNotificationCenter across all files via Xcode (you can also use grep to search inside your ios folder)

In my case the offending dependency was: https://github.com/Countly/countly-sdk-ios/blob/9addfda94f6c2eddcaf2bb8df572cc7745696513/CountlyPushNotifications.m#L70-L71

Once that was dealt with, registerNotificationReceivedForeground started firing.

Note that I wasn't even using the Countly push notification functionality, but it seems to be enabled by default without warning.

@stale
Copy link

stale bot commented Jun 12, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the 🏚 stale label Jun 12, 2021
@erkie
Copy link
Contributor

erkie commented Jun 15, 2021

STOP

@DanielEliraz
Copy link
Collaborator

DanielEliraz commented Jun 26, 2021

I want to try and figure it out, the solutions people found here are (big applause to all of them):

Please, anyone who is facing this issue, try those solutions and if it doesn't work write it here and we will continue investigating

@stale
Copy link

stale bot commented Jul 26, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the 🏚 stale label Jul 26, 2021
@stale
Copy link

stale bot commented Aug 2, 2021

The issue has been closed for inactivity.

@stale stale bot closed this as completed Aug 2, 2021
@numandev1
Copy link

registerNotificationOpened
registerNotificationReceivedBackground
registerNotificationReceivedForeground
are not trigger but when I get notification I am getting this warning on Xcode log

Warning: UNUserNotificationCenter delegate received call to -userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: but the completion handler was never called.

@numandev1
Copy link

numandev1 commented Aug 31, 2021

I fixed by adding these lines into info.plist because I was also using react-native-firebase

<key>FirebaseAppDelegateProxyEnabled</key>
<false/>

@kesha-antonov
Copy link

In my case I forgot to link ios properly in AppDelegate and staff: https://wix.github.io/react-native-notifications/docs/getting-started/#ios

@weihangChen
Copy link
Contributor

  • (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
    fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [RNNotifications didReceiveBackgroundNotification:userInfo withCompletionHandler:completionHandler];

    completionHandler(UIBackgroundFetchResultNewData);
    }

after applying your suggested update, I got the registerNotificationReceivedBackground trigged, but it got triggered three times, and Xcode also got into exception and run into infinite loop
Screenshot 2022-01-03 at 21 50 28

@weihangChen
Copy link
Contributor

I have experienced same problems as you guys , and here is the solution, first the document is not updated, but the example.js in the project is. if you compare the quick start guide with the code here

then you see this is missing from the quick start guide

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
  [RNNotifications didReceiveBackgroundNotification:userInfo withCompletionHandler:completionHandler];
}

I can log the incoming message from firebase but I can't really use completion({alert: true, sound: true, badge: true}); it complains that it is nssting not a nsdictionary. also the code has incorrect import, It should be #import <RNNotifications.h>
Screenshot 2022-01-03 at 22 43 46

@DanielEliraz
Copy link
Collaborator

@weihangChen , PR will be welcomed 🍦

@weihangChen
Copy link
Contributor

@DanielEliraz , PR created
#800

@iledzka
Copy link

iledzka commented Jun 6, 2023

My issue was that I had a custom implementation for

(void)userNotificationCenter:(UNUserNotificationCenter *)center
    didReceiveNotificationResponse:(UNNotificationResponse *)response
             withCompletionHandler:(void (^)(void))completionHandler

in my AppDelegate.m file. If I don't implement this delegate method, then I can get the callbacks working as expected. This is because my implementation seems to be hijacking the implementation of this method by the library (it is supposed to be hitting this code

[_notificationEventHandler didReceiveNotificationResponse:response completionHandler:completionHandler];
). I'll probably need to create a patch because I need a custom didReceiveNotificationResponse for another push provider :/

@DanielEliraz
Copy link
Collaborator

@iledzka did it work for you?

@JameFreshket
Copy link

@iledzka I have a custom implementation too, but it has an issue. Could you please tell me if you have patched the RNNotificationCenterListener.m?

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

No branches or pull requests