We've a PWA implemented on angular 7 and NodeJS as backend. Push notification are sent from backend with web-push and handled by the angular service worker service.
The behavior that we hope to have in Android is when the user clicks on the notification, the application opens in the device (i.e. the PWA come up from background and appear visible to the user).
Currently, the code seams to execute in the background but PWA does not come up from background (i.e. the user clicks in the push notification but nothing happens).
The push notification are handled by the angular service called SwPush on front-end, and delivered to app using the following code in the typical AppComponent component of an angular 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
}
}
}
I have search all over the SO site and haven't found exactly this question. Comments about other SO questions in order to avoid round trip links to other SO answers:
this other question seams to proposes a workaround adding code inside the service-worker library, but as far as I understand this is because they are using angular 5 instead of the angular 7 (where the SwPush service include the notificationclick handler). Any way, what I need is to simulate this line:
event.waitUtil(clients.openWindow(url));
Any idea on how to open the PWA when the user clicks on push notification when using the SwPush service of angular 7?
The possibilities of PWA's are huge, and using DEITY Falcon Platform, you can easily integrate Web Push Notifications directly into your PWA front-end. If you have no plans to convert your website to a web application in the near future, you can also use PushPro as a web push service for your site or eCommerce webshop.
Progressive Web Applications (PWA) make native push notifications available to any website using a service worker on just about every platform and browser. The power of web app push notifications is being able to engage customers without a native app.
Adding a service worker to an Angular application is one of the steps for turning an application into a Progressive Web App (also known as a PWA). At its simplest, a service worker is a script that runs in the web browser and manages caching for an application. Service workers function as a network proxy.
Though the provided solutions work, it will be nice to have an approach which does not modify service worker code in node_modules or the generated code.
The approach can be to create another script named custom-service-worker.js
In this file,
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));
}
});}
());
Register custom-service-worker.js
as the service worker in place of ngsw-worker.js
in the imports section where ServiceWorkerModule.register would be written.
Also don't forget to add this script as asset in angular.json so that it gets copied in the dist
folder.
I believe this approach saves us the hassle of doing anything extra to edit the original service worker file.
Unfortunately you won't be able to open your PWA from angular code. The SwPush interface will work nicely if the app is currently open.
If your application is closed, the only thing running will be your service worker (provided it was registered succesfully). So the solution to your problem is editing angular's service worker file.
In angular 7 (specifically referring to "@angular/service-worker" v~7.2.0), after you build your app with ng build --prod
, examine your /dist
folder and look for the file ngsw-worker.js
. Open it in an editor.
On line 1885, you will find:
this.scope.addEventListener('notificationclick', (event) => this.onClick(event));
Change it to:
this.scope.addEventListener('notificationclick', (event) => {
event.notification.close();
if (clients.openWindow && event.notification.data.url) {
event.waitUntil(clients.openWindow(event.notification.data.url));
}
});
This implies that you passed in the notification payload a data object with the desired URL. e.g:
{
title: "Hello",
body: "Here, open this URL",
data: {
url : "/somewhere/over/the/rainbow/42"
}
}
Things to have in mind:
ng build --prod
process completes) ;Related links:
How can I initiate a PWA (progressive webapp) open from a click on a push notification?
https://github.com/angular/angular/issues/20956
Add this on your Angular project inside the node_modules/@angular/service-worker/ngsw-worker.js
this.scope.addEventListener('notificationclick', (event) => {
console.log('[Service Worker] Notification click Received. event:%s', event);
event.notification.close();
if (clients.openWindow && event.notification.data.url) {
event.waitUntil(clients.openWindow(event.notification.data.url));
}
});
You can enter the above code where you can find this line inside the file
this.scope.addEventListener('notificationclick', (event) => ..
And you have to build the dist again for this to work. And in backend you would need to use this format:
{"notification":{"body":"This is a message.","title":"PUSH MESSAGE","vibrate":[300,100,400,100,400,100,400],"icon":"https://upload.wikimedia.org/wikipedia/en/thumb/3/34/AlthepalHappyface.svg/256px-AlthepalHappyface.svg.png","tag":"push demo","requireInteraction":true,"renotify":true,"data":{"url":"https://maps.google.com"}}}
Inside the url you can enter your url and on clicking notification your push notification will open the given link and focus it in the browser. YOu dont need to change anything inside the dist.
The best way is to extend the Angular Cli Generated Service Worker. Changing anything inside the node_modules is strongly not recommended.
Step 1: Simply create a new my-svc-wkr.js in your root folder and implement as many event listeners as you want for example:
importScripts('./ngsw-worker.js'); // This will import the default Angular Service Worker Functionality to your custom file.
// Add additional Event Listners like Below:
self.addEventListener('notificationclick', (event) => {
console.log('notification clicked!')
});
Step 2: Now replace the service worker file in your app.module.ts as follows:
ServiceWorkerModule.register('my-svc-wkr.js', { enabled: environment.production })
Step 3: Add following in your angular.json to copy this file during build process in your dist directory:
"assets": {
...,
"src/my-svc-wkr.js"
}
You may read this article for a more detailed explanation on extending service worker functionality: https://medium.com/@smarth55/extending-the-angular-cli-service-worker-44bfc205894c
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With