如何通过点击推送通知来启动PWA (渐进式Web应用程序)?

12

按照这个示例,我了解到 PWA 可以打开 url,但如何使用推送通知来启动应用程序本身呢?不是在浏览器中打开,而是全屏版本的 PWA。

5个回答

9

这由浏览器控制。此外,在决定打开一个窗口时,可能值得检查所需的目标URL是否已经在另一个选项卡/窗口中打开,以便根据情况进行焦点或打开。 点击此处获取一些代码示例

例如,在Chrome中,如果用户使用manifest中的“standalone”将Web应用程序添加到主屏幕,则每当用户单击Web应用程序图标时,它都将在没有URL栏的情况下打开。

当接收到推送消息并且已打开同一Web应用程序时,如果用户最近(在过去的10天内)从主屏幕图标打开了Web应用程序,则不会显示URL栏。如果用户在该时间段内没有使用主屏幕图标,则通知单击将显示URL栏。

请参见此处的Chrome问题的更多信息

具体来说

Web应用程序必须添加到主屏幕,能够以独立模式打开,并且在过去的10天内已从主屏幕打开。如果不满足任何这些条件,则通知将回退到现有行为。

值得注意的是,PWA与浏览器本身并不是正确的思考方式。您总是在浏览器中启动,只是以不同的模式,“独立”与“浏览器”等。

PWA(渐进式Web应用程序)主要是一种描述使用一组API来利用新的Web技术(例如服务工作者,推送,Web应用程序清单等)提供良好用户体验的术语。


1
我已经成功地将应用程序添加到主屏幕并从主屏幕启动了应用程序,但推送通知点击始终以浏览器模式打开。有什么想法或建议吗? - jasan
我能想到的唯一事情就是检查 Chrome 版本,我假设你已经在你的 Web 应用清单中设置了独立模式? - Matt Gaunt
代码示例的链接是404。 - jdmayfield
抱歉,我已更新链接:https://web-push-book.gauntface.com/common-notification-patterns/ - Matt Gaunt

7
截至2018年10月:

我已成功使用Chrome 69.

在这个例子中,它是一个子应用程序(www.example.com/application).

简而言之:仔细检查路径!

我还遇到了一些问题,如果我从推送通知启动应用程序时,会出现未加载的cookie(登录信息),它可以打开,但未登录。如果您关闭它并点击之前添加在主屏幕上的应用程序图标,则应用程序将已经登录。

我使用以下方法实现(请参阅注释):

1)serviceworker.js

self.addEventListener('notificationclick', function (event)
{
    //For root applications: just change "'./'" to "'/'"
    //Very important having the last forward slash on "new URL('./', location)..."
    const rootUrl = new URL('./', location).href; 
    event.notification.close();
    event.waitUntil(
        clients.matchAll().then(matchedClients =>
        {
            for (let client of matchedClients)
            {
                if (client.url.indexOf(rootUrl) >= 0)
                {
                    return client.focus();
                }
            }

            return clients.openWindow(rootUrl).then(function (client) { client.focus(); });
        })
    );
});

2) manifest.json

{
    "short_name": "AppNickName",
    "name": "ApplicationName",
    "icons": [
        {
            "src": "./icon.png",
            "sizes": "36x36",
            "type": "image/png",
            "density": 0.75
        }
    ],
    "start_url": "./",  //This matters
    "display": "standalone",  //This also matters
    "gcm_sender_id": "103953800507", //FCM always uses this number (April 2019)
    "background_color": "#c8c8c8",
    "theme_color": "#c8c8c8",
    "orientation": "any"
}

你好,当你说起 start_url 很重要时,你能详细解释一下它的作用吗? - Joy Chopra

6

以下内容摘自Jake Archibald的emojoy演示:

self.addEventListener('notificationclick', event => {
    const rootUrl = new URL('/', location).href;
    event.notification.close();
    // Enumerate windows, and call window.focus(), or open a new one.
    event.waitUntil(
      clients.matchAll().then(matchedClients => {
        for (let client of matchedClients) {
          if (client.url === rootUrl) {
            return client.focus();
          }
        }
        return clients.openWindow("/");
      })
    );
});

谢谢,我刚试了这个应用。每当有新消息时,我会收到两个通知,一个包含消息内容,另一个说明网站已在后台更新。 - jasan
我收到了一条通知:“收到新聊天消息”,点击它将打开之前添加到主屏幕的PWA应用程序。请注意,如果您已经打开了Chrome标签页,则会聚焦该标签页。 - Kevin Farrugia
1
当您收到“网站已在后台更新”的消息时,这意味着“推送”事件代码中存在错误,即在传递给event.waitUntil的承诺解决之前未显示通知。 - Matt Gaunt
嗨,为什么它会在新窗口中打开链接。能否在桌面上打开同一现有应用程序中打开,因为当我们单击通知时,它会打开另一个桌面应用程序并显示链接。 - Ahmad

1

我在这里找到了一个对我有用的解决方案。

只需将以下内容添加到您的服务工作者中:

self.addEventListener('notificationclick', function(event) {
  console.log('On notification click: ', event.notification.tag);
  // Android doesn't close the notification when you click on it
  // See: http://crbug.com/463146
  event.notification.close();

  // This looks to see if the current is already open and
  // focuses if it is
  event.waitUntil(
    clients.matchAll({
      type: "window"
    })
    .then(function(clientList) {
      for (var i = 0; i < clientList.length; i++) {
        var client = clientList[i];
        if (client.url == '/' && 'focus' in client)
          return client.focus();
      }
      if (clients.openWindow) {
        return clients.openWindow('/');
      }
    })
  );
});

0

可以在此处找到更新版本: https://web.dev/push-notifications-common-notification-patterns/

当有可能时,我们应该将焦点放在一个窗口上,而不是每次用户点击通知时都打开一个新窗口。

在我们看如何实现这一点之前,值得强调的是,这只适用于您站点上的页面。这是因为我们只能看到属于我们站点的已打开页面。这样可以防止开发人员能够查看用户正在浏览的所有站���。

以前的例子中,我们将修改代码以查看是否已经打开了 /demos/notification-examples/example-page.html。

  const urlToOpen = new URL(examplePage, self.location.origin).href;

  const promiseChain = clients
  .matchAll({
    type: 'window',
    includeUncontrolled: true,
  })
  .then((windowClients) => {
    let matchingClient = null;

    for (let i = 0; i < windowClients.length; i++) {
      const windowClient = windowClients[i];
      if (windowClient.url === urlToOpen) {
        matchingClient = windowClient;
        break;
      }
    }

    if (matchingClient) {
      return matchingClient.focus();
    } else {
      return clients.openWindow(urlToOpen);
    }
  });

event.waitUntil(promiseChain);

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