Push-Benachrichtigungen im offenen Web

Matt Gaunt

Wenn Sie Entwickler fragen, welche Funktionen von Mobilgeräten im Web fehlen, stehen Push-Benachrichtigungen immer ganz oben auf der Liste.

Mit Push-Benachrichtigungen können Ihre Nutzer zeitnah Updates von ihren Lieblingswebsites erhalten und sie mit individuellen, ansprechenden Inhalten wieder auf sich aufmerksam machen.

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, darunter Web App-Manifeste und Service Workers. In diesem Beitrag schauen wir uns jede dieser Technologien an, aber nur das absolute Minimum für Push-Nachrichten. Weitere Informationen zu einigen anderen Manifesten und den Offlinefunktionen von Service Workern finden Sie unter den obigen Links.

Außerdem schauen wir uns an, was der API in zukünftigen Versionen von Chrome hinzugefügt wird. Außerdem gibt es noch häufig gestellte Fragen.

Push-Benachrichtigungen für Chrome implementieren

In diesem Abschnitt werden die einzelnen Schritte beschrieben, die Sie zur Unterstützung von Push-Nachrichten in Ihrer Webanwendung ausführen müssen.

Service Worker registrieren

Es besteht die Abhängigkeit davon, dass ein Service Worker Push-Nachrichten für das Web implementiert. Der Grund dafür ist, dass der Browser beim Empfang einer Push-Nachricht einen Service Worker starten kann, der im Hintergrund ausgeführt wird, ohne dass eine Seite geöffnet ist, und ein Ereignis auslösen kann, damit Sie entscheiden können, wie mit dieser Push-Nachricht umgegangen werden soll.

Im Folgenden finden Sie ein Beispiel dafür, wie Sie einen Service Worker in Ihrer Webanwendung registrieren. Wenn die Registrierung erfolgreich abgeschlossen wurde, rufen wir initialiseState() auf, was in Kürze behandelt wird.

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

Der Schaltflächen-Klick-Handler abonniert oder abbestellt den Nutzer für Push-Nachrichten. isPushEnabled ist eine globale Variable, die einfach verfolgt, ob Push-Nachrichten derzeit abonniert sind oder nicht. Auf diese wird in allen Code-Snippets verwiesen.

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

Anfangszustand einrichten

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

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

Nutzer erwarten, dass Push-Nachrichten für Ihre Website über eine einfache UI aktiviert oder deaktiviert werden können, und sie erwarten, dass sie über alle Änderungen auf dem Laufenden bleibt. Anders ausgedrückt: Wenn Push-Nachrichten für Ihre Website aktiviert sind, die Website eine Woche später wieder verlässt, sollte in Ihrer UI angezeigt werden, dass Push-Nachrichten bereits aktiviert sind.

In diesem Dokument finden Sie einige UX-Richtlinien. In diesem Artikel konzentrieren wir uns auf die technischen Aspekte.

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

Ein Diagramm mit den verschiedenen Überlegungen und dem Status der Push-Übertragung in Chrome

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 so festlegen, dass angezeigt wird, ob Push-Nachrichten abonniert sind oder nicht.

Da die meisten dieser Prüfungen dazu führen, dass unsere UI deaktiviert wird, sollten Sie den Anfangsstatus auf „Deaktiviert“ setzen. So lassen sich auch Unklarheiten vermeiden, falls es ein Problem mit dem JavaScript Ihrer Seite gibt, zum Beispiel, 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 initialiseState()-Methode ausführen, d.h. nachdem unser 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);
        });
    });
}

Kurze Übersicht über diese Schritte:

  • Wir prüfen, ob showNotification im ServiceWorkerRegistration-Prototyp verfügbar ist. Andernfalls können wir keine Benachrichtigung von unserem Service Worker anzeigen, wenn eine Push-Nachricht empfangen wird.
  • Wir prüfen den aktuellen Notification.permission, um sicherzustellen, dass er nicht "denied" ist. Eine abgelehnte Berechtigung bedeutet, dass Sie keine Benachrichtigungen anzeigen können, bis 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. In diesem Fall senden wir die Abodetails an unseren Server, damit wir die richtigen Informationen haben. Außerdem wird in der Benutzeroberfläche angezeigt, ob Push-Nachrichten bereits aktiviert sind oder nicht. Wir sehen uns später in diesem Artikel an, welche Details das Aboobjekt enthält.

Wir warten, bis navigator.serviceWorker.ready aufgelöst wird, um ein Abo zu prüfen und die Push-Schaltfläche zu aktivieren, da Sie erst nach dem Aktivieren des Service Workers Push-Nachrichten abonnieren können.

