Push-Benachrichtigungen im offenen Web

Matt Gaunt

Wenn Sie Entwickler fragen, welche Funktionen für Mobilgeräte im Web fehlen, stehen Push-Benachrichtigungen immer ganz oben auf der Liste.

Push-Benachrichtigungen ermöglichen es Ihren Nutzern, zeitnah Updates von Websites zu aktivieren, die sie mögen, und Sie können sie mit angepassten, ansprechenden Inhalten effektiv zu neuen Interaktionen bewegen.

Ab Chrome-Version 42 stehen Entwicklern die Push API und die Notification API zur Verfügung.

Die Push API in Chrome basiert auf verschiedenen Technologien, z. B. Web App Manifests und Service Worker. In diesem Beitrag gehen wir auf jede dieser Technologien ein, aber nur das Nötigste, um Push-Nachrichten zum Laufen zu bringen. Weitere Informationen zu einigen anderen Funktionen von Manifesten und den Offlinefunktionen von Service Workern finden Sie unter den obigen Links.

Wir schauen uns auch an, welche Funktionen der API in zukünftigen Chrome-Versionen hinzugefügt werden, und haben am Ende Antworten auf häufig gestellte Fragen.

Push-Messaging für Chrome implementieren

In diesem Abschnitt wird jeder Schritt beschrieben, den Sie ausführen müssen, um Push-Nachrichten in Ihrer Webanwendung zu unterstützen.

Service Worker registrieren

Für die Implementierung von Push-Nachrichten für das Web ist ein Service Worker erforderlich. Der Grund dafür ist, dass der Browser beim Empfang einer Push-Nachricht einen Service Worker startet, der im Hintergrund ausgeführt wird, ohne dass eine Seite geöffnet ist, und ein Ereignis auslösen, damit Sie entscheiden können, wie diese Push-Nachricht verarbeitet werden soll.

Unten sehen Sie ein Beispiel dafür, wie Sie einen Service Worker in Ihrer Webanwendung registrieren. Wenn die Registrierung erfolgreich abgeschlossen ist, rufen wir initialiseState() auf, worauf wir gleich näher eingehen werden.

var isPushEnabled = false;

…

window.addEventListener('load', function() {
    var pushButton = document.querySelector('.js-push-button');
    pushButton.addEventListener('click', function() {
    if (isPushEnabled) {
        unsubscribe();
    } else {
        subscribe();
    }
    });

    // Check that service workers are supported, if so, progressively
    // enhance and add push messaging support, otherwise continue without it.
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(initialiseState);
    } else {
    console.warn('Service workers aren\'t supported in this browser.');
    }
});

Mit dem Schaltflächen-Klick-Handler werden Push-Nachrichten für den Nutzer abonniert oder abgemeldet. isPushEnabled ist eine globale Variable, die lediglich erfasst, ob Push-Nachrichten derzeit abonniert sind oder nicht. Auf diese wird in den Code-Snippets verwiesen.

Anschließend prüfen wir, ob Service Worker unterstützt werden, bevor die Datei service-worker.js registriert wird, die die Logik für die Verarbeitung einer Push-Nachricht enthält. Hier teilen wir dem Browser mit, dass diese JavaScript-Datei der Service Worker für unsere Website ist.

Anfangszustand einrichten

Beispiel für aktivierte und deaktivierte Push-Benachrichtigungen in Chrome

Sobald der Service Worker registriert ist, müssen wir den Status der UI einrichten.

Nutzer erwarten eine einfache Benutzeroberfläche zum Aktivieren oder Deaktivieren von Push-Benachrichtigungen für Ihre Website und erwarten, dass sie bei allen Änderungen immer auf dem neuesten Stand ist. Wenn also Push-Benachrichtigungen für Ihre Website aktiviert werden und sie die Website verlassen und eine Woche später wiederkommen, sollte in Ihrer UI hervorgehoben werden, dass Push-Nachrichten bereits aktiviert sind.

Einige UX-Richtlinien finden Sie in diesem Dokument. In diesem Artikel konzentrieren wir uns auf technische Aspekte.

An diesem Punkt denken Sie vielleicht, dass es nur zwei Status gibt: aktiviert oder deaktiviert. Es gibt jedoch einige andere Zustände in Bezug auf Benachrichtigungen, die Sie berücksichtigen müssen.

Ein Diagramm, das die verschiedenen Überlegungen und den Status von Push in Chrome zeigt

Es gibt eine Reihe von APIs, die wir überprüfen müssen, bevor wir die Schaltfläche aktivieren. Wenn alles unterstützt wird, können wir unsere UI aktivieren und den Anfangszustand festlegen, um anzuzeigen, ob Push-Nachrichten abonniert wurden oder nicht.

Da die meisten dieser Prüfungen dazu führen, dass unsere UI deaktiviert wird, sollten Sie den Anfangszustand auf „Deaktiviert“ setzen. So lassen sich auch Verwirrungen vermeiden, wenn es ein Problem mit dem JavaScript auf deiner Seite gibt, z. B. wenn die JS-Datei nicht heruntergeladen werden kann oder der Nutzer JavaScript deaktiviert hat.

