flutterfire
flutterfire copied to clipboard
🐛 [firebase_messaging] Silent Notifications not working on iOS if app is terminated
Hello, We already discussed silent notifications on ios in foreground and background mode and I shared our working solution in #8277.
Now above thread is closed, so I’m forced to open this other one.
Situation is:
Android: silent notifications work in all scenarios: app in foreground, background and killed.
ios: silent notifications work in foreground and background mode, but dont work when app is killed IF app is not the last one opened.
Hi @russellwheatley maybe you have more of a clue than me on that?
I can add more details. After upgrading to 12.0.1 from 11.4.1, silent notifications on iOS work also when app is killed. Unfortunately, notifications stop working as soon as we open a different app. If we open our app back and kill it, notifications start working, and they stop working as soon as a different app is opened.
Setup is: iphone 13 iOS 15.5 Flutter 3.0.3
Video below: App is closed and messages are triggered. We open Rest app while keep sending messages, and notifications stop working.
https://user-images.githubusercontent.com/83366073/182945361-341889ed-ed44-4b4a-8c4f-721629938d86.MOV
Hello @darshankawar, any idea about this?
Its simply not ok. It seems like silent push is not working at all. They arrives when opening the app
@iosephmagno
For silent notifications + terminated state combination, according to this documentation section, the data notification in this case will be handled in onBackgroundMessage state, and, the function should be outside the main method to parse it.
Also, see this link for your reference and check if it helps.
Hello @darshankawar Yea our code is fine, in fact notifications work in all states: foreground, background and terminate. We noticed that in terminate mode, notifications stop being fired as soon as we open another app after we killed ours, see here https://github.com/firebase/flutterfire/issues/9300#issuecomment-1205724948
Basically, in above video we kill our app and start sending messages to demonstrate that we do receive and show incoming silent notifications when app is terminated. But at some point we open another app (Rest app) and this causes our terminated app not being able to show incoming silent notifications anymore.
This is why we think it might be a bug of firebase_messaging. Can you please try to reproduce the issue on your side?
Here is our setup:
firebase_messaging: 12.0.1 iphone 13 iOS: 15.5 and 15.6 Flutter: 3.0.3
Notification Sample Payload:
{
admin.messaging().send({
token: "device token",
data: {
"title": "Silent Notification",
"body": "Hello World!",
},
// Set Android priority to "high"
android: {
priority: "high",
},
// Add APNS (Apple) config
apns: {
payload: {
aps: {
contentAvailable: true,
},
},
headers: {
"apns-push-type": "background",
"apns-priority": "5", // Must be 5 when contentAvailable is set to true.
"apns-topic": "com.******.presence", // bundle identifier
},
},
});
ios/runner/AppDelegate.swift
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
ios/runner/Info.plist
<key*>FirebaseAppDelegateProxyEnabled</key*> <string*>NO</string*> <key*>UIBackgroundModes</key*> <array*> <string*>remote-notification</string*> </array*>
@darshankawar @russellwheatley we did other tests today. Pretty sure we discovered a pesky bug.
It is pesky because it can go unnoticed during a test. In fact, if you close app and send some silent notifications, they will be shown as expected.
Unfortunately, they stop showing as soon as user opens different apps on the device. We think some conflicts arise and onBackgroundMessage is not longer triggered.
I thought it best to also add a Feature Request #9317.
Thanks for the update @iosephmagno Based on your comment here: https://github.com/firebase/flutterfire/pull/9292#issuecomment-1207883365, I verified using the changes being made as part of that PR and confirmed that the notifications works in all scenarios, including the one you mentioned, ie, when app is terminated -> notification is sent -> open another app, the notification is received properly. Please see below demo of it:
https://user-images.githubusercontent.com/67046386/183639414-1b985b4e-6187-492d-b0c9-9ab94c815f45.MP4
Hello @darshankawar, what PR are you referring to?
As for your test, I see you are using firebase console to send notifications to your device. This means that maybe you are using “notification” in the payload, not “data-only” silent notifications. Can you double check it?
As mentioned, we have no issues with receiving notifications if we use “notification”. But in that case, we cannot modify payload (eg. decrypt body field) before displaying badge. This is why we asked for the new feature described in #9317.
To recap: silent notifications work in all app states (foreground, background and terminated) and let developers modify the content before displaying head ups. However, due to Apple restrictions, on iOS they might arrive late and are not displayed IF (app is terminated AND app is not the last one opened).
remote notifications work in all app states and always arrive with highest priority. They are the standard for sending sensitive high priority notifications. However, with this type of notification, there is currently no way to modify content before displaying head ups on iOS. To do that, firebase_messaging should support mutable-content and Service App Extension #9317
Hello @darshankawar, what PR are you referring to?
I am referring to https://github.com/firebase/flutterfire/pull/9292 in which you also commented asking if example app is affected by your use case.
This means that maybe you are using “notification” in the payload, not “data-only” silent notifications. Can you double check it?
I also tried with data-only message as below:
[token],
{
data: {
foo:'bar',
},
},
{
// Required for background/terminated app state messages on iOS
contentAvailable: true,
// Required for background/terminated app state messages on Android
priority: 'high',
}
With which it was received properly. The console log shows below:
flutter: A new onMessage event was published!
flutter: Handling a background message 1660117530686122
flutter: Handling a background message 1660117539038217
flutter: Handling a background message 1660117544211027
After terminating app and then sending data-only message:
flutter: A new onMessage event was published!
Lost connection to device.
Below is the video showing the same. You may not see anything happening in UI (except, the device vibrates after receiving data-only message) but the corresponding events are triggered as shown in console.
https://user-images.githubusercontent.com/67046386/183845984-0f094f88-d4b2-4b80-a5e2-75bd5f9fe97f.MP4
I suggest you to try the updated example app changes pushed yesterday to see silent notifications working properly on iOS.
Thanks for the kind assistance!
Which iOS version are you using? Can you add title and body fields, and try to display headup content? Our payload here: https://github.com/firebase/flutterfire/issues/9300#issuecomment-1207826868
Because I already looked at the PR example and there is no difference with our code. Also, Apple confirmed we must use “notification” with “content-mutable” and a service app extention to bypass above restrictions for “data” notifications: “However, due to Apple restrictions, on iOS they might arrive late and are not displayed IF (app is terminated AND app is not the last one opened).”
They also said that, contrary to android, iOS silent notifications might be put on hold temporarily if traffic is huge, and hence are not to be used for instant messaging or apps which send encrypted data with high priority. In that case the solution on iOS is to use mutable-content and service app notifications. Mutable-content tells that notification must not be displayed untill content is passed to the service app notifications (which usually modify content by performing a body-field decryption). This is in the majority of cases the reason why developers want to modify notification content before head up is displayed.
Sample payload: "aps" : { "mutable-content" : 1, "alert" : { "title" : "Notification with encrypted body!", "body" : "(Encrypted)" }, },
https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notifications
For a full coverage of iOS notifications, firebase-mesaging should add support for mutable-content in notification payload and let developers modify notification’s fields before they show head ups through flutter_local_notification, just as we now do with data-only notifications.
Which iOS version are you using?
I am on iOS 15.3.1.
Can you add title and body fields, and try to display headup content?
Yes, added as below:
admin
.messaging()
.sendToDevice(
[token],
{
data: {
title: "Silent Notification",
body: "Hello World",
},
},
{
// Required for background/terminated app state messages on iOS
contentAvailable: true,
// Required for background/terminated app state messages on Android
priority: 'high',
}
)
And then triggered the push event through nodejs which gave me success for each push, with below in console:
flutter: A new onMessage event was published!
flutter: A new onMessage event was published!
The log didn't print because it didn't record when app was terminated.
IOS version is old. Can you use flutter local notifcation to show head up in your video?
Idk what to say, when (app is terminated AND not the last opened one) it doesnt work for us and our code is the same of Russell’s example. Also, it is expected that it doesnt work in such case, because it is Apple restriction. @russellwheatley can you please look into this and shed some light?
Keeping it open and labeling for further insights from the team.
/cc @russellwheatley
Hello, we also noticed the same behaviour
- data only notification are not reliable on ios, 90% of the time it does not trigger background handler when switching app exactly like @iosephmagno mentioned. iOS is also very strict about usage of these silent notifications.
- as silent notification are not reliable on ios, there should be a way to use "notification" in payload and change its layout. Else what's the point to use a third party local notification package with firebase_messaging on iOS if we get duplicates in background (notif+local)
- on Android, everything always worked fine
@scalz yes Apple confirmed that silent notifications are not meant to be used like on android.
To send high priority notifications, iOS requires “notification” and “mutable-content:1”. Firebase messaging should integrate a service app extention to let us modify content before displaying the head up.
https://github.com/firebase/flutterfire/issues/9300#issuecomment-1210349576
I think they are investigating this already.
When will this nonsense end? As far as I understand, there is no solution for this problem for ios, so it is impossible. firebase_messaging is disappointing for me :(
So, when will this be resolved?
i have good news it works in the native side there are bug with firebase_messageing package #9563
@hatemragab 👏 Can you share your discovery in #9536 ?
Hello everyone, we’ve reviewed the issues opened for iOS background messages and we want to make our position clear.
Android and iOS handle background messaging differently. The decision made by the iOS operating system whether messages reaches the relevant iOS event handler (and subsequently received by the Dart background messaging handler) is based on a number of criteria, such as: CPU usage, priority level (data-only messages are considered “low priority” by iOS, android does not), battery level, amount of messages being received by the app, background/terminated application state, etc. This is a fundamental difference between the platforms, and you need to be aware of them when designing your application.
One solution suggested for iOS data-only messages unreliability has been to add a NotificationExtension. But this will still not create parity with Android as you will still have to include a notification with your message (therefore not data-only). It will still render the original notification if you do not update/mutate the notification that comes through the system in a timely manner. We are not currently considering this as a solution due to these limitations.
We also will not support non-FCM messages from third party packages. We specifically only support messages received from the Firebase APIs since we cannot guarantee that messages received from third party packages will not have any unintended side-effects on other Firebase products such as messaging delivery reporting and Analytics data.
To help us triage and locate genuine issues that need to be addressed we have created a specific issue template for iOS background messages. If you believe you still have an issue that needs to be addressed, please create a new issue following this template.
I will be closing this issue in favor of raising a new issue with the new template above. This template will help you provide us with all the information we need to investigate a potential issue with background messaging on iOS.