javascript - Firebase Messaging Web getToken 在正常工作 1-2 天后返回过期令牌(无法删除)
问题描述
我有一个 firebase 消息传递服务工作者设置来自定义处理我的 Web 应用程序中的推送通知(数据消息传递),该应用程序使用 messinging.setBackgroundMessageHandler 来处理后台消息。该应用程序在 localhost 中完美运行,但在我的开发服务器上只能运行几个小时或 1-2 天,之后它会停止接收任何通知。
问题是,当我加载页面并调用 firebase messinging.getToken(...) 将其注册到我的服务器时,当在服务器(java firebase admin sdk)上向我刚刚收到的那个令牌发送通知时,那里是这个错误:
com.google.firebase.messaging.FirebaseMessagingException
Requested entity was not found.
此外,如果用户退出应用程序,我会调用 messing.deleteToken(currentToken) 并从服务器注销。但是javascript删除令牌方法不起作用,我收到错误(开发工具浏览器控制台):
DELETE firebase-messaging.js:1 DELETE https://fcmregistrations.googleapis.com/v1/projects/myproject/registrations/[MY_TOKEN] 404
firebase-messaging.js:1 Uncaught (in promise) FirebaseError: Messaging: A problem occured while unsubscribing the user from FCM: FirebaseError: Messaging: A problem occured while unsubscribing the user from FCM: Requested entity was not found. (messaging/token-unsubscribe-failed). (messaging/token-unsubscribe-failed).
at https://www.gstatic.com/firebasejs/7.17.1/firebase-messaging.js:1:24434
所以我什至无法删除 Firebase SDK 实际提供的那个令牌。最终,如果我只是取消注册我的 Service Worker 并刷新页面,我会得到另一个令牌,一切都会再次运行。
我错过了什么?(我有最新的 javascript firebase sdk 7.17.1;我在谷歌上没有发现任何关于这个问题的其他信息)
部分代码如下(有些是用 GWT 编写的,但只有包装部分;与 firebase 的集成是在纯 javascript 中):
首页(窗口客户端):
//initialization in web client is done by calling this method
public final void initialize(String publicKey, FirebaseCallback callback) {
usePublicVapidKey(publicKey);
String context = GWT.getHostPageBaseURL(); //current web context (host + server web context)
init_native(context , "fcm-sw-import.js", callback); // my service worker
}
init_native 函数包含:
var messaging = this
//$wnd is actually "window"
$wnd.navigator.serviceWorker.getRegistrations().then(function(registrations) {
for (i = 0; i < registrations.length; i++) {
if (registrations[i].active && registrations[i].active.scriptURL.includes('fcm-sw-import.js') == false) {
registrations[i].unregister();
console.log ("FCM SW unregistered other service workers: " + registrations[i], registrations[i]);
}
}
});
$wnd.navigator.serviceWorker.register(fcmServiceWorkerJSfile, {scope: '.'})
.then(function(registration) {
registration.update();
messaging.useServiceWorker(registration);
$wnd.navigator.serviceWorker.ready.then(function (registration) {
console.log('FCM SW ready');
//request permissions, get token, register to server, register my callbacks etc.
messaging.@...fcm.FirebaseMessaging::requestPermissionAndRetrieveToken (L...fcm/FirebaseCallback;)(callback);
});
//console.log("SW - registered");
});
请求权限并获取令牌:
var messaging = this;
messaging.requestPermission().then(function() {
messaging.getToken().then(function(currentToken) {
messaging.currentFcmToken = currentToken;
if (currentToken) {
$wnd.navigator.serviceWorker.addEventListener('message', function handler(event) {
....
});
...
}
else {
// Show permission request.
...
// Show permission UI.
...
}
})['catch'](function(err) { //use [catch] so gwt wont think is a keyword
console.log(err);
... on error callback
});
// Callback fired if Instance ID token is updated.
messaging.onTokenRefresh(function() {
messaging.getToken().then(function(refreshedToken) {
var oldToken = messaging.currentFcmToken;
messaging.currentFcmToken = refreshedToken;
...on token refresh callback
})['catch'](function(err) {
});
});
messaging.onMessage(function(payload) {
...
});
})['catch'](function(err) {
...
});
Service Worker是 fcm-sw-import.js:
importScripts('app/fcm-sw-reg.js?v26'); //Production
setupAndInit({
apiKey: ...,
authDomain: ...,
databaseURL: ...,
messagingSenderId: ...,
projectId: ...,
storageBucket: "",
messagingSenderId: ...,
appId: ...
}, '.', "e-cache-v1");
setupAndInit 方法在“fcm-sw-reg.js”中:
importScripts('https://www.gstatic.com/firebasejs/7.17.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.17.1/firebase-messaging.js');
... other imports, vars
function setupAndInit(config, urlContext, cacheName) {
//initialize(config, urlContext);
SENDER_ID = config.messagingSenderId;
urlContextPath = urlContext;
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
const messaging = firebase.messaging();
CACHE_NAME = cacheName;
self.addEventListener('install', function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
logToConsole('SW - Opened cache');
return cache.addAll(urlsToCache);
})
);
self.skipWaiting(); // Activate worker immediately
});
self.addEventListener('activate', function(event) {
self.clients.claim();
});
self.addEventListener('fetch', function(e) {
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});
messaging.setBackgroundMessageHandler(function(payload) {
var wnd = self;
logToConsole('SW - FCM Received fcm background message ', payload);
if (payload.from != SENDER_ID) { //cancel if the sender does not match
return;
}
var data = payload.data;
var notifExporter = new evc.NotificationDetailsExporter(data);
var notifDetails = notifExporter.getNotificationDetails();
var notificationTitle;
var notificationOptions;
if (notifDetails != null) {
var notificationTitle = notifDetails.title;
var iconPath = data.frImLink ? data.frImLink : '';
var text = data.string13 ? data.string13 : "";
var value = data.value ? " - " + data.value : "";
notificationOptions = {
body: notifDetails.message,
icon: iconPath,
data: data
};
}
logToConsole('SW - sending message to wclients...');
clients.matchAll().then(clients => {
clients.forEach(client => {
send_message_to_client(client, {ebasFCM:"true", data: payload.data});
})
})
if (notificationTitle)
return self.registration.showNotification(notificationTitle,
notificationOptions);
else
return null;
});
logToConsole("SW FCM - Initialized FCM worker: " + SENDER_ID + " at: " + urlContextPath);
self.addEventListener('notificationclick', function(event) {
event.waitUntil(clients.matchAll({
includeUncontrolled: true,
type: "window"
}).then(function(clientList) {
logToConsole("SW FCM - Searching client list: ", clientList);
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
logToConsole("SW FCM - Searching client urls: ", client.url);
}
logToConsole("SW FCM - url context path: ", urlContextPath);
logToConsole("SW FCM - notif click event: ", event);
var notifExporter = new evc.NotificationDetailsExporter(event.notification.data);
var toUrl = notifExporter.getNotificationContextUrl();
if (clientList.length) {
if (toUrl)
send_message_to_client(clientList[0], {type: "openUrl", url: toUrl});
return clientList[0].focus();
}
else if (clients.openWindow) {
if (toUrl == null)
toUrl = "";
return clients.openWindow( urlContextPath + toUrl);
}
}));
event.notification.close();
});
logToConsole('SW FCM - Setup fcm done');
}
请指教。谢谢你。
解决方案
推荐阅读
- php - Laravel - 如何按键分组数据并保存到数组?
- ios - UIWindow + 锁屏问题
- c++ - 如何将方法的值保留在类内部的内存中?
- node.js - 使用 fs.writeFile 保存 exe 文件
- javascript - EmberJS 模板组件突然无法在页面上呈现
- c# - `IAuthorizationFilter.ExecuteAuthorizationFilterAsync` 中的延续可以为空吗?
- uml - 如何绘制整个系统的活动图?
- sql - 从 xlsx 文件加载数据后,Oracle 将 varchar / hex 列转换为数字格式
- c# - 如何防止等待被执行?
- node.js - 面对来自 DB2 的频繁连接丢失(使用 ibm_db 版本 - 2.4.1)