OneSignal / OneSignal-Cordova-SDK

OneSignal is a free push notification service for mobile apps. This plugin makes it easy to integrate your Ionic, PhoneGap CLI, PhoneGap Build, Cordova, or Sencha Touch app with OneSignal. Supports Android, iOS, and Amazon's Fire OS platforms. https://onesignal.com
Other
251 stars 197 forks source link

Notifications Are Not Received when iOS App is in Foreground #733

Closed selected-pixel-jameson closed 10 months ago

selected-pixel-jameson commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

czabaj commented 3 years ago

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

selected-pixel-jameson commented 3 years ago

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

czabaj commented 3 years ago

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

nan-li commented 2 years ago

Hi @selected-pixel-jameson,

Try calling complete within the setNotificationWillShowInForegroundHandler like this:

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

Documentation Here

ludufre commented 2 years ago

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

nunoarruda commented 2 years ago

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:

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);
});
jkasten2 commented 2 years ago

@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 commented 2 years ago

@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 commented 2 years ago

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

nunoarruda commented 2 years ago

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

jkasten2 commented 2 years ago

@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);
});
nunoarruda commented 2 years ago

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

jeremywj commented 2 years ago

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

nunoarruda commented 2 years ago

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);
});
emawby commented 2 years ago

@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;
nunoarruda commented 2 years ago

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

KevinToala commented 2 years ago

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.

fabioz23 commented 2 years ago

me too i'm experiencing the same problem on iOS devices (Android is ok) after migrate my project (Ionic 5.x) from capacitor@2.5.0 + onesignal-cordova-plugin@2.11.4 to capacitor@3.4.3 + onesignal-cordova-plugin@3.0.2.

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

M9lab commented 2 years ago

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

jkasten2 commented 2 years ago

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

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.

gugahoi commented 2 years ago

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

SimonBrazell commented 1 year ago

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.

estebancastrosola commented 1 year ago

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!

christiangelone commented 1 year ago

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

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

Seems that capacitor is putting its fingers :eyes:

jeremywj commented 1 year ago

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.

nan-li commented 10 months ago

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