Erstellen geplanter Push Benachrichtigungen

Avatar of Nico Martin
Nico Martin am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Geplant ist dort das Schlüsselwort – das ist eine ziemlich neue Sache! Wenn eine Push-Benachrichtigung geplant ist (d.h. „Nimm deine Pille ein“ oder „Du hast in 3 Stunden einen Flug“), bedeutet das, dass sie dem Benutzer angezeigt werden kann, auch wenn er offline gegangen ist. Das ist eine Verbesserung gegenüber früher, als Push-Benachrichtigungen erforderten, dass der Benutzer online war. 

Wie funktionieren also geplante Push-Benachrichtigungen? Wir werden uns vier Hauptbestandteile ansehen:

  • Registrieren eines Service Workers
  • Hinzufügen und Entfernen geplanter Push-Benachrichtigungen
  • Verbessern von Push-Benachrichtigungen mit Aktionsschaltflächen
  • Behandeln von Push-Benachrichtigungen im Service Worker

Zuerst ein kleiner Hintergrund

Push-Benachrichtigungen sind eine großartige Möglichkeit, Website-Benutzer darüber zu informieren, dass etwas Wichtiges passiert ist und dass sie unsere (Web-)App möglicherweise wieder öffnen möchten. Mit der Notifications API – in Kombination mit der Push API und dem HTTP Web Push Protocol – wurde das Web zu einer einfachen Möglichkeit, eine Push-Benachrichtigung von einem Server an eine Anwendung zu senden und sie auf einem Gerät anzuzeigen.

Sie haben diese Art von Entwicklung vielleicht schon beobachtet. Wie oft sehen Sie zum Beispiel eine Benachrichtigung, um Benachrichtigungen von einer Website zu akzeptieren? Während Browserhersteller bereits an Lösungen arbeiten, um dies weniger störend zu gestalten (sowohl Firefox als auch Chrome haben Pläne dargelegt), hat Chrome 80 gerade einen Origin-Trial für die neue Notification Trigger API gestartet, mit der wir Benachrichtigungen erstellen können, die durch verschiedene Ereignisse ausgelöst werden und nicht nur durch einen Server-Push. Vorerst sind zeitbasierte Trigger jedoch die einzigen unterstützten Ereignisse. Andere Ereignisse, wie geolocationsbasierte Trigger, sind jedoch bereits geplant.

Das Planen eines Ereignisses in JavaScript ist ziemlich einfach, aber es gibt ein Problem. In unserem Push-Benachrichtigungsszenario können wir nicht sicher sein, dass die Anwendung genau in dem Moment läuft, in dem wir die Benachrichtigung anzeigen möchten. Das bedeutet, dass wir sie nicht einfach auf Anwendungsebene planen können. Stattdessen müssen wir dies auf Service-Worker-Ebene tun. Hier kommt die neue API ins Spiel.

Die Notification Trigger API befindet sich in einer frühen Feedback-Phase. Sie müssen das Flag #enable-experimental-web-platform-features in Chrome aktivieren oder Ihre Anwendung für einen Origin-Trial registrieren.

Außerdem erfordert die Service Worker API eine sichere Verbindung über HTTPS. Wenn Sie es also auf Ihrem Rechner ausprobieren, müssen Sie sicherstellen, dass es über HTTPS bereitgestellt wird.

Einrichtung

Ich habe ein sehr einfaches Setup erstellt. Wir haben eine Datei application.js, eine Datei index.html und eine Datei service-worker.js sowie einige Bild-Assets.

/project-folder
├── index.html
├── application.js
├── service-worker.js
└── assets
   ├─ badge.png
   └── icon.png

Das vollständige Beispiel für eine einfache Demo der Notification Trigger API finden Sie auf GitHub.

Registrieren eines Service Workers

Zuerst müssen wir einen Service Worker registrieren. Vorerst wird er nichts anderes tun, als zu protokollieren, dass die Registrierung erfolgreich war.

// service-worker.js
// listen to the install event
self.addEventListener('install', event => console.log('ServiceWorker installed'));
<!-- index.html -->
<script>
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js');
  }
</script>

Einrichten der Push-Benachrichtigung

Innerhalb unserer Anwendung müssen wir den Benutzer um Erlaubnis bitten, Benachrichtigungen anzuzeigen. Von dort erhalten wir unsere Service-Worker-Registrierung und registrieren eine neue Benachrichtigung für diesen Geltungsbereich. Bisher nichts Neues.

Das Coole daran ist die neue showTrigger-Eigenschaft. Diese ermöglicht es uns, die Bedingungen für die Anzeige einer Benachrichtigung zu definieren. Vorerst möchten wir einen neuen TimestampTrigger hinzufügen, der einen Zeitstempel akzeptiert. Da alles direkt auf dem Gerät geschieht, funktioniert es auch offline.

