Firebase通知显示两次,如果在不同的选项卡或浏览器上最小化

时间:2017-11-23 05:40:42

标签: angularjs firebase push-notification firebase-notifications

我正在使用Google的firebase在浏览器中进行通知,这种方式非常正常。 如果我在特定选项卡中订阅通知,然后我更改选项卡或最小化浏览器,我会看到两个通知实例,如果收到任何通知,我只会遇到问题。

我无法弄清楚这个问题。我正在使用angular 1.5和firebase web sdk。

以下是供参考的代码。

Firebase服务工作者:

    importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
 importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-messaging.js');

 // Initialize the Firebase app in the service worker by passing in the
 // messagingSenderId.
 if(!firebase.apps.length) {
     firebase.initializeApp({
       'messagingSenderId': 'XXXXXXXXXXXXX'
     });
 }

 // Retrieve an instance of Firebase Messaging so that it can handle background
 // messages.
 const messaging = firebase.messaging();
 function getUniqueId(suffix) {
        var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0,
                v = c == 'x' ? r : r & 0x3 | 0x8;
            return v.toString(16);
        });
        if (typeof(suffix) == "string" || typeof(suffix) == "number") {
            return uuid + ":" + suffix;
        } else {
            return uuid + "";
        }
    }

    function paramterize(url) {
        var data = {};
        data.type = +url.match(/type\=(\d+)/)[1];
        if (data.type === 0 || data.type === 1) {
            data.accept_reject = true;
        }
        if (data.type === 3) {
            data.popup = true;
        }
        if (/conference_id=(\b([a-f0-9]*)\b)/.test(url)) {
            data.conference_id = url.match(/conference_id=(\b([a-f0-9]*)\b)/)[1];
        }
        if (/idp_privilege\=(\b([Y|N])\b)/.test(url) ) {
            data.idp_privilege = url.match(/idp_privilege\=(\b([Y|N])\b)/)[1];
        }
        if (/country_dialer\=(\+\d+)/.test(url) ) {
            data.country_dialer = url.match(/country_dialer\=(\+\d+)/)[1];
        }
        if (/group_id\=(\b([a-f0-9]*)\b)/.test(url)) {
            data.group_id = url.match(/group_id\=(\b([a-f0-9]*)\b)/)[1];
        }
        return data
    }

var setupDone = false;
var landing_url= 'https://pro.nowconfer.com'; 
var storage = {
        setup: function() {
            return new Promise(function(resolve, reject) {                         
                var request = indexedDB.open('nowconferdb',18);
                request.onsuccess = function (e) {
                    setupDone = true;
                    var db = e.target.result;
                    storage.db = db;
                    resolve();
                };
                request.onupgradeneeded = function (e) {
                    storage.db = e.target.result;
                    if (storage.db.objectStoreNames.contains('notifications')) {
                        storage.db.deleteObjectStore('notifications');
                    }
                    storage.db.createObjectStore('notifications', {
                        keyPath: '_id'
                    });
                };
            });
        },

        transaction: function (mode) {
            var trans = storage.db.transaction('notifications', mode);
            return trans.objectStore('notifications');
        },

        add: function (notification) {
            return new Promise(function(resolve, reject) {
                var request = storage.transaction('readwrite').put(notification);
                request.onsuccess = function () {
                     console.log("Successfully stored in database");
                    resolve(notification);
                };
                request.onerror = function() {
                    console.log("Error in storing database");
                    reject();
                };
            });
        }
    };

// If you would like to customize notifications that are received in the
// background (Web app is closed or not in browser focus) then you should
// implement this optional method.
// [START background_handler]
messaging.setBackgroundMessageHandler(function(payload) {


  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  const notificationTitle = 'Background Message Title';
  const notificationOptions = {
    body: 'Background Message body.',
    icon: '/firebase-logo.png'
  };
  return self.registration.showNotification(notificationTitle, {
                            body: 'Background Message body',
                            icon: 'nowconfer_icon_enterprise.png' 
                         });
});

function createDB(){
 if (!setupDone) {
        storage.setup().then(function() {
        console.log("created");
    });
  }
}
self.addEventListener('install', function(event) { event.waitUntil(self.skipWaiting())});

self.addEventListener('push', function(event) {
    console.log("Inside push event");
    if(event.data) {
            console.info('SERVICE-WORKER');
            var data = JSON.parse(event.data.text());
            console.log("data is :"+data);
            data = data.notification;
            if(data.title && (data.title == "Refresh Contacts" || data.title == "You have a group message")) return;
            console.log("notification data is :"+data);
            var notif_title = "Missed notification";
            var notif_body = "This website has been updated.";
            //var notif_icon = "https://www.pushchamp.com/static/images/notif_icon.png";
            var notif_icon = "https://pro.nowconfer.com/images/Nowconfer_Logo.png";
            var promises = [];
            landing_url = data.click_action || landing_url;
            console.log('landing_url :'+landing_url);
            data._id = data.click_action.match(/_id=(\b([a-f0-9]*)\b)/)[1];
            data.time = Date.now();
            if(data.title.indexOf("You have a new message")==-1){
                promises.push(self.registration.showNotification(data.title || notif_title, {
                    body: data.body || notif_body,
                    icon: data.icon || notif_icon,
                    click_action: landing_url               
                }));
            }

            Object.assign(data, paramterize(landing_url));
            self.clients.matchAll().then(function(clients) {
                Array.prototype.slice.call(clients).map(function(client) {
                    return client.postMessage(data);
                });
            });
            if (!setupDone) {
                storage.setup().then(function() {
                    storage.add(data);
                });
            }
            else {
                storage.add(data);
            }

            landing_url = data.landing_url || landing_url;
            return Promise.all(promises);
        }
}); 


   self.addEventListener('install', function(event) { event.waitUntil(self.skipWaiting())});

    self.addEventListener('activate', function(event) { event.waitUntil(self.clients.claim())});

    self.onactivate = function(evt) {
        var result;
        self.clients.claim().then(function(_result) {
          result = _result;
          return self.clients.matchAll();
        });
    };

 self.addEventListener('notificationclick', function(event) {
 console.log('Inside notificationclick landing_url:'+landing_url);
 event.notification.close();
        event.waitUntil(
            clients.matchAll({
                type: "window"
            }).then(function(clientList) {
                if (landing_url!=''){
                    return clients.openWindow(landing_url);
                }
                for (var i = 0; i < clientList.length; i++) {
                    var client = clientList[i];
                    if (client.url == '/' && 'focus' in client)
                     return client.focus();
                }
                if (clients.openWindow) {
                    return clients.openWindow(landing_url);
                }
            })
        );

});

