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.

Mit Push-Benachrichtigungen können Nutzer aktuelle Informationen von Websites erhalten, die sie mögen. Außerdem können Sie sie mit personalisierten, ansprechenden Inhalten effektiv wieder ansprechen.

Seit Chrome-Version 42 sind die Push API und die Notification API für Entwickler verfügbar.

Die Push API in Chrome basiert auf mehreren verschiedenen Technologien, darunter Web-App-Manifeste und Service Workers. In diesem Beitrag werden wir uns mit jeder dieser Technologien befassen, aber nur mit dem Nötigsten, um Push-Mitteilungen einzurichten. Weitere Informationen zu einigen der anderen Funktionen von Manifesten und den Offlinefunktionen von Service Workern finden Sie in den Links oben.

Außerdem sehen wir uns an, was in zukünftigen Chrome-Versionen zur API hinzugefügt wird. Abschließend gibt es noch eine FAQ.

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 Dienst-Worker starten kann, der im Hintergrund ausgeführt wird, ohne dass eine Seite geöffnet ist. Er sendet dann ein Ereignis, damit Sie entscheiden können, wie die Push-Nachricht verarbeitet werden soll.

Unten sehen Sie ein Beispiel dafür, wie Sie einen Service Worker in Ihrer Webanwendung registrieren. Nach erfolgreicher Registrierung wird initialiseState() aufgerufen, was wir gleich besprechen.

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. Darauf wird in den 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.

Anfangsstatus einrichten

Beispiel für die Benutzeroberfläche für aktivierte und deaktivierte Push-Mitteilungen in Chrome

Sobald der Dienstworker registriert ist, müssen wir den Status unserer Benutzeroberfläche einrichten.

Nutzer erwarten eine einfache Benutzeroberfläche, mit der sie Push-Mitteilungen für Ihre Website aktivieren oder deaktivieren können. Außerdem erwarten sie, dass die Oberfläche auf dem neuesten Stand gehalten wird. 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.

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

An dieser Stelle denken Sie vielleicht, dass es nur zwei Status gibt: „aktiviert“ oder „deaktiviert“. Es gibt jedoch noch einige andere Status, die Sie bei Benachrichtigungen 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 Benutzeroberfläche deaktiviert wird, sollten Sie den Anfangsstatus auf „Deaktiviert“ setzen. So wird auch Verwirrung vermieden, falls ein Problem mit dem JavaScript Ihrer Seite auftritt, 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 initialiseState()-Methode durchfü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);
        });
    });
}

Hier eine 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, ob die aktuelle Notification.permission 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-Mitteilungen 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, um sicherzustellen, dass wir die richtigen Informationen haben. Außerdem wird auf der Benutzeroberfläche angezeigt, ob Push-Mitteilungen bereits aktiviert sind oder nicht. Welche Details im Aboobjekt enthalten sind, sehen wir uns später in diesem Artikel an.

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

Im nächsten Schritt geht es darum, zu verarbeiten, wenn der Nutzer Push-Nachrichten aktivieren möchte. Bevor wir das tun können, müssen wir jedoch ein Google Developers 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 Console erstellen

Chrome verwendet FCM zum Senden und Zustellen 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 das in anderen Browsern funktioniert, wird später in diesem Artikel erläutert.

Neues Firebase-Entwicklerprojekt erstellen

Klicken Sie zuerst auf https://console.firebase.google.com/ auf „Neues Projekt erstellen“, um ein neues Projekt zu erstellen.

Screenshot des neuen Firebase-Projekts

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

Startseite des Firebase-Projekts

Klicken Sie auf diesem Dashboard oben links neben dem Projektnamen auf das Zahnrad und dann auf „Projekteinstellungen“.

Menü mit Firebase-Projekteinstellungen

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

Menü „Cloud Messaging“ des Firebase-Projekts

Diese Seite enthält den API-Schlüssel für Push-Mitteilungen, den wir später verwenden, und die Absender-ID, die wir im nächsten Abschnitt in das Manifest der Webanwendung einfügen müssen.

Web-App-Manifest hinzufügen

Für Push-Mitteilungen müssen wir eine Manifestdatei mit dem Feld gcm_sender_id hinzufügen, damit das Push-Abo erfolgreich abgeschlossen werden kann. 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 das Gerät eines Nutzers bei FCM registriert wird. So kann FCM das Gerät des Nutzers identifizieren und prüfen, ob Ihre Absender-ID mit dem entsprechenden API-Schlüssel übereinstimmt und der Nutzer Ihrem Server erlaubt hat, ihm Push-Nachrichten zu senden.

