首页 > 解决方案 > 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');
}

请指教。谢谢你。

标签: javascriptfirebasefirebase-cloud-messagingservice-worker

解决方案


推荐阅读