<button class="js-push-button" disabled>
    Enable Push Messages
</button>

Mit diesem Ausgangszustand können wir die oben beschriebenen Prüfungen in der Methode initialiseState() ausführen, also nachdem der Service Worker registriert wurde.

// Once the service worker is registered set the initial state
function initialiseState() {
    // Are Notifications supported in the service worker?
    if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
    console.warn('Notifications aren\'t supported.');
    return;
    }

    // Check the current Notification permission.
    // If its denied, it's a permanent block until the
    // user changes the permission
    if (Notification.permission === 'denied') {
    console.warn('The user has blocked notifications.');
    return;
    }

    // Check if push messaging is supported
    if (!('PushManager' in window)) {
    console.warn('Push messaging isn\'t supported.');
    return;
    }

    // We need the service worker registration to check for a subscription
    navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
    // Do we already have a push message subscription?
    serviceWorkerRegistration.pushManager.getSubscription()
        .then(function(subscription) {
        // Enable any UI which subscribes / unsubscribes from
        // push messages.
        var pushButton = document.querySelector('.js-push-button');
        pushButton.disabled = false;

        if (!subscription) {
            // We aren't subscribed to push, so set UI
            // to allow the user to enable push
            return;
        }

        // Keep your server in sync with the latest subscriptionId
        sendSubscriptionToServer(subscription);

        // Set your UI to show they have subscribed for
        // push messages
        pushButton.textContent = 'Disable Push Messages';
        isPushEnabled = true;
        })
        .catch(function(err) {
        console.warn('Error during getSubscription()', err);
        });
    });
}

Ein kurzer Überblick über diese Schritte:

  • Wir prüfen, ob showNotification im Prototyp „ServiceWorkerRegistration“ verfügbar ist. Andernfalls können wir keine Benachrichtigung von unserem Service Worker anzeigen, wenn eine Push-Nachricht eingeht.
  • Wir prüfen, wie der aktuelle Notification.permission lautet, um sicherzustellen, dass er nicht "denied" ist. Eine abgelehnte Berechtigung bedeutet, dass Sie erst Benachrichtigungen anzeigen können, wenn der Nutzer die Berechtigung im Browser manuell ändert.
  • Um zu prüfen, ob Push-Nachrichten unterstützt werden, prüfen wir, ob PushManager im Fensterobjekt verfügbar ist.
  • Schließlich haben wir mit pushManager.getSubscription() geprüft, ob wir bereits ein Abo haben oder nicht. In diesem Fall senden wir die Abodetails an unseren Server, um sicherzustellen, dass wir die richtigen Informationen haben, und stellen die UI so ein, dass Push-Nachrichten bereits aktiviert sind oder nicht. Welche Details das Aboobjekt enthält, erfährst du weiter unten in diesem Artikel.

Wir warten, bis navigator.serviceWorker.ready behoben ist, um nach einem Abo zu suchen und die Push-Schaltfläche zu aktivieren, da Sie erst Push-Nachrichten abonnieren können, nachdem der Service Worker aktiv ist.

Der nächste Schritt besteht darin, zu verarbeiten, wann der Nutzer Push-Nachrichten aktivieren möchte. Dazu müssen wir jedoch ein Google Developer Console-Projekt einrichten und einige Parameter zu unserem Manifest hinzufügen, um Firebase Cloud Messaging (FCM), ehemals Google Cloud Messaging (GCM) zu verwenden.

Ein Projekt in der Firebase Developer Console erstellen

Chrome verwendet FCM für das Senden und Zustellen von Push-Nachrichten. Um die FCM API nutzen zu können, müssen Sie jedoch ein Projekt in der Firebase Developer Console einrichten.

Die folgenden Schritte gelten speziell für Chrome, Opera für Android und den Samsung-Browser, in denen FCM verwendet wird. Wie dies in anderen Browsern funktioniert, erfahren Sie später in diesem Artikel.

Neues Firebase-Entwicklerprojekt erstellen

Erstellen Sie zuerst ein neues Projekt auf https://console.firebase.google.com/. Klicken Sie dazu auf „Neues Projekt erstellen“.

Screenshot des neuen Firebase-Projekts

Fügen Sie einen Projektnamen hinzu und erstellen Sie das Projekt. Sie werden dann zum Projekt-Dashboard weitergeleitet:

Firebase-Projekt-Startseite

Klicken Sie in diesem Dashboard oben links auf das Zahnrad neben dem Projektnamen und dann auf "Project Settings" (Projekteinstellungen).

Menü für Firebase-Projekteinstellungen

Klicken Sie auf der Seite „Einstellungen“ auf den Tab „Cloud Messaging“.

Firebase-Projekt: Cloud Messaging-Menü

Diese Seite enthält den API-Schlüssel für Push-Nachrichten, den wir später verwenden, und die Absender-ID, die wir im nächsten Abschnitt in das Web-App-Manifest eingeben müssen.

