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

[Bug]: iOS - App in foreground: no Event fired, no Push displayed #943

Closed
2 of 3 tasks
louis123562 opened this issue Dec 4, 2023 · 18 comments
Closed
2 of 3 tasks

Comments

@louis123562
Copy link

louis123562 commented Dec 4, 2023

What happened?

I migrated from Cordova to Capacitor and updated this plugin to the version ^5.0.3
On iOS, i do get Push Notifications only, when the App is not in focus or my device (iphone, ipad) is locked.

I tried to catch the event "foregroundWillDisplay" when the App is opened, but that does not work great...
It turns out, that the event does get fired, but displaying the notification with event.notification.display() from the examples does not work.

code fragments

initialize OneSignal Plugin

  async initializeOneSignal() {

    // Uncomment to set OneSignal device logging to VERBOSE  
    OneSignal.Debug.setLogLevel(6);

    // NOTE: Update the init value below with your OneSignal AppId.
    OneSignal.initialize("my-app-key");

  }

Add Event Listeners

  async addEventListeners() {

    let myClickListener = async function (event) {
      let notificationData = JSON.stringify(event);
      console.log("push notification was clicked");
      console.log(notificationData);
    };

    let myChangeListener = async function (event) {
      let notificationData = JSON.stringify(event);
      console.log("subscription state changed");
      console.log(notificationData);
    };

    let permissionChangedListener = async function (event) {
      let notificationData = JSON.stringify(event);
      console.log("permission changed", notificationData);
    };

    let myLifecyleListener = function (event) {

      /// Display Notification, preventDefault to not display
      event.preventDefault();

      // Use notification.display() to display the notification after some async work
      event.notification.display();
    }

    OneSignal.Notifications.addEventListener("permissionChange", permissionChangedListener);
    OneSignal.Notifications.addEventListener("click", myClickListener);
    OneSignal.Notifications.addEventListener("foregroundWillDisplay", myLifecyleListener);
    OneSignal.User.pushSubscription.addEventListener("change", myChangeListener);

  }

Initialize in app.component.ts

  async initializePushNotification() {
    await this.pushService.initializeOneSignal();
    await this.pushService.addEventListeners();
  }

JSON for the API Call to trigger Push

{
	"app_id": "app-id",
	"include_subscription_ids": [
		"id-from-my-app"
	],
	"contents": {
		"en": "body",
		"de": "body"
	},
	"subtitle": {
		"en": "subtitle",
		"de": "subtitle"
	},
	"headings": {
		"en": "heading",
		"de": "heading"
	},
	"small_icon": "locales\/android\/drawable-mdpi\/ic_stat_onesignal_default.png",
	"huawei_small_icon": "locales\/android\/drawable-mdpi\/ic_stat_onesignal_default.png",
	"large_icon": "locales\/android\/drawable-mdpi\/ic_stat_onesignal_default.png",
	"huawei_large_icon": "locales\/android\/drawable-mdpi\/ic_stat_onesignal_default.png"
}

When i send a push message via API, the event does get fired, but even here, no "banner" or "toast" is displayed. Instead, i get the following in console:

VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler:
VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler: Fired! body
VERBOSE: OSNotificationWillDisplayEvent.preventDefault called.

And after 25 seconds i get:

WARNING: OSNotificationLifecycleListener:onWillDisplayNotification timed out. Display was not called within 25.000000 seconds. Continue with display notification: 0
VERBOSE: finishProcessingNotification: Fired!
VERBOSE: Notification display type: 0
VERBOSE: notificationReceived called! opened: NO
VERBOSE: finishProcessingNotification: call completionHandler with options: 0

In system settings, the proper settings are set to receive push and show banners.

Steps to reproduce?