Der nächste Schritt besteht darin, zu prüfen, wann der Nutzer Push-Nachrichten aktivieren möchte. Zuvor müssen wir jedoch ein Google Developer Console-Projekt einrichten und unserem Manifest einige Parameter hinzufügen, um Firebase Cloud Messaging (FCM) zu verwenden, das früher als Google Cloud Messaging (GCM) bezeichnet wurde.

Projekt in der Firebase Developer Console erstellen

Chrome nutzt FCM für das Senden und Senden von Push-Nachrichten. Wenn Sie die FCM API verwenden möchten, 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 Samsung-Browser, die FCM verwenden. Wie dies in anderen Browsern funktioniert, erfahren Sie weiter unten in diesem Artikel.

Neues Firebase-Entwicklerprojekt erstellen

Erstellen Sie zunächst auf https://console.firebase.google.com/ ein neues Projekt. Klicken Sie dazu auf "Neues Projekt erstellen".

Screenshot eines neuen Firebase-Projekts

Geben Sie einen Projektnamen ein, erstellen Sie das Projekt und Sie werden 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ü mit Firebase-Projekteinstellungen

Klicken Sie auf der Einstellungsseite auf den Tab "Cloud Messaging".

Cloud Messaging-Menü für Firebase-Projekt

Diese Seite enthält den API-Schlüssel für Push-Nachrichten, den wir später verwenden, sowie 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 FCM / GCM verwendet werden kann.

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

Im Folgenden 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>"
}

Legen Sie für gcm_sender_id die Absender-ID aus Ihrem Firebase-Projekt fest.

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 kein Webmanifest mit diesen Parametern 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-Benachrichtigungen abonnieren

Nachdem Sie nun ein Manifest eingerichtet haben, können Sie zum JavaScript Ihrer Websites zurückkehren.

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

Dadurch wird der Nutzer aufgefordert, Ihrem Ursprung die Berechtigung zum Senden von Push-Benachrichtigungen zu erteilen. Ohne diese Berechtigung kannst du kein Abo abschließen.

Wenn das von der Methode Subscribe() zurückgegebene promise aufgelöst wird, erhältst du ein PushSubscription-Objekt, das einen Endpunkt enthält.

Der Endpunkt sollte für jeden Nutzer auf Ihrem Server gespeichert werden, da er später Push-Nachrichten senden muss.

Mit dem folgenden Code wird der Nutzer für Push-Nachrichten 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 kann nun eine Push-Nachricht empfangen. Es geschieht jedoch nichts, bis wir unserer Service Worker-Datei einen Push-Ereignis-Listener hinzufügen.

Service Worker-Push-Ereignis-Listener

Beim Empfang einer Push-Nachricht wird im Service Worker ein Push-Ereignis ausgelöst. Danach müssen Sie eine Benachrichtigung anzeigen lassen. Im nächsten Abschnitt erfahren Sie, wie eine Push-Nachricht tatsächlich gesendet wird.

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
    })
    );
});

Mit diesem Code wird ein Push-Ereignis-Listener registriert und eine Benachrichtigung mit einem vordefinierten Titel, Textkörper, Symbol und einem Benachrichtigungs-Tag angezeigt. Eine Feinheiten, die bei diesem Beispiel hervorgehoben werden sollten, ist die Methode event.waitUntil(). Bei dieser Methode wird ein Promise angenommen und die Lebensdauer eines Event-Handlers verlängert (oder der Service Worker aufrechterhalten), bis das Promise berechnet wurde. In diesem Fall ist das an event.waitUntil übergebene Promise das von showNotification() zurückgegebene Promise.

Das Benachrichtigungs-Tag dient als Kennung für eindeutige Benachrichtigungen. Wenn zwei Push-Nachrichten mit einer kurzen Verzögerung an denselben Endpunkt gesendet werden und Benachrichtigungen mit demselben Tag angezeigt werden, zeigt der Browser die erste Benachrichtigung an und ersetzt sie durch die zweite, sobald die Push-Nachricht empfangen wird.

Wenn Sie mehrere Benachrichtigungen gleichzeitig anzeigen möchten, verwenden Sie ein anderes oder gar kein Tag. Ein ausführlicheres Beispiel für das Einblenden einer Benachrichtigung sehen wir uns später in diesem Beitrag an. Halten wir es vorerst einfach und prüfen Sie, ob beim Senden einer Push-Nachricht diese Benachrichtigung angezeigt wird.

Senden einer Push-Nachricht

Wir haben Push-Nachrichten abonniert und unser Service Worker ist bereit, eine Benachrichtigung anzuzeigen. Deshalb 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. Am Ende der URL befindet sich ein Parameter registration_id.

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

Der registration_id wäre dann:

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

Dies gilt speziell für Browser, die FCM verwenden. In einem normalen Browser erhalten Sie einfach einen Endpunkt, der standardmäßig aufgerufen wird und unabhängig von der URL funktioniert.

Das bedeutet, dass Sie auf Ihrem Server prüfen müssen, ob der Endpunkt für FCM bestimmt ist. Wenn ja, müssen Sie die „registration_id“ extrahieren. In Python könnten Sie dies wie folgt tun:

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 du die Registrierungs-ID hast, kannst du die FCM API aufrufen. Referenzdokumente zur FCM API

Die wichtigsten Aspekte, die beim Aufrufen von FCM beachtet werden sollten, sind:

  • 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 entsprechende Absender-ID zu finden, sicherzustellen, dass der Nutzer die Berechtigung für Ihr Projekt erteilt hat, und schließlich dafür zu sorgen, dass die IP-Adresse des Servers für dieses Projekt auf die Zulassungsliste gesetzt wurde.
  • Einen geeigneten Content-Type-Header von 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 von den Endpunkten Ihrer Nutzer extrahieren.

Informationen zum Senden von Push-Nachrichten von Ihrem Server finden Sie in der Dokumentation. Wenn Sie den Service Worker schnell überprüfen möchten, 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 eine brillante 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 beim Entwickeln der Back-End-Logik daran, dass der Autorisierungsheader und das Format des POST-Textes spezifisch für den FCM-Endpunkt sind. Ermitteln Sie daher, wann der Endpunkt für FCM ist, und fügen Sie den Header bedingt hinzu und formatieren Sie den POST-Text. Für andere Browser – und hoffentlich in Zukunft für Chrome – müssen Sie das Web Push Protocol implementieren.

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

Beispiel für ein umfassenderes Push-Ereignis

Die Benachrichtigung, die wir bisher erhalten haben, ist ziemlich einfach. Was die Beispiele angeht, ist sie ziemlich schlecht, um einen realen Anwendungsfall abzudecken.

Realistisch gesehen werden die meisten Nutzer einige Informationen von ihrem Server abrufen wollen, bevor die Benachrichtigung angezeigt wird. Dabei kann es sich um Daten handeln, um den Benachrichtigungstitel und die Nachricht mit einem bestimmten Inhalt zu füllen, oder um einen Schritt weiter zu gehen und einige Seiten oder Daten im Cache zu speichern. Wenn der Nutzer auf die Benachrichtigung klickt, ist alles sofort verfügbar, wenn der Browser geöffnet wird – auch 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 für unsere 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 betonen, dass event.waitUntil() ein Promise akzeptiert, das zu dem von showNotification() zurückgegebenen Promise führt. Das bedeutet, dass unser Event-Listener erst beendet wird, wenn der asynchrone fetch()-Aufruf abgeschlossen und die Benachrichtigung angezeigt wird.

Du wirst feststellen, dass wir auch dann eine Benachrichtigung anzeigen, wenn ein Fehler vorliegt. Andernfalls zeigt Chrome eine eigene allgemeine Benachrichtigung an.

URL öffnen, wenn der Nutzer auf eine Benachrichtigung klickt

Wenn der Nutzer auf eine Benachrichtigung klickt, wird ein notificationclick-Ereignis in Ihrem Service Worker gesendet. Innerhalb Ihres Handlers können Sie die entsprechende Aktion ausführen, z. B. einen Tab fokussieren 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 Websiteursprungs geöffnet. Dazu wird ein vorhandener Tab mit demselben Ursprung (falls vorhanden) hervorgehoben und ansonsten ein neuer geöffnet.

Hier finden Sie einen Beitrag zu den Verwendungsmöglichkeiten der Notification API.

Abo für ein Nutzergerät beenden

Sie haben das Gerät eines Nutzers abonniert und er erhält Push-Nachrichten. Wie können Sie diese Nachrichten abbestellen?

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

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);
        });
    });
}

Abonnement auf dem neuesten Stand halten

Abos können zwischen FCM und Ihrem Server nicht mehr synchron sein. Achte darauf, dass dein Server den Antworttext der Sende-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 mehr synchron sein. Wenn du beispielsweise ein erfolgreiches Abonnieren/Abbestellen abgeschlossen hast, kannst du aufgrund einer instabilen Netzwerkverbindung deinen Server nicht mehr aktualisieren. Oder ein Nutzer widerruft möglicherweise die Berechtigung für Benachrichtigungen, die ein automatisches Abbestellen auslöst. Prüfen Sie in solchen Fällen regelmäßig das Ergebnis von serviceWorkerRegistration.pushManager.getSubscription() (z.B. beim Seitenaufbau) und synchronisieren Sie es mit dem Server. Sie können auch automatisch ein Abo abschließen, wenn Sie kein Abo mehr haben und keine Notification.permission == 'granted' mehr sind.

In sendSubscriptionToServer() müssen Sie berücksichtigen, wie Sie mit fehlgeschlagenen Netzwerkanfragen umgehen, wenn Sie endpoint aktualisieren. Eine Lösung besteht darin, den Status von endpoint in einem Cookie zu verfolgen, um festzustellen, ob Ihr Server die neuesten Details benötigt.

Alle oben genannten Schritte führen zu einer vollständigen Implementierung von Push-Benachrichtigungen im Web in Chrome 46. Es gibt immer noch Spezifikationsfunktionen, die die Arbeit erleichtern (z. B. eine Standard-API zum Auslösen von Push-Nachrichten). Mit dieser Version können Sie jedoch schon heute damit beginnen, Push-Nachrichten in Ihre Webanwendungen zu integrieren.

Fehler in Ihrer Webanwendung beheben

Bei der Implementierung von Push-Nachrichten treten Fehler an einem von zwei Orten auf: auf Ihrer Seite oder Ihrem Service Worker.

Fehler auf der Seite können mit den DevTools behoben werden. Zum Beheben von Service Worker-Problemen haben Sie zwei Möglichkeiten:

  1. Rufen Sie chrome://Inspect > Service Worker auf. Diese Ansicht liefert außer den aktuell ausgeführten Service-Workern nur wenige Informationen.
  2. Rufen Sie chrome://serviceworker-internals auf. Dort können Sie den Status der Service Worker und ggf. vorhandene Fehler einsehen. Diese Seite ist temporär, bis die Entwicklertools einen ähnlichen Funktionsumfang haben.

Einer der besten Tipps, die ich Leuten geben kann, die Service Worker noch nicht kennen, ist das Kästchen „Open DevTools-Fenster und Pausieren der JavaScript-Ausführung beim Service Worker-Start zum Debugging“. Mit diesem Kästchen wird am Anfang des Service Workers ein Haltepunkt hinzugefügt und die Ausführung wird angehalten. So können Sie das Service Worker-Skript fortsetzen oder einzelne Schritte ausführen, um zu sehen, ob Probleme auftreten.

Screenshot des Kästchens „Ausführung pausieren“ in „serviceworker-internals“

Wenn zwischen FCM und dem Push-Ereignis Ihres Service Workers ein Problem besteht, können Sie nicht viel tun, um das Problem zu beheben, da Sie nicht sehen 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 etwa so aus:

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

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

Fehlerbehebung bei Service Workern in Chrome für Android

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

Screenshot zum Speicherort der Service Worker in der Chrome-Prüfung

UX für Push-Benachrichtigungen

Das Chrome-Team hat ein Dokument mit Best Practices für Push-Benachrichtigungen sowie ein Dokument erstellt, in dem einige der Grenzfälle bei der Arbeit mit Push-Benachrichtigungen behandelt werden.

Push-Benachrichtigungen in Chrome und im offenen Web der Zukunft

In diesem Abschnitt geht es um einige der Chrome-spezifischen Teile dieser Implementierung, die Sie kennen sollten, und darauf, 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 nicht darum kümmern müssen, wer der Push-Anbieter ist. Auf diese Weise müssen Sie sich nicht für API-Schlüssel registrieren und speziell formatierte Daten senden, wie dies bei FCM der Fall ist.

Chrome war der erste Browser, der die Push API implementiert hat. FCM unterstützt das Web Push Protocol nicht. Aus diesem Grund benötigt Chrome die gcm_sender_id und du musst die Restful API für FCM verwenden.

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

Bis dahin müssen Sie den Endpunkt „https://fcm.googleapis.com/fcm/send“ erkennen und von anderen Endpunkten getrennt 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 ist derzeit im Push-Verfahren 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 vermeiden, wenn meine Webpräsenz mehrere Ursprünge hat oder wenn ich sowohl eine webbasierte als auch eine native Präsenz habe?

Im Moment gibt es keine Lösung dafür, aber du kannst den Fortschritt in Chromium verfolgen.

Das ideale Szenario wäre, eine Art ID für das Gerät eines Nutzers zu haben, dann auf Serverseite die Abo-IDs der nativen App und der Web-App abzugleichen und zu entscheiden, an welche ID eine Push-Nachricht gesendet werden soll. Sie könnten dies über die Bildschirmgröße, das Gerätemodell und die gemeinsame Nutzung eines generierten Schlüssels zwischen der Webanwendung 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 (FCM) API verwenden können. Ziel ist es, das Web Push Protocol zu verwenden, wenn der Standard fertiggestellt ist und von FCM unterstützt wird.

Warum sind es nicht sinnvoll, Web Sockets oder vom Server gesendete Ereignisse (EventSource) zu verwenden?

Der Vorteil von Push-Nachrichten besteht darin, dass der Service Worker selbst dann aktiviert wird, wenn Ihre Seite geschlossen wird, und eine Benachrichtigung anzeigen kann. Die Verbindung von Web Sockets und EventSource wird geschlossen, wenn die Seite oder der Browser geschlossen wird.

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

Wenn Sie keine Übermittlung im Hintergrund benötigen, sind WebSockets eine gute Option.

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

Es gibt noch keinen Zeitplan dafür, wann dies verfügbar sein wird. Es besteht jedoch die Absicht, die Hintergrundsynchronisierung zu implementieren. Es wurde noch nicht entschieden oder spezifiziert, aber es wird diskutiert, wie Sie den stillen Push mit Hintergrundsynchronisierung aktivieren.

Warum ist HTTPS erforderlich? Wie kann ich das während der Entwicklung umgehen?

Service Worker benötigen sichere Ursprünge, um sicherzustellen, dass das Service Worker-Skript vom beabsichtigten Ursprung stammt und nicht von einem Man-in-the-Middle-Angriff stammt. Derzeit bedeutet dies die Verwendung von HTTPS auf Live-Websites, auch wenn localhost während der Entwicklung funktioniert.

Wie werden Browser unterstützt?

Chrome unterstützt in der stabilen Version und an Mozilla wird in Firefox Nightly gearbeitet. Weitere Informationen findest du unter Push API implementieren. Hier kannst du die Implementierung der Push API verfolgen.

Kann ich eine Benachrichtigung nach einem bestimmten Zeitraum entfernen?

Derzeit ist dies nicht möglich. Wir planen jedoch, Support für die Abfrage einer Liste derzeit sichtbarer Benachrichtigungen hinzuzufügen. Wenn Sie einen Anwendungsfall haben, bei dem Sie eine Ablaufzeit für eine Benachrichtigung nach der Erstellung festlegen möchten, würden wir gerne wissen, was das ist. Fügen Sie daher bitte einen Kommentar hinzu und wir leiten ihn an das Chrome-Team zurück.

Wenn Sie das Senden einer Push-Benachrichtigung an den Nutzer nur nach einem bestimmten Zeitraum beenden möchten und es unerheblich ist, wie lange die Benachrichtigung sichtbar bleibt, können Sie den FCM-Parameter „TTL“ (Time to Live) verwenden. Weitere Informationen finden Sie hier.

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

In diesem Beitrag werden einige Einschränkungen beschrieben:

  • Die Verwendung von CCM als Push-Dienst in Chrome bringt eine Reihe proprietärer Anforderungen mit sich. Wir arbeiten zusammen, um zu sehen, ob einige dieser Probleme in Zukunft behoben werden können.
  • Sie müssen eine Benachrichtigung anzeigen, wenn Sie eine Push-Nachricht erhalten.
  • Bei Chrome auf Desktop-Computern werden keine Push-Nachrichten empfangen, 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, ist aber nicht unbedingt in allen Browsern verfügbar. Weitere Informationen

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

Dieses Problem betrifft nur Seiten, die derzeit nicht von einem Dienst-Worker gesteuert werden. Weitere Informationen

Was passiert, wenn eine Benachrichtigung zum Zeitpunkt, zu dem das Gerät des Nutzers die Push-Benachrichtigung erhalten hat, veraltet war?

Sie müssen immer eine Benachrichtigung anzeigen, wenn Sie eine Push-Nachricht erhalten. Wenn Sie eine Benachrichtigung senden möchten, diese aber nur für einen bestimmten Zeitraum nützlich ist, können Sie den Parameter "time_to_live" in CCM verwenden, damit FCM die Push-Nachricht nicht sendet, wenn die Ablaufzeit abgelaufen ist.

Weitere Informationen

Was passiert, wenn ich zehn Push-Nachrichten sende, das Gerät aber nur eine empfangen soll?

FCM verfügt über den Parameter "min_key", mit dem Sie FCM anweisen können, alle ausstehenden Nachrichten mit demselben "Minimierschlüssel" durch die neue Nachricht zu ersetzen.

Weitere Informationen