Web-App-Manifest hinzufügen

Für Push müssen wir eine Manifestdatei mit dem Feld gcm_sender_id hinzufügen, damit das Push-Abo erfolgreich ist. Dieser Parameter ist nur für Chrome, Opera für Android und den Samsung-Browser erforderlich, damit sie FCM / GCM verwenden können.

Die gcm_sender_id wird von diesen Browsern verwendet, wenn sie ein Nutzergerät mit FCM abonnieren. Das bedeutet, dass FCM das Gerät des Nutzers identifizieren und dafür sorgen kann, dass Ihre Absender-ID mit dem entsprechenden API-Schlüssel übereinstimmt und ob der Nutzer Ihrem Server das Senden von Push-Nachrichten erlaubt hat.

Nachfolgend finden Sie eine sehr einfache Manifestdatei:

{
    "name": "Push Demo",
    "short_name": "Push Demo",
    "icons": [{
        "src": "images/icon-192x192.png",
        "sizes": "192x192",
        "type": "image/png"
        }],
    "start_url": "/index.html?homescreen=1",
    "display": "standalone",
    "gcm_sender_id": "<Your Sender ID Here>"
}

Sie müssen den Wert gcm_sender_id auf die Absender-ID aus Ihrem Firebase-Projekt festlegen.

Nachdem Sie die Manifestdatei in Ihrem Projekt gespeichert haben (manifest.json ist ein guter Name), verweisen Sie im HTML-Code mit dem folgenden Tag im Header Ihrer Seite darauf.

<link rel="manifest" href="/manifest.json">

Wenn Sie mit diesen Parametern kein Webmanifest hinzufügen, wird beim Versuch, Push-Nachrichten für den Nutzer zu abonnieren, eine Ausnahme mit dem Fehler "Registration failed - no sender id provided" oder "Registration failed - permission denied" ausgegeben.

Push-Nachrichten abonnieren

Nachdem Sie nun ein Manifest eingerichtet haben, können Sie wieder zum JavaScript-Code Ihrer Website wechseln.

Zum Abonnieren müssen Sie die Methode subscribe() für das PushManager-Objekt aufrufen, auf das Sie über ServiceWorkerRegistration zugreifen.

Dadurch wird der Nutzer aufgefordert, Ihrer Ursprungsberechtigung zum Senden von Push-Benachrichtigungen zu erteilen. Ohne diese Berechtigung können Sie kein Abo abschließen.

Wenn das von der Methode subscribe() zurückgegebene Promise aufgelöst wird, erhalten Sie ein PushSubscription-Objekt, das einen Endpunkt enthält.

Der Endpunkt sollte für jeden Nutzer auf Ihrem Server gespeichert werden, da Sie ihn später zum Senden von Push-Nachrichten benötigen.

Mit dem folgenden Code wird der Nutzer für Push-Benachrichtigungen abonniert:

function subscribe() {
    // Disable the button so it can't be changed while
    // we process the permission request
    var pushButton = document.querySelector('.js-push-button');
    pushButton.disabled = true;

    navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
    serviceWorkerRegistration.pushManager.subscribe()
        .then(function(subscription) {
        // The subscription was successful
        isPushEnabled = true;
        pushButton.textContent = 'Disable Push Messages';
        pushButton.disabled = false;

        // TODO: Send the subscription.endpoint to your server
        // and save it to send a push message at a later date
        return sendSubscriptionToServer(subscription);
        })
        .catch(function(e) {
        if (Notification.permission === 'denied') {
            // The user denied the notification permission which
            // means we failed to subscribe and the user will need
            // to manually change the notification permission to
            // subscribe to push messages
            console.warn('Permission for Notifications was denied');
            pushButton.disabled = true;
        } else {
            // A problem occurred with the subscription; common reasons
            // include network errors, and lacking gcm_sender_id and/or
            // gcm_user_visible_only in the manifest.
            console.error('Unable to subscribe to push.', e);
            pushButton.disabled = false;
            pushButton.textContent = 'Enable Push Messages';
        }
        });
    });
}

Ihre Webanwendung ist nun bereit, eine Push-Nachricht zu empfangen. Es passiert jedoch nichts, bis wir unserer Service Worker-Datei einen Push-Ereignis-Listener hinzugefügt haben.

Service Worker-Push-Ereignis-Listener

Wenn eine Push-Nachricht empfangen wird (wird im nächsten Abschnitt erläutert, wie eine Push-Nachricht tatsächlich gesendet wird), wird in Ihrem Service Worker ein Push-Ereignis ausgelöst und Sie müssen eine Benachrichtigung anzeigen.

self.addEventListener('push', function(event) {
    console.log('Received a push message', event);

    var title = 'Yay a message.';
    var body = 'We have received a push message.';
    var icon = '/images/icon-192x192.png';
    var tag = 'simple-push-demo-notification-tag';

    event.waitUntil(
    self.registration.showNotification(title, {
        body: body,
        icon: icon,
        tag: tag
    })
    );
});

