flutterfire
flutterfire copied to clipboard
π [firebase_messaging] Web doesn't show notifications when the tab is covered by other windows
fireabase_messaging_web only shows notifications if the tab is closed or the user switches to a different tab.
This means the user doesn't get notifications when
- User switches to another OS window but leaves the tab open
- User switches to another chrome window but leaves the tab open
- The website is Added to the home screen and is running in the background
What's also weird is that in this case, the FirebaseMessaging.onMessage
event is fired.
This means there's no way to differentiate it from when the tab is active and in user's focus -- can't correct this using the onMessage
/ onBackgroundMessage
handlers then.
Since our users don't seem to close tabs & use the A2HS feature too, it seems like there's no way to implement reliable notifications on the web via firebase.
If we look at how WhatsApp web works, it won't show you notifications if you're using the website. But as soon as you switch away to another app, it shows you notifications. Can the same behaviour be replicated using firebase_messaing?
@devxpy We have not found a way to communicate with the Flutter app from the background, which is why you might be seeing the behavior. We have documented the workaround here for web applications, and we will update the documentation once we have a solution.
Based on above explaination, the link and current limitation, I am going ahead and closing this for now. If you disagree, write in comments and I'll reopen it.
I am aware of this limitation. However, as described in the original post, the onBackgroundMessage
(even the JS worker one) does NOT get called when the tab is still active but covered by other OS windows.
I donβt think the above article covers this case, hence urge you to repoen this ticket. Thanks!
Thanks for the feedback. Reopening.
@devxpy
Can you provide flutter doctor -v
, plugin version along with complete minimal reproducible code sample and steps to replicate that we can use to debug this behavior further ?
[β] Flutter (Channel stable, 2.10.5, on macOS 12.4 21F79 darwin-arm, locale en-IN)
β’ Flutter version 2.10.5 at /Users/dev/Tools/flutter
β’ Upstream repository https://github.com/flutter/flutter.git
β’ Framework revision 5464c5bac7 (9 weeks ago), 2022-04-18 09:55:37 -0700
β’ Engine revision 57d3bac3dd
β’ Dart version 2.16.2
β’ DevTools version 2.9.2
[β] Android toolchain - develop for Android devices (Android SDK version 31.0.0-rc3)
β’ Android SDK at /Users/dev/Library/Android/sdk
β’ Platform android-31, build-tools 31.0.0-rc3
β’ Java binary at: /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/bin/java
β’ Java version OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_275-b01)
β’ All Android licenses accepted.
[β] Xcode - develop for iOS and macOS (Xcode 13.2.1)
β’ Xcode at /Applications/Xcode.app/Contents/Developer
β’ CocoaPods version 1.11.3
[β] Chrome - develop for the web
β’ Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[!] Android Studio (not installed)
β’ Android Studio not found; download from https://developer.android.com/studio/index.html
(or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
[β ] IntelliJ IDEA Ultimate Edition (the doctor check crashed)
β Due to an error, the doctor check did not complete. If the error message below is not helpful, please let us know about this issue at https://github.com/flutter/flutter/issues.
β FormatException: Unexpected extension byte (at offset 5)
β’ #0 _Utf8Decoder.convertSingle (dart:convert-patch/convert_patch.dart:1789:7)
#1 Utf8Decoder.convert (dart:convert/utf.dart:351:42)
#2 InputStream.readString (package:archive/src/util/input_stream.dart:207:30)
#3 new ZipDirectory.read (package:archive/src/zip/zip_directory.dart:40:30)
#4 ZipDecoder.decodeBuffer (package:archive/src/zip_decoder.dart:19:30)
#5 ZipDecoder.decodeBytes (package:archive/src/zip_decoder.dart:14:12)
#6 IntelliJPlugins._findPluginXml (package:flutter_tools/src/intellij/intellij.dart:130:44)
#7 IntelliJPlugins._readPackageVersion (package:flutter_tools/src/intellij/intellij.dart:141:40)
#8 IntelliJPlugins.validatePackage (package:flutter_tools/src/intellij/intellij.dart:63:35)
#9 IntelliJValidator.validate (package:flutter_tools/src/intellij/intellij_validator.dart:103:15)
#10 asyncGuard.<anonymous closure> (package:flutter_tools/src/base/async_guard.dart:111:32)
#11 asyncGuard.<anonymous closure> (package:flutter_tools/src/base/async_guard.dart:109:18)
#12 _rootRun (dart:async/zone.dart:1426:13)
#13 _CustomZone.run (dart:async/zone.dart:1328:19)
#14 _runZoned (dart:async/zone.dart:1861:10)
#15 runZonedGuarded (dart:async/zone.dart:1849:12)
#16 runZoned (dart:async/zone.dart:1780:12)
#17 asyncGuard (package:flutter_tools/src/base/async_guard.dart:109:3)
#18 Doctor.startValidatorTasks (package:flutter_tools/src/doctor.dart:205:9)
#19 Doctor.diagnose (package:flutter_tools/src/doctor.dart:309:47)
#20 DoctorCommand.runCommand (package:flutter_tools/src/commands/doctor.dart:50:48)
#21 FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:1320:12)
<asynchronous suspension>
#22 FlutterCommand.run.<anonymous closure> (package:flutter_tools/src/runner/flutter_command.dart:1161:27)
<asynchronous suspension>
#23 AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
<asynchronous suspension>
#24 CommandRunner.runCommand (package:args/command_runner.dart:209:13)
<asynchronous suspension>
#25 FlutterCommandRunner.runCommand.<anonymous closure> (package:flutter_tools/src/runner/flutter_command_runner.dart:281:9)
<asynchronous suspension>
#26 AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
<asynchronous suspension>
#27 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:229:5)
<asynchronous suspension>
#28 run.<anonymous closure>.<anonymous closure> (package:flutter_tools/runner.dart:62:9)
<asynchronous suspension>
#29 AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
<asynchronous suspension>
#30 main (package:flutter_tools/executable.dart:94:3)
<asynchronous suspension>
[β] IntelliJ IDEA Ultimate Edition (version 2021.3.2)
β’ IntelliJ at /Users/dev/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/213.6777.52/IntelliJ IDEA.app
β’ Flutter plugin can be installed from:
π¨ https://plugins.jetbrains.com/plugin/9212-flutter
β’ Dart plugin can be installed from:
π¨ https://plugins.jetbrains.com/plugin/6351-dart
[β] VS Code (version 1.56.2)
β’ VS Code at /Applications/Visual Studio Code.app/Contents
β’ Flutter extension version 3.22.0
[β] Connected device (2 available)
β’ macOS (desktop) β’ macos β’ darwin-arm64 β’ macOS 12.4 21F79 darwin-arm
β’ Chrome (web) β’ chrome β’ web-javascript β’ Google Chrome 102.0.5005.115
! Error: iPad is not connected. Xcode will continue when iPad is connected. (code -13)
[β] HTTP Host Availability
β’ All required HTTP hosts are available
! Doctor found issues in 2 categories.
firebase-messaging-sw.js
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in
// your app's Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
apiKey: 'api-key',
authDomain: 'project-id.firebaseapp.com',
databaseURL: 'https://project-id.firebaseio.com',
projectId: 'project-id',
storageBucket: 'project-id.appspot.com',
messagingSenderId: 'sender-id',
appId: 'app-id',
measurementId: 'G-measurement-id',
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
messaging.onBackgroundMessage((payload) => {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
});
Repro steps -
- Open webpage
- Open console
- Switch (cmd+tab) to another app
- Send a notification from firebase console / Server SDK
Observed behaviour -
- Notice you don't see any notification or any log in the console
Expected behavior -
- See a log in the console from the
onBackgroundMessage
handler - See a notification from the browser
Notes -
- Before step (3), if you close or change the tab, you get the expected behavior
Thanks for the update. Using above code and steps to replicate, I do see the same behavior as reported, although, as mentioned the onBackgroundMessage (even the JS worker one) does NOT get called when the tab is still active but covered by other OS windows.
, this could be a limitation from browser / chrome itself which is why the current behavior.
Also, https://github.com/firebase/flutterfire/issues/8931#issuecomment-1160353683 for reference.
/cc @russellwheatley
That limitation does not seem to be there on the native web push API.
While playing around with this I discovered that even if you manually show a notification using the onMessage
handler, there's no way to reliably implement onclick behaviour (e.g. page reloaded after showing notification), because onMessage
gets triggered only from the top-level JS context, not the service worker context.
Couldn't find a solution to this problem?
Can use the BroadcastChannel API to communicate between different documents (in different windows, tabs, frames or iframes) of the same origin. I implement it on TwakeMail project and it was successful. See morehere