单击service-worker ng7 + android处理的推送通知时打开PWA

dan*_*iel 18 android push-notification progressive-web-apps angular angular7

我们在角度7和NodeJS上实现了PWA作为后端.推送通知从后端通过web-push发送,并由角度服务工作者服务处理.

我们希望Android中的行为是当用户点击通知时,应用程序在设备中打开(即PWA从后台出现并且对用户可见).

目前,代码接缝在后台执行,但PWA不是来自后台(即用户点击推送通知但没有任何反应).

推送通知由前端名为SwPush的角度服务处理,并使用角度应用程序的典型AppComponent组件中的以下代码传递给app:

export class AppComponent implements OnInit {
    constructor(private swPush: SwPush) { }

    ngOnInit(): void {
        try {
            if (this.swPush.isEnabled) {
                this.swPush.notificationClicks.subscribe(
                    event => {
                        window.focus();
                        window.open(event.notification.data.url, '_self');
                    },
                    error => {
                        // handle error
                    }
                );
            }
        } catch (err) {
            // handle error
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我搜索了整个SO网站,但没有找到这个问题.关于其他SO问题的评论,以避免往返其他SO答案的链接:

  • 我已经阅读了这个问题,在我的情况下,处理程序内的控制台日志执行没有问题
  • 另一个问题是建议在service-worker库中添加代码的解决方法,但据我所知,这是因为他们使用的是角度5而不是角度7(SwPush服务包含notificationclick处理程序).无论如何,我需要的是模拟这一行:

    event.waitUtil(clients.openWindow(URL));

当使用角度7的SwPush服务时,当用户点击推送通知时,如何打开PWA?

tom*_*lue 8

不幸的是,您将无法从角度代码中打开PWA。该SwPush接口将很好地工作,如果应用程序是当前打开的。

如果您的应用程序已关闭,则唯一正在运行的将是您的服务工作者(前提是它已成功注册)。因此,解决您的问题的方法是编辑angular的service worker文件。

在angular 7(特别是指“ @ angular / service-worker” v〜7.2.0版)中,使用构建完应用程序后ng build --prod,检查/dist文件夹并查找文件ngsw-worker.js。在编辑器中打开它。

在1885行中,您将找到:

this.scope.addEventListener('notificationclick', (event) => this.onClick(event));
Run Code Online (Sandbox Code Playgroud)

更改为:

this.scope.addEventListener('notificationclick', (event) => {
    event.notification.close();
    if (clients.openWindow && event.notification.data.url) {
        event.waitUntil(clients.openWindow(event.notification.data.url));
    }
});
Run Code Online (Sandbox Code Playgroud)

这意味着您在通知有效负载中传递了具有所需URL的数据对象。例如:

{ 
    title: "Hello", 
    body: "Here, open this URL",
    data: { 
        url : "/somewhere/over/the/rainbow/42"
    } 
}
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • 如果您有任何自动构建管道(CD),则必须手动更改ngsw-worker.js(但是您可以在ng build --prod过程完成后设法部署服务工作者文件);
  • 每次生成产品时,ngsw-worker.js都会被覆盖。
  • 我知道您在android上进行开发,但是如果您看不到更改,则可以使用Chrome开发者工具[A]强制更新服务工作者,或[B]打开当前的ngsw-worker.js文件并验证是否这是所需的版本。该解决方案也适用于台式机上已安装的应用程序。

在此处输入图片说明

相关链接:

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

https://github.com/angular/angular/issues/20956

  • 嗨,@ tomblue,我看到并尝试过这种方法,但是我真的不喜欢它,因为它需要更改角度编译。任何方法似乎都是满足要求的唯一可能方法。我对此深信不疑,最终我在package.json上添加了一个脚本步骤,例如`edit-sw-push:ts-node edit-sw-push.ts`,并使用了您建议的替代方法。这样,只要编译角度项目,就可以修改ngsw-worker.js文件,并且一切似乎都可以正常工作。无论如何....开箱即用的有角度的甜蜜度会很棒! (2认同)

Jay*_*Jay 8

尽管提供的解决方案有效,但最好采用一种不修改node_modules或生成的代码中的服务工作者代码的方法。

该方法可以是创建另一个名为 custom-service-worker.js

在这个档案中

importScripts('./ngsw-worker.js');

(function () {
    'use strict';

    self.addEventListener('notificationclick', (event) => {
        console.log("This is custom service worker notificationclick method.");
        console.log('Notification details: ', event.notification);
        // Write the code to open
        if (clients.openWindow && event.notification.data.url) {
            event.waitUntil(clients.openWindow(event.notification.data.url));
        }
    });}
());
Run Code Online (Sandbox Code Playgroud)

在将要编写ServiceWorkerModule.register的imports部分中注册custom-service-worker.js为Service Worker ngsw-worker.js

另外,请不要忘记将此脚本作为素材资源添加到angular.json中,以便将其复制到dist文件夹中。

我相信这种方法为我们省去了做额外的工作来编辑原始服务工作者文件的麻烦。

  • `clients` 变量从哪里来? (4认同)
  • 对我们来说工作得很好 - 感谢这个干净的解决方案,这比构建 imo 后操作编译的代码要好得多。 (2认同)

Ste*_*fan 5

只是为了让大家知道 - Angular 的服务工作人员现在支持开箱即用的单击操作,因此无需再创建自定义工作人员:https ://angular.io/guide/service-worker-notifications#notification-click-handling

您需要onActionClick在您的 ; 中提供对象notification.data

{
  "notification": {
    "title": "New Notification!",
    "data": {
      "onActionClick": {
        "default": {"operation": "openWindow", "url": "foo"}
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

**

运营

openWindow 在指定的 URL 处打开一个新选项卡,该 URL 是相对于 Service Worker 范围进行解析的。

focusLastFocusedOrOpen 聚焦最后一个聚焦的客户端。如果没有打开的客户端,则会在指定的 URL 处打开一个新选项卡,该 URL 是相对于 Service Worker 范围进行解析的。

navigateLastFocusedOrOpen 聚焦最后一次聚焦的客户端并将其导航到指定的 URL,该 URL 是相对于 Service Worker 范围进行解析的。如果没有打开客户端,则会在指定 URL 处打开一个新选项卡。

  • 现在这应该是公认的答案,这是 Angular 的官方做法,并且它按预期工作 (4认同)