Unten sehen 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 in Ihrem HTML-Code mit dem folgenden Tag im Kopf Ihrer Seite darauf.

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

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

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.

Der Nutzer wird 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-Mitteilungen registriert:

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

Jetzt ist Ihre Webanwendung bereit, eine Push-Nachricht zu empfangen. Es passiert jedoch erst etwas, wenn wir unserer Service Worker-Datei einen Push-Ereignis-Listener hinzufügen.

Service Worker-Push-Ereignis-Listener

Wenn eine Push-Nachricht empfangen wird (wie Sie eine Push-Nachricht senden, erfahren Sie im nächsten Abschnitt), wird in Ihrem Service Worker ein Push-Ereignis ausgelöst. Anschließend müssen Sie 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
    })
    );
});

Mit diesem Code wird ein Push-Ereignis-Listener registriert und eine Benachrichtigung mit einem vordefinierten Titel, Textkörper, Symbol und einem Benachrichtigungs-Tag angezeigt. Bei diesem Beispiel ist die Methode event.waitUntil() besonders hervorzuheben. Bei dieser Methode wird ein Promise angenommen und die Lebensdauer eines Event-Handlers verlängert (oder der Service Worker aufrechterhalten), bis das Promise begleicht 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 wir zwei Push-Nachrichten mit einer kurzen Verzögerung zwischen ihnen an denselben Endpunkt senden und Benachrichtigungen mit demselben Tag anzeigen, 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 Tag oder gar keins. Später in diesem Artikel sehen wir uns ein vollständigeres Beispiel für die Anzeige einer Benachrichtigung an. Lassen Sie uns der Einfachheit halber zuerst prüfen, ob diese Benachrichtigung beim Senden einer Push-Nachricht angezeigt wird.

Push-Nachricht senden

Wir haben Push-Nachrichten abonniert und unser Service Worker ist bereit, eine Benachrichtigung anzuzeigen. Es ist also 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 besonders. Die URL enthält am Ende den 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 zwar unabhängig von der URL.

Das bedeutet, dass Sie auf Ihrem Server prüfen müssen, ob der Endpunkt für FCM ist. Ist das der Fall, müssen Sie die registration_id extrahieren. In Python könnte das so aussehen:

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

Folgende Aspekte sind beim Aufrufen von FCM zu beachten:

  • 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.
    • Anhand des API-Schlüssels ermittelt FCM die richtige Absender-ID, prüft, ob der Nutzer die Berechtigung für Ihr Projekt erteilt hat, und ob die IP-Adresse des Servers für dieses Projekt auf der Zulassungsliste steht.
  • 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 von registration_ids: Dies sind die Registrierungs-IDs, die Sie aus den Endpunkten Ihrer Nutzer extrahieren.

Weitere Informationen zum Senden von Push-Mitteilungen von Ihrem Server finden Sie in der Dokumentation. Für eine schnelle Prüfung Ihres Service Workers können Sie mit cURL eine Push-Mitteilung 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.

Du solltest eine tolle 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. Prüfen Sie daher, ob 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 auch für Chrome in Zukunft) 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 bei einer zukünftigen Implementierung Nutzlastdaten auf Ihrem Server verschlüsselt werden müssen, bevor sie an einen Endpunkt für Push-Messaging gesendet werden. So kann der Endpunkt, unabhängig vom Push-Anbieter, den Inhalt der Push-Nachricht nicht einfach einsehen. Außerdem werden andere Sicherheitslücken wie eine unzureichende Validierung von HTTPS-Zertifikaten und Man-in-the-Middle-Angriffe zwischen Ihrem Server und dem Push-Anbieter verhindert. Diese Verschlüsselung wird jedoch noch nicht unterstützt. In der Zwischenzeit müssen Sie einen Abruf ausführen, um die Informationen abzurufen, die zum Ausfüllen einer Benachrichtigung erforderlich sind.

Vollständigeres Beispiel für ein Push-Ereignis

Die bisher gezeigte Benachrichtigung ist ziemlich einfach und deckt im Hinblick auf Muster einen realen Anwendungsfall nur unzureichend ab.

In der Realität werden die meisten Nutzer einige Informationen von ihrem Server abrufen wollen, bevor sie die Benachrichtigung anzeigen. 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 aus einer API ab, konvertieren die Antwort in ein Objekt und verwenden sie, um unsere Benachrichtigung zu erstellen.

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