This is the package.json i use (please don't blame for using moment):

{
  "name": "myApp",
  "version": "0.0.1",
  "author": "Ionic Framework",
  "homepage": "https://ionicframework.com/",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "release": "ng build --configuration production",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "dev": "npm run build && npx cap copy"
  },
  "private": true,
  "dependencies": {
    "@angular-devkit/architect": "^0.1202.14",
    "@angular/common": "^14.0.0",
    "@angular/core": "^14.0.0",
    "@angular/forms": "^14.0.0",
    "@angular/platform-browser": "^14.0.0",
    "@angular/platform-browser-dynamic": "^14.0.0",
    "@angular/router": "^14.0.0",
    "@byteowls/capacitor-oauth2": "^5.0.0",
    "@capacitor-community/barcode-scanner": "^4.0.1",
    "@capacitor-community/file-opener": "^1.0.5",
    "@capacitor/android": "5.3.0",
    "@capacitor/app": "^5.0.6",
    "@capacitor/browser": "^5.0.6",
    "@capacitor/clipboard": "^5.0.6",
    "@capacitor/core": "5.3.0",
    "@capacitor/device": "^5.0.6",
    "@capacitor/filesystem": "^5.1.3",
    "@capacitor/geolocation": "^5.0.6",
    "@capacitor/haptics": "^5.0.6",
    "@capacitor/ios": "5.3.0",
    "@capacitor/keyboard": "^5.0.6",
    "@capacitor/splash-screen": "^5.0.6",
    "@capacitor/status-bar": "^5.0.6",
    "@fortawesome/angular-fontawesome": "^0.10.1",
    "@fortawesome/fontawesome-svg-core": "^6.1.0",
    "@fortawesome/free-brands-svg-icons": "^6.1.0",
    "@fortawesome/pro-duotone-svg-icons": "^6.1.0",
    "@fortawesome/pro-light-svg-icons": "^6.1.0",
    "@fortawesome/pro-regular-svg-icons": "^6.1.0",
    "@fortawesome/pro-solid-svg-icons": "^6.1.0",
    "@ionic/angular": "^7.5.4",
    "@ionic/core": "^7.5.4",
    "@ionic/storage-angular": "^4.0.0",
    "@ngx-translate/core": "^14.0.0",
    "@types/onesignal-cordova-plugin": "^2.6.5",
    "hammerjs": "^2.0.8",
    "moment": "^2.29.1",
    "ng2-pdf-viewer": "^9.1.0",
    "ngx-extended-pdf-viewer": "^15.0.0-alpha.0",
    "ngx-translate-multi-http-loader": "^9.3.0",
    "onesignal-cordova-plugin": "^5.0.3",
    "rxjs": "^7.8.1",
    "rxjs-compat": "^6.6.7",
    "swiper": "^11.0.4",
    "tslib": "^2.3.1",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~14.0.0",
    "@angular-eslint/builder": "~14.0.0",
    "@angular-eslint/eslint-plugin": "~14.0.0",
    "@angular-eslint/eslint-plugin-template": "~14.0.0",
    "@angular-eslint/template-parser": "~14.0.0",
    "@angular/cli": "~14.0.0",
    "@angular/compiler": "^14.0.0",
    "@angular/compiler-cli": "^14.0.0",
    "@angular/language-service": "~14.0.0",
    "@capacitor/assets": "^2.0.4",
    "@capacitor/cli": "5.3.0",
    "@ionic/angular-toolkit": "^6.0.0",
    "@types/jasmine": "~3.6.0",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^13.0.0",
    "@typescript-eslint/eslint-plugin": "4.16.1",
    "@typescript-eslint/parser": "4.16.1",
    "eslint": "^7.6.0",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-jsdoc": "30.7.6",
    "eslint-plugin-prefer-arrow": "1.2.2",
    "jasmine-core": "~3.8.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "^6.3.9",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "typescript": "~4.6"
  },
  "description": "An Ionic project"
}

What did you expect to happen?

I do expect when the App is in foreground, either with the eventListener for "foregroundWillDisplay" or without, there should be a notification shown to the user. When i was using Cordova, the push notification was always shown, independent in what state the App was.

OneSignal Cordova SDK version

^5.0.3

Which platform(s) are affected?

  • iOS
  • Android

Relevant log output

VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler:
VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler: Fired! body
VERBOSE: OSNotificationWillDisplayEvent.preventDefault called.
WARNING: OSNotificationLifecycleListener:onWillDisplayNotification timed out. Display was not called within 25.000000 seconds. Continue with display notification: 0
VERBOSE: finishProcessingNotification: Fired!
VERBOSE: Notification display type: 0
VERBOSE: notificationReceived called! opened: NO
VERBOSE: finishProcessingNotification: call completionHandler with options: 0

Code of Conduct

  • I agree to follow this project's Code of Conduct
@louis123562
Copy link
Author

I want to note, that the "foregroundWillDisplay" callback only gets executed once... so its super hard to display multiple e.g. alerts / toasts on your own in a single session.

@dszczudlo
Copy link

I can confirm the behavior. Unfortunately, in foreground mode there is no option to execute another reaction when a push comes.

@nan-li
Copy link
Contributor

nan-li commented Dec 7, 2023

Hi @louis123562, thanks for reporting.

I am clarifying the information you shared.

  1. When you do not use OneSignal.Notifications.addEventListener("foregroundWillDisplay", func) at all, the notification is still not displayed in the foreground? Can you share logs from this scenario? It should be displayed with no event listener.
  2. When you do use OneSignal.Notifications.addEventListener("foregroundWillDisplay", func), what happens if you do not call event.preventDefault(), and just log the event?
  3. Can you explain your comment: "I want to note, that the "foregroundWillDisplay" callback only gets executed once... so its super hard to display multiple e.g. alerts / toasts on your own in a single session"? The callback should be triggered once for each event.

