从Service Worker播放声音

7
有没有一种方法可以从服务工作者播放音频文件?
我正在尝试使用 io.sound 库,但它是一个需要 window 的 JavaScript 插件,所以无法使用。
编辑
按照 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" });
                    });
            }
        })
    });
}

现在从event.waitUntil(..)中调用此函数,位于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时,会返回以下异常:

未捕获的(在promise中)DOM异常:不允许打开窗口。

我该如何解决这个问题?


抱歉,我已经相应地更新了我的答案。 - Jeff Posnick
1个回答

6
该Web通知API的生存规范确实提到了一个sound属性,当显示来自服务工作者的通知时,理论上允许您指定要播放的声音。
然而,尽管规范引用了此属性,但截至本文撰写时,它在任何浏览器中都不受支持更新('19年8月):看起来对sound的引用已从https://notifications.spec.whatwg.org/#alerting-the-user中删除 您最好的选择是将消息发布到由当前服务工作者控制的打开窗口,并在响应message事件时让窗口播放声音。
如果没有可控的客户端(例如因为您的服务工作者已被“推送”事件唤醒,且您的站点当前未在浏览器中打开),则您可以在notificationclick处理程序中打开一个新窗口,该处理程序是响应用户单击您在push事件处理程序中显示的通知时触发的。然后,您可以向该新窗口发送消息。

很遗憾由于“未捕获的(在承诺中)DOM异常:不允许打开窗口”,我无法打开新窗口。我已更新我的问题并附上了代码。 - Androidian
3
在响应推送事件时,你不能打开一个窗口 - 你需要显示一个通知,然后监听通知点击事件,然后再打开一个窗口。 - Alastair
@JeffPosnick,现在的状态怎么样?您在浏览器支持方面的链接(developer.mozilla...)现在无法使用。选项中的声音参数似乎也不起作用了。是这样吗? - mythicalcoder
看起来声音已经从规范中被抛弃了。我已经更新了答案以反映这一点。 - Jeff Posnick
嗯,谢谢@JeffPosnick。移动端的渐进式Web应用(PWA)怎么样?如何让声音从后台播放!或者有什么替代方案。 - mythicalcoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接