Dieser Code registriert einen Push-Ereignis-Listener und zeigt eine Benachrichtigung mit einem vordefinierten Titel, Text, Symbol und einem Benachrichtigungs-Tag an. Eine Feinheiten, die in diesem Beispiel hervorgehoben werden sollen, ist die Methode event.waitUntil(). Diese Methode nimmt ein Promise an und verlängert die Lebensdauer eines Event-Handlers (oder kann man sich so vorstellen, dass der Service Worker aktiv bleibt), bis das Promise gesetzt wird. In diesem Fall ist das an event.waitUntil übergebene Promise das zurückgegebene Promise von showNotification().

Das Benachrichtigungs-Tag dient als Kennung für eindeutige Benachrichtigungen. Wenn wir zwei Push-Nachrichten mit einer kurzen Verzögerung an denselben Endpunkt senden und Benachrichtigungen mit demselben Tag anzeigen, zeigt der Browser die erste Benachrichtigung an und ersetzt sie beim Empfang der Push-Nachricht durch die zweite.

Wenn Sie mehrere Benachrichtigungen gleichzeitig sehen möchten, verwenden Sie ein anderes oder gar kein Tag. Später in diesem Post sehen wir uns ein ausführlicheres Beispiel für die Anzeige einer Benachrichtigung an. Lassen Sie uns zunächst alles einfach halten und prüfen, ob diese Benachrichtigung beim Senden einer Push-Nachricht angezeigt wird.

Push-Nachrichten senden

Wir haben Push-Nachrichten abonniert und unser Service Worker kann eine Benachrichtigung anzeigen. Daher ist es an der Zeit, eine Push-Nachricht über FCM zu senden.

Dies gilt nur für Browser, die FCM verwenden.

Wenn Sie die Variable PushSubscription.endpoint an Ihren Server senden, ist der Endpunkt für FCM speziell. Es hat einen Parameter am Ende der URL, bei dem es sich um ein registration_id-Element handelt.

Ein Beispiel für einen Endpunkt wäre:

https://fcm.googleapis.com/fcm/send/APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP

Die FCM-URL lautet:

https://fcm.googleapis.com/fcm/send

registration_id wäre:

APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP

Dies gilt speziell für Browser, die FCM verwenden. In einem normalen Browser würden Sie einfach einen Endpunkt erhalten und diesen Endpunkt standardmäßig aufrufen. Das Ganze funktioniert dann unabhängig von der URL.

Das bedeutet, dass Sie auf Ihrem Server prüfen müssen, ob der Endpunkt für FCM vorgesehen ist, und ggf. die Registrierungs-ID extrahieren. In Python könnten Sie dazu etwas wie folgt machen:

if endpoint.startswith('https://fcm.googleapis.com/fcm/send'):
    endpointParts = endpoint.split('/')
    registrationId = endpointParts[len(endpointParts) - 1]

    endpoint = 'https://fcm.googleapis.com/fcm/send'

Sobald Sie die Registrierungs-ID haben, können Sie die FCM API aufrufen. Referenzdokumente zur FCM API

Die wichtigsten Aspekte beim Aufrufen von FCM sind folgende:

  • Beim Aufruf der API muss ein Authorization-Header mit dem Wert key=&lt;YOUR_API_KEY&gt; festgelegt werden. Dabei ist &lt;YOUR_API_KEY&gt; der API-Schlüssel aus dem Firebase-Projekt.
    • Der API-Schlüssel wird von FCM verwendet, um die geeignete Absender-ID zu finden, zu prüfen, ob der Nutzer die Berechtigung für Ihr Projekt erteilt hat, und um schließlich sicherzustellen, dass die IP-Adresse des Servers für dieses Projekt auf die Zulassungsliste gesetzt wurde.
  • Einen geeigneten Content-Type-Header mit dem Wert application/json oder application/x-www-form-urlencoded;charset=UTF-8, je nachdem, ob Sie die Daten als JSON- oder Formulardaten senden.
  • Ein Array mit registration_ids: Dies sind die Registrierungs-IDs, die Sie aus den Endpunkten Ihrer Nutzer extrahieren.

Weitere Informationen zum Senden von Push-Nachrichten von Ihrem Server finden Sie in der Dokumentation zum Senden von Push-Nachrichten von Ihrem Server. Um Ihren Service Worker schnell zu überprüfen, können Sie mit cURL eine Push-Nachricht an Ihren Browser senden.

Ersetzen Sie &lt;YOUR_API_KEY&gt; und &lt;YOUR_REGISTRATION_ID&gt; in diesem cURL-Befehl durch Ihren eigenen und führen Sie ihn über ein Terminal aus.

Sie sollten folgende Benachrichtigung sehen:

    curl --header "Authorization: key=<YOUR_API_KEY>" --header
    "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d
    "{\"registration_ids\":[\"<YOUR_REGISTRATION_ID>\"]}"