Angular中的通知控制器: 提供关于通知被推送的事件的块

$scope.$on('push:notification', function(event, notifObj) {
            var notif = {};
            //console.log('notification received:'+JSON.stringify(notif["firebase-messaging-msg-data"].notification));
            if(notifObj && notifObj["firebase-messaging-msg-data"] && notifObj["firebase-messaging-msg-data"].notification) {
                notif = notifObj["firebase-messaging-msg-data"].notification;
                notif.type = notifObj.type?notifObj.type:notif.click_action.match(/type\=(\d+)/)[1];
                notif._id = notifObj._id;
                notif.conference_id = notifObj.conference_id;
            }else{
                notif = notifObj;
            }
            switch (notif.type) {
                case 0:
                    console.log("schedule Notify:"+JSON.stringify(notif));
                    save(notif);
                    break;
                case 1:
                    save(notif);
                    break;
                case 2:
                    save(notif);
                    break;
                case 3:
                    save(notif);
                    break;
                /*case 4:
                    me.fetchProfile().then(function() {
                        $rootScope.$broadcast('refresh:profile');
                    });
                    me.getContacts('refresh').then(function() {
                        $rootScope.$broadcast('refresh:contacts');
                    });
                    break;*/
                case 5: // leave grp by others
                     save(notif);
                     me.getGroups('refresh').then(function() {
                         $rootScope.$broadcast('groups-refreshed');
                     });

                     break;
                case 6:
                     //disable group chat for group_id
                     save(notif);
                     me.getGroups('refresh').then(function() {
                         $rootScope.$broadcast('groups-refreshed');
                     });
                    break;
                case 7:
                    //enable only chat
                    me.removeConfPrivilege();
                    $rootScope.$broadcast('remove:conf:privilege');
                    console.log('case 7 is called');
                    break;

                case 11:
                    save(notif);
                    break;
                case 12:
                    save(notif);
                    console.log('Number verified notif:'+JSON.stringify(notif["firebase-messaging-msg-data"].notification));
                    var my_profile = me.getMe();

                    my_profile.mobile_number = notif.newMobileNo;
                    my_profile.num_verified = true;

                    me.setMe(my_profile).then(function(){
                        // console.log("set verified no to true for profile:"+JSON.stringify(my_profile));
                        if($state.current.title == 'profile') {
                            console.log("Reloading as currently in profile");
                            $state.go('root.profile', {}, { reload: true });
                        }
                    });

                    break;
                case 13:
                    save(notif);
                    console.log('Number unverified notif:'+JSON.stringify(notif["firebase-messaging-msg-data"].notification));
                    if(notif.message){
                        ModalService.showModal({
                            templateUrl: absoluteURL('app/layout/alert.html'),
                            controller: 'AlertController',
                            inputs: {
                                text: notif.message
                            }
                        });
                    }


                    var my_profile = me.getMe();
                    console.log("got my profile:"+JSON.stringify(my_profile));

                    my_profile.mobile_number = notif.conference_id;
                    my_profile.num_verified = false;

                    me.setMe(my_profile).then(function(){
                        console.log("set verified no to false for profile:"+JSON.stringify(my_profile));

                        if($state.current.title == "dashboard"){
                            $rootScope.$broadcast('reload:dashboard');
                        }
                    });

                    break;
                case 14:
                    save(notif);
                    // console.log('suggestion notif:'+JSON.stringify(notif));

                    break;
                case 17:
                    save(notif);
                    // console.log('suggestion notif:'+JSON.stringify(notif));

                    break;
                case 404:
                    console.log('404:'+JSON.stringify(notif));
                    sessionservice.destroy();
                    $window.location.reload();
                    break;

                case 'offer':
                    save(notif);
                    break;

                case 'missedVideoCall':
                    save(notif);
                    break;

                case 'missedVideoConf':
                    save(notif);
                    break;

                default:
                    break;
            }
        });

我不想要完整的解决方案,但是如果有人能够让我知道可能发生的事情,那么我可以尝试修复自己。提前致谢

2 个答案:

答案 0 :(得分:0)

您是否登录了同一个ID?

我认为您的页面会收到同一时间前景(有窗口)和背景(无焦点窗口)。

如果我是你,当页面在前台接收消息时,我会显示小的吐司消息。

而且,这会对你有所帮助。 https://firebase.google.com/docs/cloud-messaging/js

答案 1 :(得分:0)

真正的问题是您将得到x号。通知如果x号。标签页已打开。

您可以尝试此document.hidden

如果选项卡处于活动状态,则

document.hidden将为true。因此,在这种情况下,通知只会出现在活动标签上,而其余标签可以忽略。 您可以执行以下操作:

if (document.hidden) {
    return false;
}