【问题标题】:Play a sound from a Service Worker从 Service Worker 播放声音
【发布时间】:2017-07-05 06:01:32
【问题描述】:

有没有办法从服务人员播放音频文件?

我正在尝试使用 io.sound 库,但它是一个 JavaScript 插件,需要 window,所以它不起作用。

编辑

按照 Jeff 的建议,我正在尝试打开一个新窗口并向该窗口发布消息。这是我的代码:

function notifyClientToPlaySound() {
  idbKeyval.get('pageToOpenOnNotification')
    .then(url => {

        console.log("notifyClientToPlaySound", url);

        clients.matchAll({
            type: "window"
            //includeUncontrolled: true
        })
        .then((windowClients) => {

            console.log("notifyClientToPlaySound - windowClients", windowClients);
            for (var i = 0; i < windowClients.length; i++) {
                var client = windowClients[i];
                if (client.url === url && "focus" in client) {
                    notify({ event: "push" });
                    return client.focus();
                }
            }

            //https://developer.mozilla.org/en-US/docs/Web/API/Clients/openWindow
            if (clients.openWindow) {
                return clients.openWindow("/")
                    .then(() => {
                        notify({ event: "push" });
                    });
            }
        })
    });
}

这个函数现在在 self.addEventListener("push", (event) => { ... }

self.addEventListener("push", (event) => {
   console.log("[serviceWorker] Push message received", event);

   event.waitUntil(
      idbKeyval.get('fetchNotificationDataUrl')
        .then(url => {
            console.log("[serviceWorker] Fetching notification data from -> " + url);

            return fetch(url, {
                credentials: "include"
            });
        })
        .then(response => {
            if (response.status !== 200) {
                // Either show a message to the user explaining the error  
                // or enter a generic message and handle the
                // onnotificationclick event to direct the user to a web page  
                console.log("[serviceWorker] Looks like there was a problem. Status Code: " + response.status);
                throw new Error();
            }

            // Examine the text in the response  
            return response.json();
        })
        .then(data => {
            if (!data) {
                console.error("[serviceWorker] The API returned no data. Showing default notification", data);
                //throw new Error();
                showDefaultNotification({ url: "/" });
            }

            notifyClientToPlaySound(); <------ HERE

            var title = data.Title;
            var message = data.Message;
            var icon = data.Icon;
            var tag = data.Tag;
            var url = data.Url;

            return self.registration.showNotification(title, {
                body: message,
                icon: icon,
                tag: tag,
                data: {
                    url: url
                },
                requireInteraction: true
            });
        })
        .catch(error => {
            console.error("[serviceWorker] Unable to retrieve data", error);

            var title = "An error occurred";
            var message = "We were unable to get the information for this push message";
            var icon = "/favicon.ico";
            var tag = "notification-error";
            return self.registration.showNotification(title, {
                body: message,
                icon: icon,
                tag: tag,
                data: {
                    url: "/"
                },
                requireInteraction: true
            });
        })
   );
});

但是当clients.openWindow被调用时,会返回如下异常:

Uncaught (in promise) DOMException: Not allowed to open a window.

我该如何解决这个问题?

【问题讨论】:

  • 道歉;我已经相应地更新了我的答案。

标签: javascript audio service-worker


【解决方案1】:

Web Notifications API 的现行规范确实引用了sound property,它可以在显示通知时指定,并且理论上允许您在显示来自服务人员的通知时播放您选择的声音。

但是,虽然规范引用了此属性,但在撰写本文时,it's not supported in any browsers

更新(2019 年 8 月):似乎对 sound 的引用已从 https://notifications.spec.whatwg.org/#alerting-the-user 中删除

您最好的选择是 post a message 与当前服务人员控制的打开窗口一起,并让窗口播放声音以响应 message 事件。

如果没有可用的受控客户端(例如,因为您的 Service Worker 已被 push 事件唤醒,并且您的网站当前未在浏览器中打开),那么您可以在里面选择 opening a new window您的notificationclick 处理程序,它是响应用户单击您在push 事件处理程序中显示的通知而触发的。然后,您可以将消息发布到该新窗口。

【讨论】:

  • 不幸的是,我无法打开新窗口,因为“未捕获(承诺)DOMException:不允许打开窗口。”我已经用代码更新了我的问题
  • @Androidian 你不能打开一个窗口来响应推送事件——你需要显示一个通知,然后监听 notificationclick 事件,然后打开一个窗口。
  • @JeffPosnick 当前状态如何?您在浏览器支持 (developer.mozilla...) 上的链接现在不起作用。 options 中的 sound 参数现在似乎也不起作用。是这样吗?
  • 看起来声音已经被规范抛弃了。我已经更新了答案以反映这一点。
  • 嗯。谢谢,@JeffPosnick。移动端的 PWA 怎么样?一种方法应该如何从背景中播放声音!或者有什么替代方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
相关资源
最近更新 更多