Beispiel für eine Push-Nachricht von Chrome für Android

Denken Sie bei der Entwicklung Ihrer Back-End-Logik daran, dass der Autorisierungsheader und das Format des POST-Texts spezifisch für den FCM-Endpunkt sind. Ermitteln Sie daher, wann der Endpunkt für FCM bestimmt ist, und fügen Sie den Header und formatieren Sie den POST-Text bedingt hinzu. Für andere Browser (und hoffentlich für Chrome) müssen Sie das Web Push Protocol implementieren.

Ein Nachteil der aktuellen Implementierung der Push API in Chrome besteht darin, dass Sie mit einer Push-Nachricht keine Daten senden können. Nein, nichts. Der Grund dafür ist, dass in einer zukünftigen Implementierung Nutzlastdaten auf Ihrem Server verschlüsselt werden müssen, bevor sie an einen Push-Messaging-Endpunkt gesendet werden. Auf diese Weise kann der Endpunkt, egal wie Push-Anbieter, nicht ohne Weiteres den Inhalt der Push-Nachricht sehen. Dies schützt auch vor anderen Sicherheitslücken wie schlechter Validierung von HTTPS-Zertifikaten und Man-in-the-Middle-Angriffen zwischen Ihrem Server und dem Push-Anbieter. Diese Verschlüsselung wird jedoch noch nicht unterstützt. In der Zwischenzeit müssen Sie einen Abruf durchführen, um Informationen zu erhalten, die zum Ausfüllen einer Benachrichtigung erforderlich sind.

Vollständigeres Beispiel für ein Push-Ereignis

Die Benachrichtigung, die wir bisher gesehen haben, ist ziemlich einfach. Was die Beispiele angeht, lässt sie sich nicht mit einem realen Anwendungsfall abdecken.

Realistisch gesehen möchten die meisten Nutzer einige Informationen von ihrem Server abrufen, bevor sie die Benachrichtigung anzeigen. Dies können Daten sein, um den Titel und die Nachricht der Benachrichtigung mit etwas Bestimmtem zu füllen oder einen Schritt weiter zu gehen und einige Seiten oder Daten im Cache zu speichern, sodass beim Klicken des Nutzers auf die Benachrichtigung alles sofort verfügbar ist, wenn der Browser geöffnet wird – selbst wenn das Netzwerk zu diesem Zeitpunkt nicht verfügbar ist.

Im folgenden Code rufen wir einige Daten von einer API ab, konvertieren die Antwort in ein Objekt und verwenden es zum Ausfüllen der Benachrichtigung.

self.addEventListener('push', function(event) {
    // Since there is no payload data with the first version
    // of push messages, we'll grab some data from
    // an API and use it to populate a notification
    event.waitUntil(
    fetch(SOME_API_ENDPOINT).then(function(response) {
        if (response.status !== 200) {
        // Either show a message to the user explaining the error
        // or enter a generic message and handle the
        // onnotificationclick event to direct the user to a web page
        console.log('Looks like there was a problem. Status Code: ' + response.status);
        throw new Error();
        }

        // Examine the text in the response
        return response.json().then(function(data) {
        if (data.error || !data.notification) {
            console.error('The API returned an error.', data.error);
            throw new Error();
        }

        var title = data.notification.title;
        var message = data.notification.message;
        var icon = data.notification.icon;
        var notificationTag = data.notification.tag;

        return self.registration.showNotification(title, {
            body: message,
            icon: icon,
            tag: notificationTag
        });
        });
    }).catch(function(err) {
        console.error('Unable to retrieve data', err);

        var title = 'An error occurred';
        var message = 'We were unable to get the information for this push message';
        var icon = URL_TO_DEFAULT_ICON;
        var notificationTag = 'notification-error';
        return self.registration.showNotification(title, {
            body: message,
            icon: icon,
            tag: notificationTag
        });
    })
    );
});

Wir möchten noch einmal darauf hinweisen, dass event.waitUntil() ein Versprechen annimmt, das zu dem von showNotification() zurückgegebenen Versprechen führt. Das bedeutet, dass unser Event-Listener erst beendet wird, wenn der asynchrone fetch()-Aufruf abgeschlossen ist und die Benachrichtigung angezeigt wird.

Selbst wenn ein Fehler vorliegt, wird eine Benachrichtigung angezeigt. Andernfalls zeigt Chrome seine eigene allgemeine Benachrichtigung an.

Öffnen einer URL, wenn der Nutzer auf eine Benachrichtigung klickt

Wenn der Nutzer auf eine Benachrichtigung klickt, wird in Ihrem Service Worker ein notificationclick-Ereignis gesendet. Innerhalb des Handlers können Sie geeignete Aktionen ausführen, z. B. einen Tab hervorheben oder ein Fenster mit einer bestimmten URL öffnen:

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('/');
        }
    })
    );
});

In diesem Beispiel wird im Browser das Stammverzeichnis des Ursprungs der Website geöffnet. Dabei wird ein vorhandener Tab mit demselben Ursprung hervorgehoben, sofern vorhanden, und ansonsten ein neuer Tab geöffnet.

