React-native-notifee: iOS - No 'DELIVERED' event for local notifications when the app is in the background

Created on 15 Sep 2020  路  14Comments  路  Source: notifee/react-native-notifee

Hi there!

I am having a bit of trouble getting the onBackgroundEvent to work with the iOS version of our React-Native app.

The onForegroundEvent is triggered properly and executes the same onNotificationReceived callback as onBackgroundEvent.
Not only that but, on Android, both onForegroundEvent and onBackgroundEvent work perfectly fine.

It's just iOS that is not triggering the onBackgroundEvent, which is of crucial importance in our case (there is app logic tied to receiving the notification).

All the events are defined in the root of the application (index.js, imported from notification-listeners.ts) and the onBackgroundEvent callback is asynchronous, as can be seen in the code snippets below. The import is not the issue, as I have moved the code to the root index.js file with the same result - onBackgroundEvent is simply not working on iOS.

Are we missing something on the native side perhaps?

Notifee.onBackgroundEvent(async ({ type, detail }) => {
  if (type === EventType.DELIVERED) {
    onNotificationReceived(detail.notification);
  }
});

const onNotificationReceived = (notification?: Notification) => {
  if (!notification) {
    return;
  }

  const fireDate = Date.now();

  if (notification.id?.includes('repeat::')) {
    processRepeatedNotification(notification, fireDate);
    return;
  }

  const isFirstTime = Boolean(notification.data?.isFirstTime);

  if (isFirstTime) {
    createNotificationInterval(notification);
    return;
  }

  repeatReminder(notification, fireDate);

  const reminderString = notification.data?.reminder;
  if (reminderString) {
    const reminder = JSON.parse(reminderString);
    reminder.dateShown = fireDate;

    ReminderStore.addToReminderHistoryAsync(reminder);
  }
};
iOS needs-review

Most helpful comment

Here, we have the same issue when the notification is a remote notification from @react-native-community/push-notification-ios. We had to rollback to firebase.notifications().onNotificationOpened(...) because of that issue. The feature is working exactly as expected on Android, but not on iOS. Because of that issue we can't move to Firebase v6.

All 14 comments

I can confirm this - onBackgroundEvent notification received events don't work for me on iOS.

Looking at this release status comment as a potential explanation:

iOS events currently all go to onForegroundEvent - needs splitting up to support onBackgroundEvent

Any updates on this?

Here, we have the same issue when the notification is a remote notification from @react-native-community/push-notification-ios. We had to rollback to firebase.notifications().onNotificationOpened(...) because of that issue. The feature is working exactly as expected on Android, but not on iOS. Because of that issue we can't move to Firebase v6.

Just wanted to add a note here to say this is being looked into.

Just wanted to add a note here to say this is being looked into.

Thanks for the status update :)

Hi, looks like we have the same issue.
Is there anyone who already managed to make it work ?

@lbuljan am I correct in that the scenario is a trigger (local) notification, and you're waiting on the 'EventType.DELIVERED' to be sent when the app is in the background? I believe this isn't possible. For local notifications AFAIK, there's no listener provided by Apple to detect this.

The other events are working as expected, and onBackgroundEvent does trigger for iOS. For example, if you have a notification with actions, and a user selects one, the 'ACTION_PRESS' background event will be sent, or if you receive a data-only message via RNFB onMessage listener, and call displayNotification, a 'DELIVERED' background event will be sent.

@helenaford Yes, these are locally scheduled notifications. The issue here is that, as a workaround, the first scheduled notification is supposed to create notifications that will repeat every X amount of weeks (dynamic value based on the object the notification is being scheduled against) because Notifee does not support creating a scheduled interval notification with such flexibility.

v0.12.3. can only trigger interval notifications the instant they are scheduled, not at a specific time.
v.0.13.x supports creating an interval for a scheduled notification, but the repeat interval is limited in comparison to actual interval notifications (only daily, weekly and monthly are supported).

We have a heavy reliance on processing some things when the notification has been delivered - which works perfect on Android. Do you have any suggestions on how to go about this on iOS then?

