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

iOS - No 'DELIVERED' event for local notifications when the app is in the background #146

Closed
lbuljan opened this issue Sep 15, 2020 · 16 comments
Labels
documentation Improvements or additions to documentation Platform: iOS

Comments

@lbuljan
Copy link

lbuljan commented Sep 15, 2020

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);
  }
};
@afestein
Copy link

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

@lbuljan
Copy link
Author

lbuljan commented Sep 18, 2020

Any updates on this?

@jimmyfortinx
Copy link

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.

@helenaford
Copy link
Member

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

@lbuljan
Copy link
Author

lbuljan commented Sep 30, 2020

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

Thanks for the status update :)

@NicolasSmit
Copy link

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

@helenaford
Copy link
Member

helenaford commented Oct 2, 2020

@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.

@lbuljan
Copy link
Author

lbuljan commented Oct 3, 2020

@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?

@helenaford
Copy link
Member

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.

@mikehardy
Copy link
Collaborator

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.

@helenaford
Copy link
Member

helenaford commented Oct 9, 2020

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 helenaford changed the title iOS - onBackgroundEvent is not triggered when application is in background/killed iOS - No 'DELIVERED' event for local notifications when the app is in the background Oct 9, 2020
@lbuljan
Copy link
Author

lbuljan commented Oct 10, 2020

@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 :)

@mikehardy
Copy link
Collaborator

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!

@lbuljan
Copy link
Author

lbuljan commented Oct 10, 2020

@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.

@eqlion
Copy link

eqlion commented Mar 29, 2021

@lbuljan, we have almost the same use-case and the same issue in our app. On Android, a background notification is handled with no problems, however on iOS onBackgroundEvent doesn't fire at all. Even without checking the type of the notification, it still doesn't log anything neither in RN terminal, nor in XCode terminal. I'm not even sure how to debug it. On the other hand, I'm 100% sure that the action is not fired in background, as I would've been able to detect that.
Any help would be appreciated, I can share any details needed for tracing this issue.
RN version: 0.62.2
iOS version: 12.4.5
Notifee version: 1.2.1
Android version: 10
(Edit): I've tried logging the notification with both onBackgroundEvent and onForegroundEvent (just in case), but to no avail, alas. The later is triggered on iOS for some reason when the notifications are created (not sure whether it should work like that)

@helenaford
Copy link
Member

Docs now updated to reflect the limitation around 'DELIVERED' event. Please see https://notifee.app/react-native/docs/events. For any other issues mentioned here, please open a new git issue (if none exist for it).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation Improvements or additions to documentation Platform: iOS
Projects
None yet
Development

No branches or pull requests

7 participants