谷歌浏览器推送通知
Posted
技术标签:
【中文标题】谷歌浏览器推送通知【英文标题】:Google Chrome Push Notification 【发布时间】:2016-05-24 10:24:26 【问题描述】:我正在为我的网站用户实施 chrome 推送通知。我能够成功地做到这一点。 我有两个问题?
1) 每当我阻止来自浏览器设置的通知时,如何获取以前的订阅 ID。我必须从我的后端服务器中删除订阅 ID
2) 每当我重新加载网站时,pushManager.subscribe 方法都会在每次我向服务器发送订阅 ID 时运行,因此 API 每次都使用相同的订阅 ID 命中
push.js
'use strict';
if ('serviceWorker' in navigator)
console.log('Service Worker is supported');
navigator.serviceWorker.register('service_worker.js').then(function()
return navigator.serviceWorker.ready;
).then(function(reg)
console.log('Service Worker is ready :^)', reg);
reg.pushManager.subscribe(userVisibleOnly: true).then(function(sub)
console.log('endpoint:',JSON.stringify(sub.endpoint));
console.log(sub.endpoint.substring('https://android.googleapis.com/gcm/send/'.length));
);
).catch(function(error)
console.log('Service Worker error :^(', error);
);
service-worker.js
'use strict';
var myurl;
console.log('Started', self);
self.addEventListener('install', function(event)
self.skipWaiting();
console.log('Installed', event);
);
self.addEventListener('activate', function(event)
console.log('Activated', event);
);
self.addEventListener('push', function(event)
console.log('Push message', event);
event.waitUntil(
fetch('/notify.json').then(function(response)
return response.json().then(function(data)
console.log(JSON.stringify(data));
var title = data.title;
var body = data.body;
myurl=data.myurl;
return self.registration.showNotification(title,
body: body,
icon: 'profile.png',
tag: 'notificationTag'
);
);
).catch(function(err)
console.error('Unable to retrieve data', err);
var title = 'An error occurred';
var body = 'We were unable to get the information for this push message';
return self.registration.showNotification(title,
body: body,
icon: 'profile.png',
tag: 'notificationTag'
);
)
);
);
// var title = 'Vcona';
// event.waitUntil(
// self.registration.showNotification(title,
// 'body': 'School Management',
// 'icon': 'profile.png'
// ));
self.addEventListener('notificationclick', function(event)
console.log('Notification click: tag', event.notification.tag);
// Android doesn't close the notification when you click it
// See http://crbug.com/463146
event.notification.close();
var url = 'https://demo.innotical.com';
// Check if there's already a tab open with this URL.
// If yes: focus on the tab.
// If no: open a tab with the URL.
event.waitUntil(
clients.matchAll(
type: 'window'
)
.then(function(windowClients)
console.log('WindowClients', windowClients);
for (var i = 0; i < windowClients.length; i++)
var client = windowClients[i];
console.log('WindowClient', client);
if (client.url === url && 'focus' in client)
return client.focus();
if (clients.openWindow)
return clients.openWindow(myurl);
)
);
);
【问题讨论】:
【参考方案1】:我能给出的最佳建议:
-
在 indexDB 中跟踪您的订阅(尤其是发送到服务器的内容)。为什么选择索引数据库?
-
您可以在窗口和 serviceworker 中更新 indexDB。这很重要,因为您首先会在窗口中获得
PushSubscription
,但 serviceworker 将调度您应该监听的 pushsubscriptionchange
事件并尝试获得新的 PushSubscription
,如果可以的话。
getSubscription()
(即您当前的订阅)进行比较。此检查应包括您需要服务器端的任何值,例如,当浏览器从 不 支持有效负载到支持它们时,它们从没有密钥变为突然有密钥 - 所以您应该检查是否您的服务器是否有这些密钥。
请勿使用任何用于 GCM 的 API,这将不适用于其他浏览器(Firefox、Opera、Samsung Browser + 未来的其他浏览器)并且不需要。
【讨论】:
【参考方案2】:1) 您无法获取以前的注册 ID。方法有:
-
每次订阅通知时,您都可以将其保存到本地 chrome 数据库(例如 indexdb),当您再次订阅时,您只需从该数据库恢复您之前的 reg id。
当您向 GCM 发送通知时,它会以规范 id 和其他有关 reg id 正确性的信息来响应您,因此您可以删除无效的信息
2) 你必须先检查订阅ID是否已经存在,如果不存在则订阅:
if ('serviceWorker' in navigator)
console.log('Service Worker is supported');
navigator.serviceWorker.register('service_worker.js').then(function()
return navigator.serviceWorker.ready;
).then(function(reg)
console.log('Service Worker is ready :^)', reg);
reg.pushManager.getSubscription().then(function(subscription)
if(!subscription)
reg.pushManager.subscribe(userVisibleOnly: true).then(function(sub)
console.log('endpoint:',JSON.stringify(sub.endpoint));
console.log(sub.endpoint.substring('https://android.googleapis.com/gcm/send /'.length));
//send new subscription id to server
return;
);
);
).catch(function(error)
console.log('Service Worker error :^(', error);
);
【讨论】:
以上是关于谷歌浏览器推送通知的主要内容,如果未能解决你的问题,请参考以下文章