javascript - PushManager 订阅在 Firefox for Android 上失败
问题描述
我正在努力在我的网络应用程序中集成网络推送通知。一切都适用于桌面版 Chrome 和 Firefox 以及 Android 版 Chrome,但不适用于Firefox for Android。这个问题似乎讨论了同样的问题,但没有任何回应。
我使用本教程作为 service worker 注册脚本的基础。我添加了一些更多的打印/检查,但大部分是相同的。
因此,当registerServiceWorker
从 FF Android 上的按钮按下调用该方法时,serviceWorker
安装了该方法,该subscribeUser
函数被调用,但该pushManager.subscribe
方法将失败并显示以下错误消息:
DOMException: User denied permission to use the Push API.
这是不正确的,即使在错误打印行上暂停时Notification.permission
也会返回"granted"
。
在每晚构建中执行相同的操作会导致略有不同,但仍然是不正确的行为。该pushManager.subscribe
方法不会引发错误。而是运行回调,但带有参数null
值subscription
。因此,该过程仍然失败。
Service Worker 注册脚本:
'use strict';
function updateSubscriptionOnServer(subscription, apiEndpoint) {
return fetch(apiEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
subscription_json: JSON.stringify(subscription)
})
});
}
function subscribeUser(swRegistration, applicationServerPublicKey, apiEndpoint) {
// It seems browsers can take the base64 string directly.
// const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
console.log(`Subscribing pushManager with appkey ${applicationServerPublicKey}`);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerPublicKey
})
.then(function(subscription) {
console.log('User is subscribed.');
console.log(`Sending subscription data to server (${apiEndpoint})`, subscription);
return updateSubscriptionOnServer(subscription, apiEndpoint);
})
.then(function(response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function(responseData) {
console.log(responseData);
if (responseData.status!=="success") {
throw new Error('Bad response from server.');
}
})
.catch(function(err) {
// FF Android says "User denied permission to use the Push API."
console.log('Failed to subscribe the user: ', err);
console.log(err.stack);
});
}
function registerServiceWorker(serviceWorkerUrl, applicationServerPublicKey, apiEndpoint){
let swRegistration = null;
if ('serviceWorker' in navigator && 'PushManager' in window) {
console.log('Service Worker and Push is supported');
console.log(`Current Notification.permission = ${Notification.permission}`);
swRegistration = navigator.serviceWorker.register(serviceWorkerUrl)
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
console.log(`Current Notification.permission = ${Notification.permission}`); // Will give "granted"
subscribeUser(swReg, applicationServerPublicKey, apiEndpoint);
})
.catch(function(error) {
console.error('Service Worker Error', error);
});
} else {
console.warn('Push messaging is not supported');
return false;
}
return swRegistration;
}
我无法弄清楚如何获得有效的推送订阅。如前所述,我尝试过的所有其他浏览器都可以正常工作。我希望有人能指出我正确的方向。这是 Firefox Android 或我的代码中的错误吗?
使用手动显示通知
new Notification("Hi there!");
确实有效,原则上证明权限不是问题。
解决方案
更新:FF Fenix 团队在显示通知时确认了一个错误
随时在这里跟踪它
对服务人员对 Firefox 移动浏览器的支持感到好奇。努力寻找 Mobile Firefox 的调试工具作为插件或 3rd 方工具,但没有成功。
但是,我已经在 Mobile Firefox 上测试了我的网络推送应用程序,并且可能完全确认Service Worker Registration state存在问题。
为了丢弃我的代码中的任何问题,我使用了Matt Gaunt 的 Webpush Book
我可以告诉马特的服务人员返回注册就像这样简单:
async function registerSW() {
await navigator.serviceWorker.register('/demos/notification-examples/service-worker.js');
}
function getSW() {
return navigator.serviceWorker.getRegistration('/demos/notification-examples/service-worker.js');
}
Firefox for Android 成功请求通知权限,但在您启动 .showNotification 函数时它不会显示推送。
这是 Matt 网站的 Badge 示例中的 showNotification 方法示例:
async function onBadgeClick() {
const reg = await getSW();
/**** START badgeNotification ****/
const title = 'Badge Notification';
const options = {
badge: '/demos/notification-examples/images/badge-128x128.png'
};
reg.showNotification(title, options);
/**** END badgeNotification ****/
}
看起来不错,应该可以正常工作,但对于 Firefox Mobile,它根本不起作用。我想这个问题应该升级到Mozilla。
更新 在 Github 上创建了新的错误报告:
推荐阅读
- microsoft-graph-api - 获取 Outlook 邮件的原始 MIME
- node.js - 如何将特定的响应 JSON 键值传递给 url
- python - 根据前两列中的任何一列更新每一行的值
- tensorflow.js - 如何在tensorflowjs中将张量转换为Uint8Array数组
- angular - 如何使用角度将登录页面设为默认页面
- dart - 将动态解析为 int 或回退到默认值
- java - Executor 代替 ExecutorService 有什么场景吗?Executor 接口背后的意图?
- java - JavaFx 宽度动画过渡与动画
- vue.js - 如何在 vuelidate 中使用 $each.$iter
- bash - 当信号被捕获时,三通管道在结束前被杀死