In diesem Beitrag geht es um einige der Dinge, die du mit der Notification API tun kannst.

Nutzergerät kündigen

Sie haben das Gerät eines Nutzers abonniert und dieser erhält Push-Nachrichten. Wie können Sie das Abo für einen Nutzer beenden?

Zum Abbestellen eines Nutzergeräts müssen Sie vor allem die Methode unsubscribe() für das PushSubscription-Objekt aufrufen und den Endpunkt von Ihren Servern entfernen, damit Sie keine Push-Nachrichten senden, von denen Sie wissen, dass sie nicht empfangen werden. Der folgende Code tut genau dies:

function unsubscribe() {
    var pushButton = document.querySelector('.js-push-button');
    pushButton.disabled = true;

    navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
    // To unsubscribe from push messaging, you need get the
    // subscription object, which you can call unsubscribe() on.
    serviceWorkerRegistration.pushManager.getSubscription().then(
        function(pushSubscription) {
        // Check we have a subscription to unsubscribe
        if (!pushSubscription) {
            // No subscription object, so set the state
            // to allow the user to subscribe to push
            isPushEnabled = false;
            pushButton.disabled = false;
            pushButton.textContent = 'Enable Push Messages';
            return;
        }

        var subscriptionId = pushSubscription.subscriptionId;
        // TODO: Make a request to your server to remove
        // the subscriptionId from your data store so you
        // don't attempt to send them push messages anymore

        // We have a subscription, so call unsubscribe on it
        pushSubscription.unsubscribe().then(function(successful) {
            pushButton.disabled = false;
            pushButton.textContent = 'Enable Push Messages';
            isPushEnabled = false;
        }).catch(function(e) {
            // We failed to unsubscribe, this can lead to
            // an unusual state, so may be best to remove
            // the users data from your data store and
            // inform the user that you have done so

            console.log('Unsubscription error: ', e);
            pushButton.disabled = false;
            pushButton.textContent = 'Enable Push Messages';
        });
        }).catch(function(e) {
        console.error('Error thrown while unsubscribing from push messaging.', e);
        });
    });
}

Das Abonnement auf dem neuesten Stand halten

Abos können zwischen FCM und deinem Server nicht mehr synchron sein. Achten Sie darauf, dass Ihr Server den Antworttext der POST-Anfrage der FCM API parst und nach error:NotRegistered- und canonical_id-Ergebnissen sucht, wie in der FCM-Dokumentation erläutert.

Abos können auch zwischen dem Service Worker und Ihrem Server nicht synchron sein. Nach erfolgreichem Abonnieren bzw. Kündigen eines Abos kann eine unzuverlässige Netzwerkverbindung beispielsweise verhindern, dass Sie Ihren Server aktualisieren, oder ein Nutzer kann die Berechtigung für Benachrichtigungen widerrufen, wodurch ein automatisches Abbestellen ausgelöst wird. Prüfen Sie in solchen Fällen das Ergebnis von serviceWorkerRegistration.pushManager.getSubscription() regelmäßig (z.B. beim Seitenaufbau) und synchronisieren Sie es mit dem Server. Sie haben auch die Möglichkeit, ein Abo automatisch neu abzuschließen, wenn Sie kein Abo mehr haben und „Notification.permission“ == 'granted' sein sollen.

In sendSubscriptionToServer() müssen Sie beim Aktualisieren von endpoint berücksichtigen, wie mit fehlgeschlagenen Netzwerkanfragen umgegangen werden soll. Eine Lösung besteht darin, den Status von endpoint in einem Cookie zu erfassen, um festzustellen, ob Ihr Server die neuesten Details benötigt oder nicht.

Alle oben genannten Schritte führen zu einer vollständigen Implementierung von Push-Benachrichtigungen im Web in Chrome 46. Es gibt noch spezielle Funktionen, die das Ganze einfacher machen (z. B. eine Standard-API zum Auslösen von Push-Nachrichten). Mit dieser Version können Sie jedoch schon heute Push-Nachrichten in Ihre Webanwendungen einbinden.

Webanwendung debuggen

Bei der Implementierung von Push-Nachrichten sind Programmfehler an einem von zwei Orten zu finden: auf Ihrer Seite oder im Service Worker.

Fehler auf der Seite können mit den DevTools behoben werden. Sie haben zwei Möglichkeiten, um Service Worker-Probleme zu beheben:

  1. Gehen Sie zu chrome://Inspect > Service Worker. Diese Ansicht bietet außer den aktuell ausgeführten Service Workern nur wenige Informationen.
  2. Rufen Sie chrome://serviceworker-internals auf, um den Status der Service Worker sowie eventuelle Fehler anzusehen. Diese Seite ist temporär, bis die Entwicklertools über ähnliche Funktionen verfügen.