Noch einmal: event.waitUntil() nimmt ein Versprechen entgegen, das von showNotification() zurückgegeben wird. Das bedeutet, dass unser Ereignis-Listener erst beendet wird, wenn der asynchrone fetch()-Aufruf abgeschlossen ist und die Benachrichtigung angezeigt wird.

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

URL öffnen, wenn Nutzer auf eine Benachrichtigung klicken

Wenn der Nutzer auf eine Benachrichtigung klickt, wird ein notificationclick-Ereignis in Ihrem Service Worker gesendet. Im Handler können Sie entsprechende Maßnahmen ergreifen, z. B. den Fokus auf einen Tab legen 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 der Browser mit dem Stamm des Ursprungs der Website geöffnet. Dazu wird der Fokus auf einen vorhandenen Tab mit demselben Ursprung gelegt, falls vorhanden, andernfalls wird ein neuer Tab geöffnet.

In diesem Beitrag werden einige der Möglichkeiten beschrieben, die die Notification API bietet.

Abo eines Nutzergeräts kündigen

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

Um das Abo eines Nutzergeräts zu kündigen, müssen Sie hauptsächlich die Methode unsubscribe() auf dem PushSubscription-Objekt aufrufen und den Endpunkt von Ihren Servern entfernen, damit keine Push-Nachrichten gesendet werden, die bekanntlich 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);
        });
    });
}

Abo auf dem neuesten Stand halten

Abos können zwischen FCM und deinem Server nicht mehr synchron sein. Dein Server muss den Antworttext der POST-Sendeanfrage der FCM API parsen und nach error:NotRegistered- und canonical_id-Ergebnissen suchen, wie in der FCM-Dokumentation beschrieben.

Außerdem kann es passieren, dass sich Abos zwischen dem Dienst-Worker und Ihrem Server nicht synchronisieren. Beispielsweise kann es sein, dass nach dem Abonnieren oder Abbestellen eine fehlerhafte Netzwerkverbindung das Aktualisieren deines Servers verhindert. Es kann auch sein, dass ein Nutzer die Berechtigung für Benachrichtigungen widerruft, was eine automatische Abbestellung auslöst. Prüfen Sie in solchen Fällen regelmäßig (z.B. beim Laden der Seite) das Ergebnis von serviceWorkerRegistration.pushManager.getSubscription() und synchronisieren Sie es mit dem Server. Sie können sich auch automatisch wieder anmelden, wenn Sie kein Abo mehr haben und Notification.permission == 'granted'.

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 noch weitere Funktionen, die die Arbeit erleichtern werden, z. B. eine Standard-API zum Auslösen von Push-Mitteilungen. Mit dieser Version können Sie jedoch schon jetzt Push-Mitteilungen in Ihre Webanwendungen einbinden.

Webanwendung debuggen

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

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

  1. Rufen Sie chrome://inspect > Dienstprogramme auf. Diese Ansicht enthält nur wenige Informationen, außer den derzeit ausgeführten Dienst-Workern.
  2. Rufen Sie chrome://serviceworker-internals auf. Dort sehen Sie den Status der Dienstprogramme und gegebenenfalls Fehler. Diese Seite ist nur vorübergehend verfügbar, 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 Start des Service Workers zum Debugging“. Wenn Sie dieses Kästchen aktivieren, wird ein Haltepunkt am Anfang Ihres Service Workers hinzugefügt und die Ausführung pausiert. So können Sie das Service Worker-Script fortsetzen oder Schritt für Schritt durchgehen und prüfen, ob Probleme auftreten.

Screenshot, der zeigt, wo sich das Kästchen zum Pausieren der Ausführung in serviceworker-internals befindet

Wenn es ein Problem zwischen FCM und dem Push-Ereignis Ihres Service Workers zu geben scheint, können Sie nicht viel tun, um das Problem zu beheben, da Sie nicht sehen können, ob Chrome etwas empfangen hat. Achten Sie darauf, dass die Antwort von FCM erfolgreich ist, wenn Ihr Server einen API-Aufruf ausführt. Das sieht ungefähr so aus:

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

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

Fehlerbehebung bei Service Workern in Chrome für Android

Derzeit ist das Debuggen von Dienstarbeitern in Chrome für Android nicht einfach. 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 die UX von Push-Benachrichtigungen sowie ein Dokument mit einigen Grenzfällen bei der Arbeit mit Push-Benachrichtigungen zusammengestellt.

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

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 den Endpunkt an Ihren Server weitergeben und Push-Nachrichten senden können, indem Sie das Web Push Protocol implementieren.

