I'm creating a PWA using angular 7, but I'm struggling with the push notifications.
I was following the tutorials as this and this using SWPush and Vapid keypairs. I was able to subscribe and unsubscribe and my server part works as well, but unfortunately the tutorials do not cover showing the actual notification in the app.
As I understood it, the notifications should pop up automatically without calling it in the code, right?. You just subscribe and the ngsw does the rest. Unfortunately they don't show up in my case. I can show them only by manually calling them in the code like this:
this.swPush.messages.subscribe(
(notification: any) => {
console.log("received push message", notification);
let options = {
body: notification.body,
icon: "assets/icon/favicon.png",
actions: <any>notification.actions,
data: notification.data,
vibrate: [100, 50, 10, 20, 20]
};
this.showNotification(notification.title, options)
},
err => {
console.error(err);
}
);
[...]
showNotification(title: string, options: NotificationOptions) {
navigator.serviceWorker.getRegistration().then(reg => {
reg.showNotification(title, options).then(res => {
console.log("showed notification", res)
}, err => {
console.error(err)
});
});
}
But this seems to work only when the app/page is in foreground. Otherwise I get a notification like "The site has been updated in the background". Obviously I am doing something wrong here.But what?
What do I have to do to show notifications when the app is in the background?
Is there a way to handle click events on the notifications?
The ng documentation is really sparse here.
Note that you must ensure the browser itself has notifications turned on at the OS level, otherwise notifications will automatically be blocked. The PWA features work on all major platforms: Mac, Windows, Android, but notably not iOS currently.
Can PWA send push notifications to iOS? There is, in practice, no official support for push notifications from Apple. However, there are some ways that developers find that get around the system a bit.
Turn on notifications for Android devicesTap More on the bottom navigation bar and select Settings. Tap Turn on notifications. Tap Notifications. Tap Show notifications.
After lots of struggle I found something and will share it for others:
Digging into the ngsw-worker.js that is created by running build --prod there is this function:
onPush(msg) {
// Push notifications without data have no effect.
if (!msg.data) {
return;
}
// Handle the push and keep the SW alive until it's handled.
msg.waitUntil(this.handlePush(msg.data.json()));
}
...
handlePush(data) {
return __awaiter$5(this, void 0, void 0, function* () {
yield this.broadcast({
type: 'PUSH',
data,
});
if (!data.notification || !data.notification.title) {
return;
}
const desc = data.notification;
let options = {};
NOTIFICATION_OPTION_NAMES.filter(name => desc.hasOwnProperty(name))
.forEach(name => options[name] = desc[name]);
yield this.scope.registration.showNotification(desc['title'], options);
});
}
As it looks like angular subscribes and shows the notification for you, it is not necessary to subscribe and show it in your own code. I had an issue with my sending library (https://github.com/laravel-notification-channels/webpush) that was sending the payload like this:
payload = {"title":"test","actions":[{"title":"View App","action":"view_app"}],"body":"test","icon":"\/icon.png","data":{"id":"21a3804e-6d71-4a56-b513-535709c37c0f"}}
but angular expects obviously something like:
payload = {
"notification":{"title":"test","actions":[{"title":"View App","action":"view_app"}],"body":"test","icon":"\/icon.png","data":{"id":"21a3804e-6d71-4a56-b513-535709c37c0f"}}
}
which caused this line in ngsw-worker.js to fail:
if (!data.notification || !data.notification.title) {
return;
}
Therefor, no notification was shown, but the browser reported an update in the background. Hope this helps someone.
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