OneSignal-Cordova-SDK icon indicating copy to clipboard operation
OneSignal-Cordova-SDK copied to clipboard

Notifications Are Not Received when iOS App is in Foreground

Open selected-pixel-jameson opened this issue 4 years ago • 24 comments

Description: I'm able to receive iOS notifications fine when the app is not open. However, when I open the app the notifications do not show up. Previously I was able to adjust how these notifications showed up, but I'm not longer able to do that with version 3.0 of the library.

OneSignal.shared.setInFocusDisplayType(OSNotificationDisplayType.notification)

Is no longer an option of any kind.

(your description here)

Environment OneSignal Cordova SDK : 3.0 Capacitor 3.0

I have added I have UNUserNotificationCenterDelegate to the AppDelegate in the XCode Project.

I have added

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    willPresent notification: UNNotification,
                                    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
     print("Push notification received in foreground.")
     completionHandler([.alert, .sound, .badge])
  }

To handled the push notifications that are received while the app is in the foreground. Still nothing.

Also, I'm not using any of Capacitor's Push Notification libraries or any other cordova libraries. I've had this working in my App for years. Since I've updated the iOS version to beyond 12.1 it no longer works.

selected-pixel-jameson avatar Sep 20 '21 20:09 selected-pixel-jameson

In efforts to try and figure this out I've implemented the setNotificationWillShowInForegroundHandler().

window['plugins'].OneSignal.setNotificationWillShowInForegroundHandler(() => {
          console.log("--------- SHOW NOTIFICATION IN FOREGROUND -------------")
})

I see this log within XCode when I send a push notification along with the payload of the push notification itself, but no notifications are shown.

selected-pixel-jameson avatar Sep 21 '21 18:09 selected-pixel-jameson

The only way I was able to work my way around this was by implementing Local Notifications and when I receive a notification from setNotificationWillShowInForegroundHandler() I set a local notification to be displayed immediately.

        window['plugins'].OneSignal.setNotificationWillShowInForegroundHandler((payload) => {
          this.currentNotification = payload.notification
          let notification: LocalNotificationSchema = {
            title: payload.notification.title || null,
            body: payload.notification.body || null,
            id: Date.now() || null,
            extra: payload.notification.additionalData || null

          }
          let notifications: ScheduleOptions = {
            notifications: [notification]
          }
          LocalNotifications.schedule(notifications).then(response => {
            console.log(response)
          })

        })

        LocalNotifications.addListener("localNotificationActionPerformed", (notification) => {
          if (this.currentNotification && this.currentNotification.additionalData)
            this.handlePushNotificationData(this.currentNotification.additionalData);
        })

This is not ideal by any means.

selected-pixel-jameson avatar Sep 21 '21 19:09 selected-pixel-jameson

@Jeasmine Can you shed some light on this? It seems like this is directly related to version 3.0 of the One Signal library. It would be really helpful.

selected-pixel-jameson avatar Sep 21 '21 19:09 selected-pixel-jameson

Did you read v3 changes? There is dedicated Foreground Notification Control

czabaj avatar Oct 08 '21 08:10 czabaj

@czabaj Did you read anything beyond the title of this issue?

selected-pixel-jameson avatar Oct 08 '21 12:10 selected-pixel-jameson

nope, sorry, just pass by and try to help. Have no time, you are on your own.

czabaj avatar Oct 08 '21 12:10 czabaj

Hi @selected-pixel-jameson,

Try calling complete within the setNotificationWillShowInForegroundHandler like this:

window.plugins.OneSignal.setNotificationWillShowInForegroundHandler(function(notificationReceivedEvent) {
  notificationReceivedEvent.complete(notificationReceivedEvent.getNotification());
});

Documentation Here

nan-li avatar Oct 15 '21 08:10 nan-li

Hi @selected-pixel-jameson,

Try calling complete within the setNotificationWillShowInForegroundHandler like this:

window.plugins.OneSignal.setNotificationWillShowInForegroundHandler(function(notificationReceivedEvent) {
  notificationReceivedEvent.complete(notificationReceivedEvent.getNotification());
});

Documentation Here

I'm calling exactly like that, but I receive that while debug with Xcode:

2021-11-02 05:15:52.096967-0300 App[6608:1880452] VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler: Fired! testing_this_shit
2021-11-02 05:15:56.111602-0300 App[6608:1880452] ERROR: Notification willShowInForeground completion timed out. Completion was not called within 25.000000 seconds.
2021-11-02 05:15:56.111992-0300 App[6608:1880452] VERBOSE: finishProcessingNotification: Fired!
2021-11-02 05:15:56.112165-0300 App[6608:1880452] VERBOSE: Notification display type: 7
2021-11-02 05:15:56.112572-0300 App[6608:1880452] VERBOSE: notificationReceived called! opened: NO
2021-11-02 05:15:56.113083-0300 App[6608:1880452] VERBOSE: finishProcessingNotification: call completionHandler with options: 7

image

ludufre avatar Nov 02 '21 08:11 ludufre

I have the same problem, I only tested on iOS (iPhone XS, iOS 15.1). I'm on a Capacitor-based project.

With onesignal-cordova-plugin v2.x the default behavior was to display a native alert dialog or to be more explicit:

this.oneSignal.inFocusDisplaying(this.oneSignal.OSInFocusDisplayOption.InAppAlert);

Source: https://documentation.onesignal.com/v7.0/docs/sdk-reference#app-in-focus-notification-display


With onesignal-cordova-plugin v3.x it looks like we should do the following instead:

OneSignal.setNotificationWillShowInForegroundHandler((notificationReceivedEvent) => {
    const notification = notificationReceivedEvent.getNotification();
    notificationReceivedEvent.complete(notification);
});

But no native alert dialog is shown.

Sources:

  • https://documentation.onesignal.com/docs/step-by-step-cordova-2x-to-300-upgrade-guide#step-3-update-initialization-code
  • https://documentation.onesignal.com/docs/cordova-30-api-reference#setnotificationopenedhandler-function

IMPORTANT NOTE: It looks like there are mistakes in the OneSignal documentation. They are "mixing up" setNotificationWillShowInForegroundHandler with setNotificationOpenedHandler.

OneSignal team, please fix this when you have a chance.


WORKAROUND: Use a JavaScript alert or confirm dialog.

OneSignal.setNotificationWillShowInForegroundHandler((notificationReceivedEvent) => {
    const notification = notificationReceivedEvent.getNotification();
    alert(notification.body);
});

nunoarruda avatar Nov 30 '21 17:11 nunoarruda

@nunoarruda In the OneSignal-Cordova-SDK 3.0.0 version the alert dialog style was removed, so only display options that remain from the 2.x.x release are none and notification. The native dialog / alert has limited features which only allow displaying title, body, and action buttons. The work around you posted is a good solution, the OneSignal API for this was designed with this extensibility in mind.

Thanks for the on the documentation, we will correct it soon.

jkasten2 avatar Nov 30 '21 19:11 jkasten2

@selected-pixel-jameson It seems like your issue might be another notifications plugin causing issue with OneSignal. Could you let us know which plugins and versions you are using in your cordova project?

You don't need to call OneSignal.setNotificationWillShowInForegroundHandler at all if you always want a notification to display. This method just allows you to prevent displaying and to read the payload if you choose.

jkasten2 avatar Nov 30 '21 19:11 jkasten2

@ludufre Your setNotificationWillShowInForegroundHandler code looks correct. If you remove setNotificationWillShowInForegroundHandler do the notifications always display then? This the default behavior for OneSignal.

If that does not help could you let us know which plugins and versions you are using in your cordova project?

jkasten2 avatar Nov 30 '21 19:11 jkasten2