The logs you shared look like event.notification.display() is not having an effect. VERBOSE: OSNotificationWillDisplayEvent.preventDefault called. is logged when preventDefault() is called. Then it waits 25 seconds for the developer to call display(). If display() is not called, then it times out and does not display the notification.

Hi @dszczudlo, is there any additional information you can share to reproduce the issue?

@dszczudlo
Copy link

dszczudlo commented Dec 7, 2023 via email

@louis123562
Copy link
Author

Hello @nan-li,

below my answers to your clarification potins.

Answer to 1.

With // OneSignal.Notifications.addEventListener("foregroundWillDisplay", myLifecyleListener); (commented out), this is the output from xCode:

VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler:
VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler: Fired! body
VERBOSE: finishProcessingNotification: Fired!
VERBOSE: Notification display type: 7
VERBOSE: notificationReceived called! opened: NO
VERBOSE: finishProcessingNotification: call completionHandler with options: 7

I do not see anything on my iPad or on my iPhone that looks like a notification and there is no notification sound.

Answer to 2.

With only console.log(event); in the callback, a fresh app start and then an API call, i get the following in xCode:

VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler:
VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler: Fired! body
VERBOSE: OSNotificationWillDisplayEvent.preventDefault called.
To Native Cordova ->  ⚡️  [log] - {"notification":{"notificationId":"291730fe-a2c9-4f1a-a220-3073d4007ade","body":"body","title":"heading","rawPayload":{"aps":{"alert":{"subtitle":"subtitle","title":"heading","body":"body"},"mutable-content":1,"sound":"default"},"custom":{"i":"291730fe-a2c9-4f1a-a220-3073d4007ade"}},"sound":"default","actionButtons":[],"subtitle":"subtitle","mutableContent":true}}
OneSignalPush proceedWithWillDisplay OneSignalPush387111720 ["options": [291730fe-a2c9-4f1a-a220-3073d4007ade]]
VERBOSE: finishProcessingNotification: Fired!
VERBOSE: Notification display type: 7
VERBOSE: notificationReceived called! opened: NO
VERBOSE: finishProcessingNotification: call completionHandler with options: 7

When sending another push via API, i get this output:

VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler:
VERBOSE: onesignalUserNotificationCenter:willPresentNotification:withCompletionHandler: Fired! body
VERBOSE: OSNotificationWillDisplayEvent.preventDefault called.

And a few seconds later:

WARNING: OSNotificationLifecycleListener:onWillDisplayNotification timed out. Display was not called within 25.000000 seconds. Continue with display notification: 0
VERBOSE: finishProcessingNotification: Fired!
VERBOSE: Notification display type: 0
VERBOSE: notificationReceived called! opened: NO
VERBOSE: finishProcessingNotification: call completionHandler with options: 0

Answer to 3.

Thats what i mean with "my callback only gets executed once". This ouput

WARNING: OSNotificationLifecycleListener:onWillDisplayNotification timed out. Display was not called within 25.000000 seconds. Continue with display notification: 0
VERBOSE: finishProcessingNotification: Fired!
VERBOSE: Notification display type: 0
VERBOSE: notificationReceived called! opened: NO
VERBOSE: finishProcessingNotification: call completionHandler with options: 0

repeats on every following push i send via API. Only after a fresh app start, the first time a push hits the device, the callback gets executed. After that one - only the same garbage and NO callback execution.

Calling display() has no effect at all. Everything remains the same - no visible appearance, no change in the log outputs.

It would be very great if we can fix this issue; otherwise i will be forced to switch to another provider.

@dszczudlo
Copy link

@louis123562
If you want to see the push messages in foreground mode, you can try to change change/add this in the capacitor config file. It works for me.

"ios": {
"handleApplicationNotifications": false
},

But unfortunately the problem you described with the eventListender "foregroundWillDisplay" still exists.
In a previous version that I used from onesignal for ionic, there was the "onReceived" event. So I reloaded the data of my APP as soon as a push message arrived. It would also be possible with the eventListender "foregroundWillDisplay", but it stops working after the first push message arrived.
I can confirm the behavior with the eventListender foregroundWillDisplay that you described.

@nan-li
Copy link
Contributor

nan-li commented Dec 7, 2023

Hi all, thanks for your responses, I will investigate the behavior of foregroundWillDisplay that is reported.

As for notifications not displaying in the foreground, that's right, I do recall now there was an issue with Capacitor and needing to override foregroundWillDisplay in configurations.

So now, the only problem is with the foregroundWillDisplay listener, correct?

@dszczudlo
Copy link

