从服务器发送通知时未触发推送事件
Posted
技术标签:
【中文标题】从服务器发送通知时未触发推送事件【英文标题】:Push event not firing on send notification from server 【发布时间】:2018-02-17 04:07:28 【问题描述】:我想从我的服务器推送通知。因为我正在使用 Java 的 Web 推送 API,我可以将通知发送到端点 url,但在接收方我的服务工作者没有执行推送事件,因为我正在使用 VAPID所以根据我的理解不需要使用 gcm Id,这里是我的 service worker 文件。
'use strict';
const applicationServerPublicKey = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-
SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';
function urlB64ToUint8Array(base64String)
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i)
outputArray[i] = rawData.charCodeAt(i);
return outputArray;
self.addEventListener('install', function(event)
event.waitUntil(self.skipWaiting());
console.log("activate");
);
self.addEventListener('activate', function(event)
event.waitUntil(self.clients.claim());
console.log("install");
);
self.addEventListener('push', function(event)
console.log('Received push');
let notificationTitle = 'Hello';
const notificationOptions =
body: 'Thanks for sending this push msg.',
icon: '/JMS/resources/images/icon.png',
badge: '/JMS/resources/images/badge.png',
tag: 'simple-push-demo-notification',
data:
url: 'https://developers.google.com/web/fundamentals/getting-
started/push-notifications/',
,
;
if (event.data)
const dataText = event.data.text();
notificationTitle = 'Received Payload';
notificationOptions.body = `Push data: '$dataText'`;
event.waitUntil(
Promise.all([
self.registration.showNotification(
notificationTitle, notificationOptions),
])
);
);
self.addEventListener('notificationclick', function(event)
event.notification.close();
event.waitUntil(
clients.openWindow('https://www.auctiontiger.net')
);
let clickResponsePromise = Promise.resolve();
if (event.notification.data && event.notification.data.url)
clickResponsePromise = clients.openWindow(event.notification.data.url);
event.waitUntil(
Promise.all([
clickResponsePromise
])
);
);
这是我的 main.js 文件,我可以从中调用我的本地服务器。
'use strict';
const applicationServerPublicKey = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-
SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';
const pushButton = document.querySelector('.js-push-btn');
let isSubscribed = false;
let swRegistration = null;
function urlB64ToUint8Array(base64String)
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i)
outputArray[i] = rawData.charCodeAt(i);
return outputArray;
function updateBtn()
if (Notification.permission === 'denied')
pushButton.textContent = 'Push Messaging Blocked.';
pushButton.disabled = true;
updateSubscriptionOnServer(null);
return;
if (isSubscribed)
pushButton.textContent = 'Disable Push Messaging';
else
pushButton.textContent = 'Enable Push Messaging';
pushButton.disabled = false;
function updateSubscriptionOnServer(subscription)
// TODO: Send subscription to application server
const subscriptionJson = document.querySelector('.js-subscription-json');
const subscriptionDetails =
document.querySelector('.js-subscription-details');
if (subscription)
subscriptionJson.textContent = JSON.stringify(subscription);
subscriptionDetails.classList.remove('is-invisible');
else
subscriptionDetails.classList.add('is-invisible');
function subscribeUser()
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe(
userVisibleOnly: true,
applicationServerKey:applicationServerKey
)
.then(function(subscription)
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
initialiseUI();
return sendSubscriptionToServer(subscription);
)
.catch(function(err)
console.log('Failed to subscribe the user: ', err);
);
function sendSubscriptionToServer(subscription)
var key = subscription.getKey ? subscription.getKey('p256dh') : '';
var auth = subscription.getKey ? subscription.getKey('auth') : '';
return fetch('/JMS/profile/subscription',
method: 'POST',
headers:
'Content-Type': 'application/json'
,
body: JSON.stringify(
endpoint: subscription.endpoint,
// Take byte[] and turn it into a base64 encoded string suitable for
// POSTing to a server over HTTP
key:key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key)))
: '',
auth:auth ? btoa(String.fromCharCode.apply(null, new
Uint8Array(auth))) : ''
)
);
function unsubscribeUser()
swRegistration.pushManager.getSubscription()
.then(function(subscription)
if (subscription)
return subscription.unsubscribe();
)
.catch(function(error)
console.log('Error unsubscribing', error);
)
.then(function()
updateSubscriptionOnServer(null);
console.log('User is unsubscribed.');
isSubscribed = false;
updateBtn();
);
function initialiseUI()
pushButton.addEventListener('click', function()
pushButton.disabled = true;
if (isSubscribed)
unsubscribeUser();
else
subscribeUser();
);
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription)
isSubscribed = !(subscription === null);
updateSubscriptionOnServer(subscription);
if (isSubscribed)
console.log('User IS subscribed.');
else
console.log('User is NOT subscribed.');
updateBtn();
);
if ('serviceWorker' in navigator && 'PushManager' in window)
console.log('Service Worker and Push is supported');
navigator.serviceWorker.register('sw.js')
.then(function(swReg)
console.log('Service Worker is registered', swReg.scope);
swReg.update();
swRegistration = swReg;
initialiseUI();
)
.catch(function(error)
console.error('Service Worker Error', error);
);
else
console.warn('Push messaging is not supported');
pushButton.textContent = 'Push Not Supported';
这是我用于我的应用程序的 webpush API 的 URL, [https://github.com/web-push-libs/webpush-java][1] 最后是我的服务器端代码,
@RequestMapping(value = "profile/subscription", method = RequestMethod.POST,
headers = "Content-Type=application/json")
@ResponseBody
public String post(@RequestBody String body,byte[]
payload,HttpServletResponse response)
throws GeneralSecurityException, IOException, JoseException,
ExecutionException, InterruptedException, ParseException, JSONException
String data="";
org.json.JSONObject ob = new org.json.JSONObject(body);
final int TTL = 255;
payload= "hello".getBytes();
com.demo.controller.PushService pushService = new
com.demo.controller.PushService();
nl.martijndwars.webpush.Notification notification =new
nl.martijndwars.webpush.Notification(ob.getString("endpoint")
,new Subscription().getUserPublicKey((ob.getString("key"))),
Base64.decode(ob.getString("auth")),
payload,TTL);
pushService.send(notification);
org.json.JSONObject ob2 = new org.json.JSONObject(body);
ob2.put("data", notification.getPayload());
JSONArray arr= new JSONArray();
arr.add(ob2);
data=arr.toJSONString();
response.setHeader("Service-Worker-Allowed", "/");
return data;
实际上我是从客户端浏览器和端点上的服务器端发送通知中获取的,我能够发送通知,但我的 服务人员无法触发推送事件,所以我的浏览器没有收到通知。
auth:"hcQQq+1FeDuSu7V0zd5DXA=="
endpoint:"https://fcm.googleapis.com/fcm/send/
cXgp0l3svNo:APA91bG8dDfZhrc0iaSyzvuV1BvnxXz9T-
SmLCKOymKrEdwvrh0_SjzjnU3ORRKvW5QD-
Zp196T5nAGPayR7EKu_Bkb0pQrSex7Q3DZSu54Lo83AEiUE6p-2Xn-nrquCymKVFt6Z4nY8"
key:"BJv2qC3WSCsRszMi57vOBpFjnIpdJ/
uXQQFj4d0XZD9lRuZKuBgJNVFra0SFEvRlQQ88eG8RWWs7sSvO9Pbdkwk="
请帮助我摆脱这种情况,任何帮助将不胜感激。在此先感谢您。
【问题讨论】:
当您说“我可以发送通知”时,您的意思是您从推送服务中获得了成功的响应代码(即 2xx)吗?如果没有,则必须检查 HTTP 响应代码 是的,我收到成功响应代码 200。 全部在 VAPID 上,我们不需要在 fcm 和 gcm 中创建任何项目,是否可以看到我发送的消息? 【参考方案1】:问题可能是由于某些防火墙阻止您接收推送通知。我就是这种情况。
【讨论】:
以上是关于从服务器发送通知时未触发推送事件的主要内容,如果未能解决你的问题,请参考以下文章
service-worker 可以停止 GCM api 发送的推送通知吗?