@nunoarruda In the OneSignal-Cordova-SDK 3.0.0 version the alert dialog style was removed, so only display options that remain from the 2.x.x release are none and notification. The native dialog / alert has limited features which only allow displaying title, body, and action buttons. The work around you posted is a good solution, the OneSignal API for this was designed with this extensibility in mind.

Thanks for the on the documentation, we will correct it soon.

Hi @jkasten2 thanks for the fast feedback but it is still not clear to me what UI should we expect when we have:

OneSignal.setNotificationWillShowInForegroundHandler((notificationReceivedEvent) => {
    const notification = notificationReceivedEvent.getNotification();
    notificationReceivedEvent.complete(notification);
});

According to the documentation, it should show a notification: Screenshot 2021-11-30 at 18 22 06

But nothing is happening...

Is this "Show Notification" bit referring to a regular push notification UI? Screenshot 2021-11-30 at 18 34 49

If it is, thats not happening either.

nunoarruda avatar Nov 30 '21 19:11 nunoarruda

@nunoarruda The OneSignal-Cordova-SDK 3.0.0 defaults to always showing a notification without the handler. The setNotificationWillShowInForegroundHandler doesn't affect how the notification looks, it is the exact same push notification that is sent.

So in your example, if you want to prevent showing the push notification, and instead show an alert, use this code:

OneSignal.setNotificationWillShowInForegroundHandler((notificationReceivedEvent) => {
    // 1. Display the push as native alert
    const notification = notificationReceivedEvent.getNotification();
    alert(notification.body);

    // 2. Completing the event with null to prevent the push from displaying as a notification.
    //     If you want both to show pass notification instead.
    notificationReceivedEvent.complete(null);
});

jkasten2 avatar Nov 30 '21 21:11 jkasten2

@jkasten2 thanks for the explanation but even without setNotificationWillShowInForegroundHandler the notification does not show up when the app is in the foreground/focus. It's only showing up when the app is closed or in the background. So it looks like the default behavior is not working as expected, that's the issue we're all having here. Can the OneSignal team take a deeper look at this?

nunoarruda avatar Nov 30 '21 21:11 nunoarruda

Changing .complete() to .complete(null) seems to have fixed this issue for me.

jeremywj avatar Dec 01 '21 14:12 jeremywj

I can confirm that this bug only happens on iOS, it works fine on Android.

iOS:

  1. Open your app (so it stays in foreground/focus "mode")
  2. Send a test push notification to your device
  3. No push notification is received (unexpected)

Android:

  1. Open your app (so it stays in foreground/focus "mode")
  2. Send a test push notification to your device
  3. A push notification is received (expected)

I'm using the following workaround in order to have consistent cross-platform functionality:

// When the app is in foreground/focus we should receive regular push notifications by default
// but that's not working on iOS -> https://github.com/OneSignal/OneSignal-Cordova-SDK/issues/733
// So we use this method to silence notifications on Android and show a JavaScript dialog as a workaround
OneSignal.setNotificationWillShowInForegroundHandler((notificationReceivedEvent) => {
    const notification = notificationReceivedEvent.getNotification();

    // Silence notification on Android
    notificationReceivedEvent.complete(null);

    // Show JavaScript alert dialog as workaround
    alert(notification.body);
});

nunoarruda avatar Dec 01 '21 16:12 nunoarruda

@nunoarruda This line

// Silence notification on Android
notificationReceivedEvent.complete(null);

Doesn't just silence the notification on Android it also completely silences the notification on iOS. The OneSignal SDK in this case is passing presentation option None to the following callback:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center 
       willPresentNotification:(UNNotification *)notification 
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;

emawby avatar Feb 02 '22 18:02 emawby

@emawby yeah I know, that code is part of the workaround (temporary solution) I shared in order to have a consistent/cross-browser behavior. The problem is that, even with notificationReceivedEvent.complete(notification), the foreground notification is silent on iOS.

