onMessage: callback called twice on incoming messages Flutter web
As it turns out..a good flutter clean, Android Studio and machine restart solved it..
Now I'm not receiving the same message twice, but for those who actually are experimenting duplicate messages this will solve it, dough it's just a workaround.
Just declared int lastMessageId = 0
variable.
When a message comes in, check its id
against it and, only if they're different, save the new message id as lastMessageId
and display the message.
Stream<PushNotificationState> _mapListenToMessagesToState(ListenToMessages event) async* {
print('_mapListenToMessagesToState started');
int lastMessageId = 0;
_pushNotificationSwitcher.onMessage().listen((message) {
print('incoming message is : $message');
var data = message['data'];
int messageId = int.parse(data['id']);
if( lastMessageId != messageId) {
lastMessageId = messageId;
print(
'_mapListenToMessagesToState onMessage() listener: received new message');
add(ReceivedNewMessage(message: message));
}
});
}
Vincenzo
At age of 40 an accident forced me in bed for a few months and I realised that I wanted point my life in a different direction to really fulfil my purpose in life, help others and help making this planet a better place. I love to create stuff and I constantly have perhaps too many ideas. I'm now launching a bicycle related start-up. I got back into coding after 25 years away from it as it was a fundamental skill to get updated to get the project started and since then I'm working on the start-up's products. I first learned Swift as it seemed the easiest language I could learn at fast pace, but when Apple created SwiftUI framework ( Flutter copycat A.F.A.I.K ) I decided to move away from Swift the obvious choice has been learning Flutter ( the original ). So happy I made the transition and I'm not looking back.
Updated on December 24, 2022Comments
-
Vincenzo over 1 year
In my app, for the web version, I use package
firebase 7.3.0
for Firebase services and I'm now setting up FCM for web too. When I get a new message with the app in foreground theonMessage:
frommessaging()
gets triggered twice. It also used to happen for theflutter_messaging
device plugin prior to a certain Flutter version but is now solved.I basically set a
StreamTransformer
to get the message in the same type ofMap<String, dynamic>
as theflutter_messaging
device package used inPlatformPushNotificationDevice
, I use a Stub to switch classes depending on the platform. In the web classPlatformPushNotificationWeb
I instantiate messaging asvar firebaseMessaging = messaging();
and declare my methods, one of which isonMessage()
:Stream<Map<String, dynamic>> onMessage() async* { print('PlatformPushNotificationWeb.onMessage() started'); handleData(Payload payload, EventSink<Map<String, dynamic>> sink) { Map<String,dynamic> message = { 'notification': { 'title': payload.notification.title, 'body': payload.notification.body, 'sound': true }, 'data': payload.data }; sink.add(message); } final transformer = StreamTransformer<Payload, Map<String, dynamic>>.fromHandlers( handleData: handleData); yield* firebaseMessaging.onMessage.transform(transformer); }
so the listener in my bloc will receive the same message type no matter the platform,
Stream<PushNotificationState> _mapListenToMessagesToState(ListenToMessages event) async* { print('_mapListenToMessagesToState started'); _pushNotificationSwitcher.onMessage().listen((message) { print('_mapListenToMessagesToState onMessage() listener: received new message'); add(ReceivedNewMessage(message: message)); }); }
but for every incoming message I get the listener responding twice.
I set the
index.html
as:<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>fixit cloud biking</title> <!-- <meta name="google-signin-client_id" content="YOUR_GOOGLE_SIGN_IN_OAUTH_CLIENT_ID.apps.googleusercontent.com">--> <meta name="google-signin-client_id" content="xxxx.apps.googleusercontent.com"> <!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">--> </head> <!--<body>--> <body id="app-container"> <script src="main.dart.js?version=45" type="application/javascript"></script> <!-- The core Firebase JS SDK is always required and must be listed first --> <script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-app.js"></script> <!-- TODO: Add SDKs for Firebase products that you want to use https://firebase.google.com/docs/web/setup#available-libraries --> <script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-auth.js"></script> <script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-analytics.js"></script> <script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-messaging.js"></script> <script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-storage.js"></script> <script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-database.js"></script> <script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-remote-config.js"></script> <script> if ("serviceWorker" in navigator) { window.addEventListener("load", function () { //navigator.serviceWorker.register("/flutter_service_worker.js"); navigator.serviceWorker.register("/firebase-messaging-sw.js"); }); } </body> </html>
and the
firebase-messaging-sw.js
file as :importScripts("https://www.gstatic.com/firebasejs/7.19.1/firebase-app.js"); importScripts("https://www.gstatic.com/firebasejs/7.19.1/firebase-messaging.js"); firebase.initializeApp({ apiKey: "xxxx", authDomain: "xxxx", databaseURL: "xxxx", projectId: "xxx", storageBucket: "xxxx", messagingSenderId: "xxxx", appId: "xxx", measurementId: "G-xxxx", }); const messaging = firebase.messaging(); messaging.setBackgroundMessageHandler(function (payload) { console.log('[firebase-messaging-sw.js] Received background message ', payload); const promiseChain = clients .matchAll({ type: "window", includeUncontrolled: true }) .then(windowClients => { for (let i = 0; i < windowClients.length; i++) { const windowClient = windowClients[i]; windowClient.postMessage(payload); } }) .then(() => { return registration.showNotification("New Message"); }); return promiseChain; }); self.addEventListener('notificationclick', function (event) { console.log('notification received: ', event) });
Could it be that instantiating messaging in the
PlatformPushNotificationWeb
class and in thefirebase-messaging-sw.js
file the reason ofonMessage:
callback being triggered twice? Many thanks.