Hi @nan-li , for me it would be great if the eventListener foregroundWillDisplay would work.

@louis123562
Copy link
Author

Hey @nan-li,

i can confirm that, with

  ios: {
    handleApplicationNotifications: false
  },

in capacitor.config AND the callback for foregroundWillDisplay not registered, push notifications / OS toasts are displayed when the app is in foreground - GREAT! That little option for the capacitor config should be mentioned in the OneSignal docs.

When i register the callback for the foregroundWillDisplay event, calling inside of it event.preventDefault() and / or event.getNotification().display(), no toast is shown, no console.log(event) appears (console.log output ONLY first time).

So yeah, your assumption, that the only problem is foregroundWillDisplay, is correct.

@nan-li
Copy link
Contributor

nan-li commented Dec 11, 2023

Thanks @louis123562 for the feedback, we updated our Capacitor setup docs with a callout about handleApplicationNotifications.

I will continue to investigate and reproduce the foreground display issue you are both seeing.

@Brainiac-88
Copy link

Dear all,
I can confirmthat the "foregroundWillDisplay" not working on Android side too.
The event is not fire, The "click" is working well.
So is there any event to handle notification event when the app is in foreground?
Thank You.

@TobiTobsn007
Copy link

Hi I also have the problem, that the foregroundWillDisplay event only fires once. :-(
Hope there is a solution soon.

@KennyLibaro
Copy link

Hello,
I'm also facing the same issue that foregroundWillDisplay only fires one time. I don't actually need to display the notification when it is received in the foreground, but I do need to know when I receive multiple.
Thanks for looking into the issue and hope there is a fix for this soon.

@nan-li
Copy link
Contributor

nan-li commented Dec 27, 2023

Hi everyone, thanks for your continued comments.
I am able to reproduce on a Capacitor project and am working to resolve the issue.

@nan-li
Copy link
Contributor

nan-li commented Jan 31, 2024

Hi everyone, thank you for your patience.
We released the fix in Release 5.0.5.

Please update and reach out if you are still seeing any issues. Thank you!

@nan-li nan-li closed this as completed Jan 31, 2024
@louis123562
Copy link
Author

Hi everyone, thank you for your patience. We released the fix in Release 5.0.5.

Please update and reach out if you are still seeing any issues. Thank you!

Mmhm... i just tested 5.0.5 and i dont see any difference in the behaviour.
foregroundWillDisplay still only gets fired once and not on subsequent pushes.

I also still see

WARNING: OSNotificationLifecycleListener:onWillDisplayNotification timed out. Display was not called within 25.000000 seconds. Continue with display notification: 0

but in my code, i do call it:

    const myLifecyleListener = async (event: NotificationWillDisplayEvent) => {

      /// Display Notification, preventDefault to not display
      event.preventDefault();

      console.log("NotificationWillDisplayEvent FIRED!!!");
      console.log(event);

      //Do something...

      //even time-shifting does not help :(
      setTimeout(() => {
        // Use notification.display() to display the notification after some async work
        event.getNotification().display();
      }, 2000);


    }

    OneSignal.Notifications.addEventListener("foregroundWillDisplay", myLifecyleListener);

@KennyLibaro
Copy link

Hi everyone, thank you for your patience. We released the fix in Release 5.0.5.
Please update and reach out if you are still seeing any issues. Thank you!

Mmhm... i just tested 5.0.5 and i dont see any difference in the behaviour. foregroundWillDisplay still only gets fired once and not on subsequent pushes.

I also still see

WARNING: OSNotificationLifecycleListener:onWillDisplayNotification timed out. Display was not called within 25.000000 seconds. Continue with display notification: 0

but in my code, i do call it:

    const myLifecyleListener = async (event: NotificationWillDisplayEvent) => {

      /// Display Notification, preventDefault to not display
      event.preventDefault();

      console.log("NotificationWillDisplayEvent FIRED!!!");
      console.log(event);

      //Do something...

      //even time-shifting does not help :(
      setTimeout(() => {
        // Use notification.display() to display the notification after some async work
        event.getNotification().display();
      }, 2000);


    }

    OneSignal.Notifications.addEventListener("foregroundWillDisplay", myLifecyleListener);

Hi,

Weird, for me after updating to 5.0.5 everything works as expected:

  • triggers multiple times
  • preventDefault() -> prevents the notification from being shown
  • event.getNotification().display() -> will display the notification after a preventDefault

That being said, I don't see anything wrong with your code though.
Maybe best to try uninstalling the package completely and reinstalling it?

@louis123562
Copy link
Author

yeah, now it works for me, too :)

I removed my node_modules, package.json.lock, and the iOS platform folder, reinstalled node modules and added the platform again.

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

No branches or pull requests

6 participants