如何将网页通知内容复制到剪贴板

14

我正在使用Firebase Cloud Messaging (FCM)发送数据消息,以便我可以使用Service Worker处理通知。现在我正在使用Service Worker显示通知,当我点击通知时,我想将通知内容复制到剪贴板中。

const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler((payload)=> {
    const title = payload.data.title;
    const options = {
        body: payload.data.body
    };
    return self.registration.showNotification(title,
        options);
});

self.addEventListener('notificationclick', (event)=>{
    console.log(event);
    navigator.clipboard.writeText(event).then(function() {
        console.log('Async: Copying to clipboard was successful!');
      }, function(err) {
        console.error('Async: Could not copy text: ', err);
      });
});

当通知被点击时,会触发notificationclick事件。但是我得到了navigator.clipboard的undefined。我还为我的网站使用了安全域。我也不能使用document.execcommand('copy'),因为无法使用Service Worker访问DOM。请问是否有一种方法可以在不打开任何URL的情况下复制通知内容?


我认为你需要这个:https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage 你将能够在客户端完成你想要的操作。 如果有帮助,请告诉我,我会回答你。 - Gilsdav
似乎你必须打开一个实际的浏览器窗口才能运行复制命令,否则你就无法访问该API。也许打开它、复制并关闭可以几乎像从未发生过一样?我会尝试看看它的表现,即使知道这不是理想的。 - enapupe
@Gilsdav,由于postMessage只能与DOM一起使用,但我不想打开任何窗口。 - Pawan Aichra
@enapupe 是的,navigator.cilpborad 不起作用。但我正在寻找其他实现相同目标的方法。 - Pawan Aichra
2个回答

8

您无法从 ServiceWorker 复制到剪贴板。您需要一个活动的前台浏览器选项卡/窗口才能复制到剪贴板。

来自 Chrome 网页更新存档 https://developers.google.com/web/updates/2018/03/clipboardapi

与许多新 API 一样,navigator.clipboard 仅支持通过 HTTPS 提供的页面。为了防止滥用,只有当页面是活动选项卡时才允许访问剪贴板。活动选项卡中的页面可以在不请求权限的情况下写入剪贴板,但始终需要权限才能从剪贴板读取。

我还检查了 ServiceWorkers 和 Clipboard APIs 的浏览器规格,没有任何关于 service workers 上下文的具体定义。

编辑:我已经联系了该帖子的作者,询问了这个特定问题 https://mobile.twitter.com/_developit/status/1264290519926128641

我认为它在 ServiceWorker 中不可用。我的建议是,如果通知单击处理程序未打开页面,则打开页面,并在该页面内同步调用 writeText()。


3
你可以使用客户端postMessage API:
服务工作者:
self.addEventListener('notificationclick', (event)=>{
    console.log(event);

    if (!event.clientId) return;
    const client = await clients.get(event.clientId);
    if (!client) return;

    client.postMessage({
      type: 'clipboard',
      msg: event
    });
});

简单脚本:

navigator.serviceWorker.addEventListener('message', event => {
  if(event.data.type === 'clipboard') {
      navigator.clipboard.writeText(event.data.msg).then(function() {
        console.log('Async: Copying to clipboard was successful!');
      }, function(err) {
        console.error('Async: Could not copy text: ', err);
      });
  }
});

请记住,Safari不支持此功能。


正如我所提到的,我不想打开一个页面。那么我们该如何执行简单脚本呢? - Pawan Aichra
我认为你可以打开一个窗口,只需复制到剪贴板clients.openWindow,然后直接关闭它自己。 - Gilsdav

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