// application.js
document.querySelector('#notification-button').onclick = async () => {
  const reg = await navigator.serviceWorker.getRegistration();
  Notification.requestPermission().then(permission => {
    if (permission !== 'granted') {
      alert('you need to allow push notifications');
    } else {
      const timestamp = new Date().getTime() + 5 * 1000; // now plus 5000ms
      reg.showNotification(
        'Demo Push Notification',
        {
          tag: timestamp, // a unique ID
          body: 'Hello World', // content of the push notification
          showTrigger: new TimestampTrigger(timestamp), // set the time for the push notification
          data: {
            url: window.location.href, // pass the current url to the notification
          },
          badge: './assets/badge.png',
          icon: './assets/icon.png',
        }
      );
    }
  });
};

Behandeln der Benachrichtigung

Im Moment sollte die Benachrichtigung zum angegebenen Zeitstempel angezeigt werden. Aber jetzt brauchen wir eine Möglichkeit, damit zu interagieren, und hier benötigen wir die Ereignisse notificationclick und notificationclose des Service Workers.

Beide Ereignisse lauschen auf die relevanten Interaktionen und beide können das volle Potenzial des Service Workers nutzen. Wir könnten zum Beispiel ein neues Fenster öffnen

// service-worker.js
self.addEventListener('notificationclick', event => {
  event.waitUntil(self.clients.openWindow('/'));
});

Das ist ein ziemlich einfaches Beispiel. Aber mit der Macht des Service Workers können wir viel mehr tun. Lassen Sie uns prüfen, ob das benötigte Fenster bereits geöffnet ist, und nur dann ein neues öffnen, wenn es nicht geöffnet ist.

// service-worker.js
self.addEventListener('notificationclick', event => {
  event.waitUntil(self.clients.matchAll().then(clients => {
    if (clients.length){ // check if at least one tab is already open
      clients[0].focus();
    } else {
      self.clients.openWindow('/');
    }
  }));
});

Benachrichtigungsaktionen

Eine weitere großartige Möglichkeit, die Interaktion mit Benutzern zu erleichtern, ist das Hinzufügen vordefinierter Aktionen zu den Benachrichtigungen. Wir könnten sie zum Beispiel entscheiden lassen, ob sie die Benachrichtigung abweisen oder die App öffnen möchten.

// application.js
reg.showNotification(
  'Demo Push Notification',
  {
    tag: timestamp, // a unique ID
    body: 'Hello World', // content of the push notification
    showTrigger: new TimestampTrigger(timestamp), // set the time for the push notification
    data: {
      url: window.location.href, // pass the current url to the notification
    },
    badge: './assets/badge.png',
    icon: './assets/icon.png',
    actions: [
      {
        action: 'open',
        title: 'Open app’
      },
      {
        action: 'close',
        title: 'Close notification',
      }
    ]
  }
);

Jetzt verwenden wir diese Benachrichtigungen im Service Worker.

// service-worker.js
self.addEventListener('notificationclick', event => {
  if (event.action === 'close') {
    event.notification.close();
  } else {
    self.clients.openWindow('/');
  }
});

Abbrechen von Push-Benachrichtigungen

Es ist auch möglich, anstehende Benachrichtigungen abzubrechen. In diesem Fall müssen wir alle anstehenden Benachrichtigungen vom Service Worker abrufen und sie dann schließen, bevor sie an das Gerät gesendet werden.

// application.js
document.querySelector('#notification-cancel').onclick = async () => {
  const reg = await navigator.serviceWorker.getRegistration();
  const notifications = await reg.getNotifications({
    includeTriggered: true
  });
  notifications.forEach(notification => notification.close());
  alert(`${notifications.length} notification(s) cancelled`);
};

Kommunikation

Der letzte Schritt ist die Einrichtung der Kommunikation zwischen der App und dem Service Worker mithilfe der Methode postMessage für die Service-Worker-Clients. Nehmen wir an, wir möchten den bereits aktiven Tab benachrichtigen, dass ein Klick auf eine Push-Benachrichtigung stattgefunden hat.

// service-worker.js
self.addEventListener('notificationclick', event => {
  event.waitUntil(self.clients.matchAll().then(clients => {
    if(clients.length){ // check if at least one tab is already open
      clients[0].focus();
      clients[0].postMessage('Push notification clicked!');
    } else {
      self.clients.openWindow('/');
    }
  }));
});
// application.js
navigator.serviceWorker.addEventListener('message', event => console.log(event.data));

Zusammenfassung

Die Notification API ist ein sehr mächtiges Werkzeug zur Verbesserung des mobilen Erlebnisses von Webanwendungen. Dank der Einführung der Notification Trigger API hat sie gerade eine sehr wichtige Verbesserung erfahren. Die API ist noch in der Entwicklung, daher ist jetzt der perfekte Zeitpunkt, damit herumzuspielen und Feedback an die Entwickler zu geben.

Wenn Sie mit Vue oder React arbeiten, empfehle ich Ihnen, sich meine eigene Progressive Web App Demo anzusehen. Sie enthält ein dokumentiertes Beispiel für beide Frameworks, das die Notification Trigger API verwendet und wie folgt aussieht: