onMessage:在传入消息上调用两次回调 Flutter web
onMessage: callback called twice on incoming messages Flutter web
在我的应用程序中,对于 Web 版本,我使用包 firebase 7.3.0
用于 Firebase 服务,我现在也在为 Web 设置 FCM。
当我在前台收到应用程序的新消息时,来自 messaging()
的 onMessage:
被触发两次。它也曾经发生在某个 Flutter 版本之前的 flutter_messaging
设备插件,但现在已经解决了。
我基本上设置了一个StreamTransformer
来获取与PlatformPushNotificationDevice
中使用的flutter_messaging
设备包相同类型的Map<String, dynamic>
消息,我使用一个Stub来根据平台切换 classes。
在网络中 class PlatformPushNotificationWeb
我将消息实例化为 var firebaseMessaging = messaging();
并声明我的方法,其中之一是 onMessage()
:
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);
}
因此无论平台如何,我集团中的侦听器都会收到相同的消息类型,
Stream<PushNotificationState> _mapListenToMessagesToState(ListenToMessages event) async* {
print('_mapListenToMessagesToState started');
_pushNotificationSwitcher.onMessage().listen((message) {
print('_mapListenToMessagesToState onMessage() listener: received new message');
add(ReceivedNewMessage(message: message));
});
}
但是对于每条传入的消息,我都会让听众响应两次。
我将 index.html
设置为:
<!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>
和 firebase-messaging-sw.js
文件为:
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)
});
难道是在PlatformPushNotificationWeb
class和firebase-messaging-sw.js
文件中实例化了消息,导致onMessage:
回调被触发了两次?
非常感谢。
事实证明..一个很好的 flutter clean,Android Studio 和机器重启解决了它..
现在我不会收到两次相同的消息,但对于那些真正尝试重复消息的人来说,这将解决问题,不过这只是一种解决方法。
刚刚声明了 int lastMessageId = 0
变量。
当一条消息进来时,对照它检查它的 id
,只有当它们不同时,才将新消息 ID 保存为 lastMessageId
并显示消息。
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));
}
});
}
在我的应用程序中,对于 Web 版本,我使用包 firebase 7.3.0
用于 Firebase 服务,我现在也在为 Web 设置 FCM。
当我在前台收到应用程序的新消息时,来自 messaging()
的 onMessage:
被触发两次。它也曾经发生在某个 Flutter 版本之前的 flutter_messaging
设备插件,但现在已经解决了。
我基本上设置了一个StreamTransformer
来获取与PlatformPushNotificationDevice
中使用的flutter_messaging
设备包相同类型的Map<String, dynamic>
消息,我使用一个Stub来根据平台切换 classes。
在网络中 class PlatformPushNotificationWeb
我将消息实例化为 var firebaseMessaging = messaging();
并声明我的方法,其中之一是 onMessage()
:
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);
}
因此无论平台如何,我集团中的侦听器都会收到相同的消息类型,
Stream<PushNotificationState> _mapListenToMessagesToState(ListenToMessages event) async* {
print('_mapListenToMessagesToState started');
_pushNotificationSwitcher.onMessage().listen((message) {
print('_mapListenToMessagesToState onMessage() listener: received new message');
add(ReceivedNewMessage(message: message));
});
}
但是对于每条传入的消息,我都会让听众响应两次。
我将 index.html
设置为:
<!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>
和 firebase-messaging-sw.js
文件为:
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)
});
难道是在PlatformPushNotificationWeb
class和firebase-messaging-sw.js
文件中实例化了消息,导致onMessage:
回调被触发了两次?
非常感谢。
事实证明..一个很好的 flutter clean,Android Studio 和机器重启解决了它..
现在我不会收到两次相同的消息,但对于那些真正尝试重复消息的人来说,这将解决问题,不过这只是一种解决方法。
刚刚声明了 int lastMessageId = 0
变量。
当一条消息进来时,对照它检查它的 id
,只有当它们不同时,才将新消息 ID 保存为 lastMessageId
并显示消息。
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));
}
});
}