Sorry for the delay, the issue is we're confined to what Apple allows us to do. Let me look into this, and see if there's something custom we can do natively for iOS.

@Salakar @mikehardy, not sure if you have any suggestions? 馃槄 Maybe there's something I've overlooked that will work "out-of-the-box", or how this can be handled on RN side.

notifee is a local notifications package, right? It has nothing to do with cloud messaging, which is the only way you can maybe wake up your app on iOS related to messaging and notifications.

So my assumption would be this is not the correct place to have any discussion of app code running on iOS when the app is not in the foreground. As soon as you leave foreground on iOS, there is a chance your app moves into quit state, and unless you have a mechanism to wake it up again, nothing runs, no handlers.

Notifee is not in charge of any of those possible wakeup mechanisms. react-native-firebase/messaging module can be used to wake it up via a cloud message if implemented carefully. react-native-background-fetch module can be used to wake it up on a schedule if the user interacts with the app frequently enough for the iOS power miser to grant your app power budget. VOIP apps are woken up by calls. Background location and motion apps are woken up by physical motion. That is the list of all wakeup methods I know of.

My recommendation (and what I've done) is implement react-native-background-fetch as well as react-native-firebase/messaging and also react-native-background-geolocation-android (though I have a legitmate use for location! if you don't, you can't do this). I send data-only messages on a regular schedule that fit my timing needs, and I receive other unscheduled wakeups with background-fetch and geolocation.

Renaming this issue title because I think it could read as all background events aren't working.

Not sure if this should even be closed because it's covering multiple things, which makes it hard come to any sort of resolution:

  • Background events not working for iOS, fix being make sure to have RNFB 7.30 + installed.
  • Triggers not being able to handle flexible intervals e.g. trigger every 2 weeks from an initial start date. Could be a possible enhancement, or something that needs to be 'under review'.
  • No 'DELIVERED' event for local notifications when the app is in the background. Something that needs to be made clear in the documentation that on iOS it's not possible.

@helenaford @mikehardy

Thanks for the feedback, seems like there is no going around the iOS limitations in our case.

However, you should definitely look into more flexible intervals as an improvement in the future. By itself, that improvement would allow at least 80% of the desired functionality on our end :)

Hi @lbuljan - do you have any specifics on the API gap for scheduling flexibility between what exists now and what you would like to see? You may have mentioned this elsewhere - if so sorry and just say so - but if not, we'd be curious what customers perceive to be missing. Thanks!

@mikehardy

To explain our use case:

Users can schedule reminders that repeat every X weeks or days (depending on the object the reminder is set against). After the reminder notification has been received, the user is supposed to receive repeated notifications in intervals of 30 minutes for 3 hours (so 6 more reminders). If the user does not respond to any of them, create an in-app reminder the user can action later (through AsyncStorage) on the last received repeated notification (the one 3 hours after the reminder has been received). If the user responds to the notifications (by actioning a specific thing within the app), cancel the 6 repeated notifications.

For instance, if the reminder is supposed to show on Friday every two weeks, what I had to do to schedule that kind of notification is:

  1. Create a timestamp trigger notification for that specific date (because we can't schedule an interval trigger at a specific date, only immediately)
  2. Once that notification is delivered, cancel it and schedule an interval trigger notification at that point in time to repeat at X amount of weeks.
  3. At the same time, schedule repeated reminders every 30 minutes up to 3 hours (and create an in-app reminder on the last one).

As you can see, the entire desired functionality depends on processing the notification when it is delivered. Works perfectly fine on Android. On iOS, however, if the first notification is delivered when the app is in background, none of the required processing is done - no interval notification is scheduled at that time. That's a bummer.

The way I see it, if we could either...

  1. immediately schedule an interval trigger notification starting at a specific date
  2. schedule a timestamp trigger notification with the repeat interval flexibility of an interval trigger notification (specify time unit and interval separately)

...we could at least be sure that the core reminder notification will be received on both platforms every X weeks or whatever the repeat interval may be. I still see no way to schedule the 6 repeated ones without relying on processing the delivered notification, but that is not as important as making sure the core notification arrives on schedule.

Was this page helpful?
0 / 5 - 0 ratings