Das Web Push Protocol ist ein neuer Standard, den Push-Anbieter implementieren können. So müssen sich Entwickler keine Gedanken mehr darüber machen, wer der Push-Anbieter ist. Dadurch müssen sie sich nicht mehr für API-Schlüssel registrieren und keine speziell formatierten Daten senden, wie es 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 Endziel für Chrome ist die Verwendung des Web Push-Protokolls mit Chrome und FCM.

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

Web Push-Protokoll implementieren

In Firefox Nightly wird derzeit an Push gearbeitet. Es 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 verhindern, dass ich doppelte Benachrichtigungen erhalte, wenn meine Webpräsenz mehrere Ursprünge hat oder wenn ich sowohl eine Web- als auch eine native Präsenz habe?

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

Im Idealfall haben Sie eine Art ID für das Gerät eines Nutzers und können dann auf Serverseite die Abo-IDs der nativen App und der Webanwendung abgleichen und entscheiden, an welche eine Push-Nachricht gesendet werden soll. Sie können dies anhand der Bildschirmgröße oder des Gerätemodells tun oder einen generierten Schlüssel zwischen der Webanwendung und der nativen App teilen. Jeder Ansatz hat jedoch 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-Protokoll zu verwenden, sobald 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 passiert, wenn ich keine Hintergrundereignisse senden möchte?

Wenn Sie keine Hintergrundübermittlung benötigen, sind Web Sockets eine gute Option.

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

Es gibt noch keinen Zeitplan für die Verfügbarkeit, aber es ist geplant, die Hintergrundsynchronisierung zu implementieren. Auch wenn es noch nicht entschieden oder spezifiziert ist, wird derzeit diskutiert, ob die Funktion „Silent Push“ mit der Hintergrundsynchronisierung aktiviert werden soll.

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

Für Service Worker sind sichere Ursprünge erforderlich, damit sichergestellt werden kann, dass das Service Worker-Script von der beabsichtigten Quelle stammt und nicht durch einen Man-in-the-Middle-Angriff manipuliert wurde. Derzeit bedeutet das, dass HTTPS auf Live-Websites verwendet werden muss. Während der Entwicklung funktioniert jedoch localhost.

Wie sieht die Browserunterstützung aus?

Chrome unterstützt in der stabilen Version und an Mozilla wird in Firefox Nightly gearbeitet. Weitere Informationen finden Sie im Fehlerbericht zur Implementierung der Push API. Die Implementierung von Benachrichtigungen können Sie hier verfolgen.

Kann ich eine Benachrichtigung nach einem bestimmten Zeitraum entfernen?

Derzeit ist das nicht möglich. Wir planen jedoch, eine Liste der derzeit sichtbaren Benachrichtigungen anzubieten. Wenn Sie einen Anwendungsfall für das Festlegen eines Ablaufdatums für Benachrichtigungen haben, nachdem sie erstellt wurden, würden wir uns sehr über einen Kommentar freuen. Wir leiten ihn dann an das Chrome-Team weiter.

Wenn Sie nur verhindern möchten, dass eine Push-Benachrichtigung nach einem bestimmten Zeitraum an den Nutzer gesendet wird, und nicht darauf achten, wie lange die Benachrichtigung sichtbar bleibt, können Sie den FCM-Parameter „Time to Live“ (TTL) verwenden. Weitere Informationen

Welche Einschränkungen gelten für Push-Mitteilungen in Chrome?

In diesem Beitrag werden einige Einschränkungen beschrieben:

  • Die Verwendung von CCM als Push-Dienst in Chrome führt zu einer Reihe von proprietären Anforderungen. Wir arbeiten gemeinsam daran, zu prüfen, ob einige dieser Einschränkungen in Zukunft aufgehoben werden können.
  • Sie müssen eine Benachrichtigung anzeigen, wenn Sie eine Push-Nachricht erhalten.
  • Bei Chrome auf dem Computer gilt jedoch, dass Push-Nachrichten nicht empfangen werden, wenn Chrome nicht geöffnet ist. Das unterscheidet sich von ChromeOS und Android, wo Push-Nachrichten immer empfangen werden.

Sollten wir nicht die Berechtigungs-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 Service Worker gesteuert werden. Weitere Informationen

Was passiert, wenn eine Benachrichtigung veraltet ist, wenn sie auf dem Gerät des Nutzers empfangen wird?

Sie müssen immer eine Benachrichtigung anzeigen lassen, wenn Sie eine Push-Nachricht erhalten. Wenn Sie eine Benachrichtigung senden möchten, die 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 Gültigkeitsdauer 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