Einer der besten Tipps für alle, die noch nicht mit Service Workern vertraut sind, ist die Verwendung des Kontrollkästchens "Open DevTools Windows and Pairing JavaScript-Ausführung beim Service Worker-Start zum Debugging". Wenn Sie dieses Kästchen anklicken, wird beim Start des Service Workers ein Haltepunkt hinzugefügt und die Ausführung pausieren. So können Sie das Service Worker-Skript fortsetzen oder Schritt für Schritt durchgehen und prüfen, ob Probleme auftreten.

Screenshot, der zeigt, wo sich das Kästchen „Ausführung pausieren“ auf „serviceworker-internals“ befindet.

Bei einem Problem zwischen FCM und dem Push-Ereignis Ihres Service Workers können Sie nicht viel tun, um das Problem zu beheben, da Sie nicht feststellen können, ob Chrome etwas empfangen hat. Wichtig ist, dass die Antwort von FCM erfolgreich ist, wenn Ihr Server einen API-Aufruf durchführt. Sie sieht ungefähr so aus:

{"multicast_id":1234567890,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1234567890"}]}

Sehen Sie sich die Antwort "success": 1 an. Wenn stattdessen ein Fehler angezeigt wird, liegt ein Fehler mit der FCM-Registrierungs-ID vor und die Push-Nachricht wird nicht an Chrome gesendet.

Fehler in Service Workern in Chrome für Android beheben

Derzeit ist die Fehlerbehebung für Service Worker in Chrome für Android nicht offensichtlich. Gehen Sie zu chrome://inspect, suchen Sie Ihr Gerät und suchen Sie nach einem Listenelement mit dem Namen "Worker pid:....", das die URL Ihres Service Workers enthält.

Screenshot, der zeigt, wo sich die Service Worker in Chrome Inspect befinden

UX für Push-Benachrichtigungen

Das Chrome-Team hat ein Dokument mit Best Practices für Push-Benachrichtigungen zusammengestellt sowie ein Dokument zu einigen Grenzfällen bei der Arbeit mit Push-Benachrichtigungen zusammengestellt.

Die Zukunft von Push-Nachrichten in Chrome und im offenen Web

In diesem Abschnitt werden einige Details zu einigen Chrome-spezifischen Teilen dieser Implementierung beschrieben, die Sie kennen sollten und wie sie sich von anderen Browserimplementierungen unterscheidet.

Web-Push-Protokoll und -Endpunkte

Das Schöne am Push API-Standard ist, dass Sie in der Lage sein sollten, den Endpunkt an Ihren Server weiterzuleiten und Push-Nachrichten zu senden, indem Sie das Web-Push-Protokoll implementieren.

Das Web Push Protocol ist ein neuer Standard, den Push-Anbieter implementieren können, sodass sich Entwickler keine Gedanken darüber machen müssen, wer der Push-Anbieter ist. Dadurch müssen sich so keine API-Schlüssel registrieren und speziell formatierte Daten wie bei FCM senden.

Chrome war der erste Browser, in dem die Push API implementiert wurde, und FCM unterstützt das Web Push Protocol nicht. Deshalb benötigt Chrome gcm_sender_id und Sie müssen die Restful API für FCM verwenden.

Das Ziel von Chrome ist es, das Web-Push-Protokoll mit Chrome und FCM zu verwenden.

Bis dahin müssen Sie den Endpunkt „https://fcm.googleapis.com/fcm/send“ erkennen und getrennt von anderen Endpunkten verarbeiten, d.h. die Nutzlastdaten auf eine bestimmte Weise formatieren und den Autorisierungsschlüssel hinzufügen.

So implementieren Sie das Web-Push-Protokoll

Firefox Nightly arbeitet derzeit an Push und wird wahrscheinlich der erste Browser sein, der das Web Push Protocol implementiert.

Häufig gestellte Fragen

Wo sind die Spezifikationen?

https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ https://w3c.github.io/push-api/ https://notifications.spec.whatwg.org/

Kann ich doppelte Benachrichtigungen verhindern, wenn meine Webpräsenz mehrere Ursprünge hat oder ich sowohl eine Web- als auch eine native Präsenz habe?

Es gibt derzeit keine Lösung für dieses Problem, aber Sie können den Fortschritt in Chromium verfolgen.

Das ideale Szenario wäre, eine Art von ID für das Gerät eines Nutzers zu haben und dann serverseitig die Abo-IDs der nativen App und der Web-App abzugleichen und zu entscheiden, an welche davon eine Push-Nachricht gesendet werden soll. Sie können dies über Bildschirmgröße, Gerätemodell und die gemeinsame Nutzung eines generierten Schlüssels zwischen der Web-App und der nativen App tun. Aber jeder Ansatz hat Vor- und Nachteile.

Warum benötige ich eine gcm_sender_id?

Dies ist erforderlich, damit Chrome, Opera für Android und der Samsung-Browser die Firebase Cloud Messaging API (FCM) verwenden können. Ziel ist es, das Web Push Protocol zu verwenden, wenn der Standard fertiggestellt ist und FCM ihn unterstützen kann.

Warum werden keine WebSockets oder vom Server gesendete Ereignisse (EventSource) verwendet?

Push-Nachrichten haben den Vorteil, dass der Service Worker auch dann geweckt ist, wenn Ihre Seite geschlossen ist, und eine Benachrichtigung anzeigen kann. Die Verbindung von WebSockets und EventSource wird geschlossen, wenn die Seite oder der Browser geschlossen wird.

Was ist, wenn ich keine Bereitstellung von Hintergrundereignissen benötige?

Wenn Sie keine Hintergrundübermittlung benötigen, sind WebSockets eine sehr gute Option.

Wann kann ich Push-Nachrichten verwenden, ohne dass Benachrichtigungen angezeigt werden (z.B. Push-Benachrichtigungen im Hintergrund)?

Es gibt noch keinen zeitlichen Rahmen dafür, wann dies verfügbar sein wird, aber es ist eine Absicht, die Hintergrundsynchronisierung zu implementieren. Auch wenn dies weder beschlossen noch spezifiziert ist, wird erörtert, die stille Push-Funktion mit Hintergrundsynchronisierung zu aktivieren.

Warum ist dafür HTTPS erforderlich? Wie kann ich das in der Entwicklungsphase umgehen?

Service Worker benötigen sichere Ursprünge, damit das Service Worker-Skript aus dem vorgesehenen Ursprung stammt und nicht von einem Man-in-the-Middle-Angriff stammt. Derzeit bedeutet dies, dass HTTPS auf Live-Websites verwendet wird, obwohl localhost während der Entwicklung funktioniert.

Wie wird Browser unterstützt?

Google Chrome unterstützt in seiner stabilen Version und Mozilla arbeitet derzeit an Firefox Nightly. Weitere Informationen finden Sie unter Fehler in der Push API implementieren. Außerdem können Sie hier die Implementierung von Benachrichtigungen verfolgen.

Kann ich eine Benachrichtigung nach einem bestimmten Zeitraum entfernen?

Das ist derzeit nicht möglich, aber wir planen, die Unterstützung hinzuzufügen, um eine Liste der derzeit sichtbaren Benachrichtigungen zu erhalten. Wenn Sie einen Anwendungsfall haben, um eine Ablaufzeit für Benachrichtigungen festzulegen, nachdem sie angezeigt wurde, würden wir gerne wissen, was das ist. Fügen Sie also bitte einen Kommentar hinzu und wir leiten ihn an das Chrome-Team weiter.

Wenn Sie das Senden einer Push-Benachrichtigung an den Nutzer nur nach einem bestimmten Zeitraum beenden möchten und es keine Rolle spielt, wie lange die Benachrichtigung sichtbar bleibt, können Sie den FCM-Parameter für die Gültigkeitsdauer (ttl) verwenden. Weitere Informationen finden Sie hier.

Welche Einschränkungen gibt es bei Push-Benachrichtigungen in Chrome?

Es gibt einige Einschränkungen, die in diesem Post beschrieben werden:

  • Die Nutzung von CCM in Chrome als Push-Dienst führt zu einer Reihe von proprietären Anforderungen. Wir arbeiten gemeinsam daran, dass einige dieser Probleme behoben werden können.
  • Sie müssen eine Benachrichtigung anzeigen, wenn Sie eine Push-Nachricht erhalten.
  • Für Chrome auf Desktop-Computern gilt jedoch, dass Push-Nachrichten nicht empfangen werden, wenn Chrome nicht ausgeführt wird. Dies unterscheidet sich von ChromeOS und Android, wo Push-Nachrichten immer empfangen werden.

Sollten wir nicht die Permissions API verwenden?

Die Permission API ist in Chrome implementiert, steht aber nicht unbedingt in allen Browsern zur Verfügung. Weitere Informationen

Warum öffnet Chrome den vorherigen Tab nicht, wenn ich auf eine Benachrichtigung klicke?

Dieses Problem betrifft nur Seiten, die derzeit nicht von einem Service Worker kontrolliert werden. Weitere Informationen

Was passiert, wenn eine Benachrichtigung zum Zeitpunkt des Empfangs der Push-Benachrichtigung auf dem Gerät des Nutzers veraltet ist?

Sie müssen immer eine Benachrichtigung anzeigen, wenn Sie eine Push-Nachricht erhalten. In einem Szenario, in dem Sie eine Benachrichtigung senden möchten, dies aber nur für einen bestimmten Zeitraum nützlich ist, können Sie den Parameter „time_to_live“ für CCM verwenden, damit FCM die Push-Nachricht nach Ablauf der Ablaufzeit nicht sendet.

Weitere Informationen

Was passiert, wenn ich 10 Push-Nachrichten sende, aber nur eine Push-Nachricht erhalten möchte?

Der FCM hat einen „Minimierschlüssel“-Parameter, mit dem Sie FCM anweisen können, jede ausstehende Nachricht mit demselben „Minimierschlüssel“ durch die neue Nachricht zu ersetzen.

Weitere Informationen