nunoarruda avatar Feb 02 '22 20:02 nunoarruda

I get the same error when migrating to version 3 of OneSignal Cordova SDK. I think I will have no alternative but to implement local notifications at the moment. Since it is important in our flow that the user sees a notification and emits the sound.

KevinToala avatar Feb 23 '22 07:02 KevinToala

me too i'm experiencing the same problem on iOS devices (Android is ok) after migrate my project (Ionic 5.x) from [email protected] + [email protected] to [email protected] + [email protected].

With the app in foreground no notification is shown (but swift plugin and ionic/angular layer print on console the notification details...).

With the app in background the OS shows regularly the notifications.

The strange things is that no one has given satisfactory answers since September, only a workaround (inside app notification).

fabioz23 avatar Mar 26 '22 08:03 fabioz23

Same problem here, i had to implement a hook with ionic toast instead. Wait for a solution...

M9lab avatar Jun 29 '22 15:06 M9lab

This iOS issue is most likely due to another notification SDK / library handling notification display the event and suppressing it.

  • iOS can have multiple foreground notification display handlers (via swizzling) but only one of them can make the this display decision.

Check your Cordova / Ionic project for other SDK / libraries / plugin that also handle notifications. Check for there in focus / foreground setting and also configure them to display the notification in this case.

  • Feel free to list them and their versions if you need additional guidance, the community could help find these settings for the 3rd party plugins.

jkasten2 avatar Jun 30 '22 17:06 jkasten2

I've just noticed this and think I have found a solution. Essentially, I believe the problem stems from Capacitor trying to handle push notifications by default and its default behavior is to just change the badge number. To get it working, I did the following:

  1. Install @capacitor/push-notifications (I installed 1.0.9 as it seems to be the latest one compatible with Capacitor 3)
  2. Configure it to display notifications by adding the following to your capacitor.config.json
  "plugins": {
    "PushNotifications": {
      "presentationOptions": ["alert"]
    }
  }

This should be enough to get everything working. 🥳

gugahoi avatar Aug 26 '22 03:08 gugahoi

I've just noticed this and think I have found a solution. Essentially, I believe the problem stems from Capacitor trying to handle push notifications by default and its default behavior is to just change the badge number. To get it working, I did the following:

  1. Install @capacitor/push-notifications (I installed 1.0.9 as it seems to be the latest one compatible with Capacitor 3)
  2. Configure it to display notifications by adding the following to your capacitor.config.json
  "plugins": {
    "PushNotifications": {
      "presentationOptions": ["alert"]
    }
  }

This should be enough to get everything working. 🥳

Thanks @gugahoi !

Works great with the addition of the following instead:

{
  "plugins": {
    "PushNotifications": {
      "presentationOptions": ["badge", "sound", "alert"]
    }
  }
} 

That way it also makes a sound and adds a badge, with just "alert" it was working but the notifications were silent.

SimonBrazell avatar Nov 06 '22 20:11 SimonBrazell

ings is that no one has given satisfactory answers since September, only a workaround (inside app n

Hi! Can you show me how do you show this toast with the notification when app is in Foreground? Ty!

estebancastrosola avatar Dec 30 '22 18:12 estebancastrosola

Make sure you have this set on your capacitor.config.ts

  ....
  ios: {
    handleApplicationNotifications: false
  },

Seems that capacitor is putting its fingers :eyes:

christiangelone avatar Apr 11 '23 15:04 christiangelone

Make sure you have this set on your capacitor.config.ts

  ....
  ios: {
    handleApplicationNotifications: false
  },

Seems that capacitor is putting its fingers 👀

This! Worked perfectly after I used this suggestion/fix.

jeremywj avatar Apr 21 '23 15:04 jeremywj

Looks like this has been figured out as a Capacitor configuration and resolved since, so I am closing this issue.

nan-li avatar Dec 11 '23 19:12 nan-li