Powiadomienia push w otwartej sieci

Jeśli zapytasz zespół programistów, jakich funkcji na urządzeniach mobilnych brakuje w internecie, powiadomienia push będą zawsze wyżej na liście.

Dzięki powiadomieniom push użytkownicy mogą otrzymywać aktualności z ulubionych witryn i skutecznie zachęcać ich do korzystania z dostosowanych i ciekawych treści.

Od wersji Chrome 42 interfejsy Push API i notification API są dostępne dla programistów.

Interfejs Push API w Chrome korzysta z kilku różnych technologii, w tym pliku manifestu aplikacji internetowejusług działających w tle. W tym poście omówimy każdą z tych technologii, ale tylko w zakresie niezbędnym do uruchomienia powiadomień push. Aby lepiej poznać niektóre inne funkcje plików manifestu i możliwości offline mechanizmów Service Worker, skorzystaj z linków powyżej.

Przyjrzymy się także elementom, które zostaną dodane do interfejsu API w kolejnych wersjach Chrome, a na koniec odpowiemy na najczęstsze pytania.

Implementacja wiadomości push w Chrome

W tej sekcji opisujemy wszystkie kroki, które musisz wykonać, aby umożliwić obsługę powiadomień push w aplikacji internetowej.

Rejestrowanie skryptu service worker

W przypadku wiadomości push w internecie wymagany jest usługa workera. Dzieje się tak, ponieważ po otrzymaniu wiadomości push przeglądarka może uruchomić usługę workera, która działa w tle bez otwierania strony, i wysłać zdarzenie, aby umożliwić Ci określenie sposobu obsługi tej wiadomości.

Poniżej przedstawiamy przykład rejestracji serwisu w aplikacji internetowej. Po pomyślnym zakończeniu rejestracji wywołujemy funkcję initialiseState(), którą omówimy za chwilę.

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

Obsługa kliknięcia przycisku umożliwia użytkownikowi subskrybowanie lub anulowanie subskrypcji wiadomości push. isPushEnabled to zmienna globalna, która po prostu śledzi, czy użytkownik jest obecnie subskrybowany do otrzymywania wiadomości push. W fragmentach kodu będą się do nich odnosić.

Następnie sprawdzamy, czy skrypty service worker są obsługiwane, zanim zarejestrujemy plik service-worker.js, który zawiera logikę obsługi wiadomości push. Tutaj po prostu informujemy przeglądarkę, że ten plik JavaScript jest usługą wtyczki dla naszej witryny.

Konfigurowanie stanu początkowego

Przykład interfejsu użytkownika w Chrome w przypadku włączonych i wyłączonych powiadomień push

Gdy skrypt service worker zostanie zarejestrowany, musimy skonfigurować stan naszego interfejsu użytkownika.

Użytkownicy oczekują prostego interfejsu do włączania i wyłączania powiadomień push w Twojej witrynie. Oczekują też, że będzie on aktualizowany zgodnie z aktualnymi zmianami. Innymi słowy, jeśli użytkownik włączy wiadomości push w Twojej witrynie, a potem ją opuści i powróci po tygodniu, interfejs powinien wskazywać, że wiadomości push są już włączone.

Kilka wskazówek dotyczących UX znajdziesz w tym dokumencie. W tym artykule skupimy się na aspektach technicznych.

W tym momencie możesz pomyśleć, że masz do czynienia tylko z 2 stanami: włączonym i wyłączonym. Istnieją jednak inne stany powiadomień, które należy wziąć pod uwagę.

Diagram przedstawiający różne kwestie i stany push w Chrome

Zanim włączymy przycisk, musimy sprawdzić kilka interfejsów API. Jeśli wszystko jest obsługiwane, możemy włączyć interfejs użytkownika i ustawić stan początkowy, aby wskazać, czy subskrypcja powiadomień push jest aktywna.

Ponieważ większość z tych testów powoduje wyłączenie interfejsu, stan początkowy powinien być ustawiony na „wyłączone”. Zapobiegnie to też ewentualnym nieporozumieniom, jeśli wystąpi problem z kodem JavaScript na stronie, np. nie można pobrać pliku JS lub użytkownik wyłączył JavaScript.

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

W tym początkowym stanie możemy wykonać opisane powyżej kontrole w metodzie initialiseState(), czyli po zarejestrowaniu naszego serwisu.

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

Krótki opis tych czynności:

  • Sprawdzamy, czy showNotification jest dostępny w prototypie ServiceWorkerRegistration. Bez niego nie będziemy mogli wyświetlić powiadomienia z naszego serwisu workera po otrzymaniu wiadomości push.
  • Sprawdzamy, jaka jest aktualna wartość Notification.permission, aby upewnić się, że nie jest to "denied". Odmowa uprawnień oznacza, że nie możesz wyświetlać powiadomień, dopóki użytkownik ręcznie nie zmieni uprawnień w przeglądarce.
  • Aby sprawdzić, czy obsługa wiadomości push jest dostępna, sprawdzamy, czy w obiekcie window jest dostępna właściwość PushManager.
  • Na koniec użyliśmy pushManager.getSubscription(), aby sprawdzić, czy mamy już subskrypcję. Jeśli tak, wysyłamy na nasz serwer szczegóły subskrypcji, aby mieć pewność, że mamy prawidłowe informacje, i ustawiamy interfejs tak, aby wskazywał, czy powiadomienia push są już włączone. Szczegóły obiektu subskrypcji przyjrzymy się bliżej w dalszej części tego artykułu.

Czekamy, aż navigator.serviceWorker.ready zostanie rozwiązany, aby sprawdzić subskrypcję i włączyć przycisk push, ponieważ dopiero po aktywacji pracownika usługi możesz subskrybować wiadomości push.

Następnym krokiem jest obsłużenie sytuacji, gdy użytkownik chce włączyć wiadomości push. Zanim to zrobimy, musimy skonfigurować projekt w Google Developers Console i dodać do pliku manifestu kilka parametrów, aby korzystać z Komunikacji w chmurze Firebase (FCM), która wcześniej była znana jako Komunikacja w chmurze Google (GCM).

Tworzenie projektu w konsoli programisty Firebase

Chrome używa FCM do wysyłania i przekazywania powiadomień push, ale aby korzystać z interfejsu FCM API, musisz skonfigurować projekt w Konsoli dewelopera Firebase.

Poniższe czynności dotyczą przeglądarek Chrome, Opera na Androida i Samsung Browser, które korzystają z FCM. Omówimy to w dalszej części artykułu.

Utwórz nowy projekt Firebase Developer

Na początek utwórz nowy projekt na stronie https://console.firebase.google.com/, klikając „Utwórz nowy projekt”.

Zrzut ekranu z nowego projektu Firebase

Dodaj nazwę projektu, utwórz projekt, a potem przejdziesz do jego panelu:

Strona główna projektu Firebase

W panelu kliknij kółko obok nazwy projektu w lewym górnym rogu, a potem kliknij „Ustawienia projektu”.

Menu ustawień projektu Firebase

Na stronie ustawień kliknij kartę „Wiadomości w chmurze”.

Menu Komunikacji w chmurze w projekcie Firebase

Ta strona zawiera klucz interfejsu API do przesyłania wiadomości push, którego użyjemy później, oraz identyfikator nadawcy, który trzeba umieścić w następnej sekcji w manifeście aplikacji internetowej.

Dodaj plik manifestu aplikacji internetowej

W przypadku push musimy dodać plik manifestu z polem gcm_sender_id, aby subskrypcja push zakończyła się sukcesem. Ten parametr jest wymagany tylko przez przeglądarki Chrome, Opera na Androida i Samsung, do korzystania z FCM / GCM.

Te przeglądarki używają parametru gcm_sender_id, gdy subskrybują urządzenie użytkownika w usługach FCM. Oznacza to, że FCM może zidentyfikować urządzenie użytkownika i upewnić się, że identyfikator nadawcy jest zgodny z odpowiednim kluczem interfejsu API oraz że użytkownik zezwolił Twojemu serwerowi na wysyłanie wiadomości push.

Oto bardzo prosty plik manifestu:

{
    "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>"
}

Musisz ustawić wartość gcm_sender_id na identyfikator nadawcy z projektu Firebase.

Po zapisaniu pliku manifestu w projekcie (manifest.json to dobry format nazwy) odwołuj się do niego w pliku HTML za pomocą tego tagu w sekcji nagłówka strony.

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

Jeśli nie dodasz pliku manifestu internetowego z tymi parametrami, podczas próby subskrypcji wiadomości push dla użytkownika pojawi się wyjątek z błędem "Registration failed - no sender id provided" lub "Registration failed - permission denied".

Subskrybowanie powiadomień push

Po skonfigurowaniu pliku manifestu możesz wrócić do JavaScriptu w swoich witrynach.

Aby się zapisać, musisz wywołać metodę subscribe() obiektu PushManager, do którego dostęp uzyskujesz za pomocą ServiceWorkerRegistration.

Użytkownik zostanie poproszony o zezwolenie na wysyłanie powiadomień push. Bez tego uprawnienia nie będzie można się subskrybować.

Jeśli obietnica zwracana przez metodę subscribe() zostanie spełniona, otrzymasz obiekt PushSubscription, który będzie zawierać punkt końcowy.

Punkt końcowy powinien być zapisany na serwerze dla każdego użytkownika, ponieważ będziesz go potrzebować do wysyłania wiadomości push w późniejszym terminie.

Ten kod subskrybuje użytkownika do otrzymywania powiadomień push:

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

Twoja aplikacja internetowa jest już gotowa do odbierania wiadomości push, ale nic się nie stanie, dopóki nie dodasz do pliku usługi internetowej listenera zdarzenia push.

Detektor zdarzenia push skryptu service worker

Po otrzymaniu wiadomości push (w następnym rozdziale omówimy, jak wysyłać takie wiadomości) w Twoim serwisie workerze zostanie wywołane zdarzenie push. W tym momencie musisz wyświetlić powiadomienie.

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

Ten kod rejestruje detektor zdarzenia push i wyświetla powiadomienie z wstępnie zdefiniowanym tytułem, tekstem, ikoną i tagiem powiadomienia. W tym przykładzie warto zwrócić uwagę na metodę event.waitUntil(). Ta metoda przyjmuje obietnice i przedłuża czas życia okna obsługi zdarzeń (lub można ją traktować jako utrzymywanie procesu event.waitUntil w stanie aktywnym) do momentu, aż obietnica zostanie zakończona. W tym przypadku obietnica przekazana do event.waitUntil to zwrócona obietnica z showNotification().

Tag powiadomienia działa jako identyfikator pojedynczych powiadomień. Jeśli wyślemy 2 wiadomości push do tego samego punktu końcowego z krótkim opóźnieniem i z tym samym tagiem, przeglądarka wyświetli pierwsze powiadomienie, a po otrzymaniu wiadomości push zastąpi je drugim.

Jeśli chcesz wyświetlać kilka powiadomień jednocześnie, użyj innego tagu lub wcale go nie używaj. W dalszej części tego posta omówimy bardziej kompletny przykład wyświetlania powiadomienia. Na razie nie komplikujmy sprawy i sprawdźmy, czy wysłanie powiadomienia push spowoduje wyświetlenie tego powiadomienia.

Wysyłanie komunikatu push

Subskrybujemy wiadomości push, a nasz serwis worker jest gotowy do wyświetlania powiadomień. Czas wysłać wiadomość push za pomocą FCM.

Dotyczy to tylko przeglądarek korzystających z FCM.

Gdy wysyłasz zmienną PushSubscription.endpoint na serwer, punkt końcowy FCM jest specjalny. Na końcu adresu URL znajduje się parametr registration_id.

Przykładem punktu końcowego jest:

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

Adres URL FCM to:

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

registration_id to:

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

Dotyczy to przeglądarek korzystających z FCM. W zwykłej przeglądarce po prostu pobierasz punkt końcowy i wywołujesz go w standardowy sposób. Działa to niezależnie od adresu URL.

Oznacza to, że musisz sprawdzić na serwerze, czy punkt końcowy jest przeznaczony dla FCM, a jeśli tak, wyodrębnij identyfikator rejestracji. Aby to zrobić w Pythonie, możesz użyć tego kodu:

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

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

Gdy już masz identyfikator rejestracji, możesz wywołać interfejs FCM API. Dokumenty referencyjne dotyczące interfejsu FCM API znajdziesz tutaj.

Najważniejsze aspekty, o których należy pamiętać podczas wywoływania FCM:

  • Podczas wywołania interfejsu API musisz ustawić nagłówek Authorization (Autoryzacja) z wartością key=&lt;YOUR_API_KEY&gt;, gdzie &lt;YOUR_API_KEY&gt; to klucz API z projektu Firebase.
    • Klucz interfejsu API jest używany przez FCM do znajdowania odpowiedniego identyfikatora nadawcy, sprawdzania, czy użytkownik udzielił uprawnień do projektu, oraz do sprawdzania, czy adres IP serwera znajduje się na liście dozwolonych adresów w przypadku danego projektu.
  • Odpowiedni nagłówek Content-Type o wartości application/json lub application/x-www-form-urlencoded;charset=UTF-8 w zależności od tego, czy wysyłasz dane w formacie JSON, czy w formie formularza.
  • Tablica registration_ids – to identyfikatory rejestracji, które wyodrębniasz z punktów końcowych użytkowników.

Zapoznaj się z dokumentacją na temat wysyłania powiadomień push z serwera. Aby szybko sprawdzić swojego pracownika usługi, możesz użyć cURL, aby wysłać powiadomienie push do przeglądarki.

Zamień &lt;YOUR_API_KEY&gt; i &lt;YOUR_REGISTRATION_ID&gt; w tym poleceniu cURL na własne i uruchom je z terminala.

Powinien pojawić się komunikat:

    curl --header "Authorization: key=<YOUR_API_KEY>" --header
    "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d
    "{\"registration_ids\":[\"<YOUR_REGISTRATION_ID>\"]}"
Przykład wiadomości push z Chrome na Androida

Podczas tworzenia logiki backendu pamiętaj, że nagłówek Authorization i format treści żądania POST są specyficzne dla punktu końcowego FCM, więc wykryj, kiedy punkt końcowy jest przeznaczony dla FCM, i warunkowo dodaj nagłówek oraz sformatuj treść żądania POST. W przypadku innych przeglądarek (a tym samym Chrome w przyszłości) musisz wdrożyć protokół Web Push Protocol.

Wadą obecnej implementacji interfejsu Push API w Chrome jest to, że nie można wysyłać żadnych danych w ramach powiadomienia push. Nic. Dzieje się tak, ponieważ w przyszłej implementacji dane ładunku muszą zostać zaszyfrowane na serwerze, zanim zostaną wysłane do punktu końcowego wiadomości push. Dzięki temu urządzenie końcowe, niezależnie od tego, którego dostawcy używasz, nie będzie mogło łatwo wyświetlić treści wiadomości push. Zapewnia też ochronę przed innymi lukami w zabezpieczeniach, takimi jak słaba weryfikacja certyfikatów HTTPS i ataki typu „man-in-the-middle” między serwerem a dostawcą powiadomień push. Jednak szyfrowanie nie jest jeszcze obsługiwane, więc na razie musisz wykonać pobieranie, aby uzyskać informacje potrzebne do wypełnienia powiadomienia.

Bardziej kompletny przykład zdarzenia push

Otrzymane do tej pory powiadomienie jest dość podstawowe i nie obejmuje w pełni rzeczywistych przypadków użycia.

Większość użytkowników będzie chciała uzyskać pewne informacje z serwera przed wyświetleniem powiadomienia. Mogą to być dane, które wypełniają tytuł i tekst powiadomienia, lub nawet dane, które są przechowywane w pamięci podręcznej, aby po kliknięciu powiadomienia wszystko było dostępne od razu po otwarciu przeglądarki, nawet jeśli sieć jest w danym momencie niedostępna.

W tym kodzie pobieramy dane z interfejsu API, zamieniamy odpowiedź na obiekt i używamy go do wypełniania powiadomienia.

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

Warto jeszcze raz podkreślić, że funkcja event.waitUntil() przyjmuje obietnicę, która jest zwracana przez funkcję showNotification(). Oznacza to, że nasz detektor zdarzeń nie zakończy działania, dopóki nie zostanie zakończone asynchroniczne wywołanie funkcji fetch() i nie zostanie wyświetlone powiadomienie.

Nawet jeśli wystąpi błąd, wyświetlamy powiadomienie. Dzieje się tak dlatego, że jeśli tego nie zrobimy, Chrome będzie pokazywać własne powiadomienie ogólne.

Otwieranie adresu URL po kliknięciu powiadomienia przez użytkownika

Gdy użytkownik kliknie powiadomienie, w Twoim serwisie workerze zostanie wysłane zdarzenie notificationclick. W obiekcie funkcji możesz wykonać odpowiednie działanie, na przykład ustawić fokus na karcie lub otworzyć okno z określonym adresem URL:

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

W tym przykładzie przeglądarka otwiera katalog główny witryny źródłowej, skupiając się na istniejącej karcie tego samego pochodzenia (jeśli taka istnieje) lub otwierając nową.

Opublikowaliśmy post na temat niektórych funkcji, które możesz zrobić przy użyciu interfejsu Notification API.

Rezygnacja z subskrypcji na urządzeniu użytkownika

Użytkownik zasubskrybował urządzenie i otrzymuje powiadomienia push. Jak można zrezygnować z subskrypcji?

Aby anulować subskrypcję na urządzeniu użytkownika, musisz wywołać metodę unsubscribe() obiektu PushSubscription i usunąć punkt końcowy ze swoich serwerów (aby nie wysyłać wiadomości push, które wiesz, że nie zostaną odebrane). Ten kod robi dokładnie to:

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

Aktualizowanie subskrypcji

Subskrypcje mogą być niesynchronizowane między FCM a serwerem. Upewnij się, że Twój serwer analizuje treść odpowiedzi żądania POST interfejsu FCM API, szukając wyników error:NotRegisteredcanonical_id, zgodnie z opisem w dokumentacji FCM.

Subskrypcje mogą też być niezsynchronizowane między service workerem a serwerem. Na przykład po subskrybowaniu lub anulowaniu subskrypcji niestabilne połączenie z siecią może uniemożliwić aktualizację serwera. Użytkownik może też cofnąć uprawnienia do wysyłania powiadomień, co spowoduje automatyczne anulowanie subskrypcji. W takich przypadkach sprawdzaj wynik funkcji serviceWorkerRegistration.pushManager.getSubscription() okresowo (np. podczas wczytywania strony) i synchronizuj go z serwerem. Możesz też automatycznie ponownie zasubskrybować usługę, jeśli nie masz już subskrypcji i Notification.permission == 'granted'.

sendSubscriptionToServer() musisz określić, jak chcesz obsługiwać nieudane żądania sieci podczas aktualizowania endpoint. Jednym z rozwiązań jest śledzenie stanu obiektu endpoint w pliku cookie w celu określenia, czy serwer potrzebuje najnowszych informacji.

Wszystkie powyższe czynności umożliwiają pełną implementację komunikatów push w przeglądarce Chrome 46. Nadal istnieją funkcje specyficzne dla danego systemu, które ułatwiają pracę (np. standardowy interfejs API do uruchamiania powiadomień push), ale ta wersja umożliwia już dzisiaj tworzenie powiadomień push w aplikacjach internetowych.

Debugowanie aplikacji internetowej

Podczas implementowania wiadomości push błędy będą występować w jednym z tych 2 miejsc: na stronie lub w usługowym workerze.

Błędy na stronie można debugować za pomocą DevTools. Aby debugować problemy związane z usługami w tle, masz 2 opcje:

  1. Kliknij chrome://inspect > Service workers (Usługa w tle). Ten widok nie zawiera wielu informacji oprócz obecnie działających usług.
  2. Otwórz stronę chrome://serviceworker-internals, aby wyświetlić stan usług workerów i błędy (jeśli występują). Ta strona jest tymczasowa, dopóki Narzędzia deweloperskie nie będą miały podobnego zestawu funkcji.

Jedną z najlepszych wskazówek, jakie mogę podać osobom, które dopiero zaczynają korzystać z usług działających w tle, jest użycie pola wyboru „Otwórz okno DevTools i wstrzymaj wykonywanie kodu JavaScript podczas uruchamiania usługi pracującej w tle na potrzeby debugowania”. To pole wyboru spowoduje dodanie punktu przerwania na początku usługi workera i wstrzymanie wykonania. Pozwoli Ci to wznowić działanie lub przejść przez skrypt usługi workera i sprawdzić, czy nie występują w nim żadne problemy.

Zrzut ekranu pokazujący, gdzie znajduje się pole wyboru w przypadku usługi serviceworker-internals.

Jeśli występuje problem między FCM a zdarzeniem push skryptu usługi, nie można w żaden sposób rozwiązać problemu, bo nie da się sprawdzić, czy Chrome otrzymał coś od siebie. Najważniejsze jest, aby odpowiedź FCM była pomyślna, gdy serwer wysyła żądanie do interfejsu API. Wyglądać to będzie mniej więcej tak:

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

Zwróć uwagę na odpowiedź "success": 1. Jeśli zamiast tego pojawi się błąd, oznacza to, że coś jest nie tak z identyfikatorem rejestracji FCM i komunikat push nie jest wysyłany do Chrome.

Debugowanie usług Service Worker w Chrome na Androida

Obecnie debugowanie procesów Service Worker w Chrome na Androida nie jest oczywiste. Musisz otworzyć chrome://inspect, znaleźć swoje urządzenie i poszukać na liście pozycji o nazwie „Worker pid:....” z adresem URL mechanizmu Service Worker.

Zrzut ekranu pokazujący, gdzie podczas inspekcji Chrome przebywają mechanizmy Service Worker

UX powiadomień push

Zespół Chrome opracował dokument ze sprawdzonymi metodami dotyczącymi UX powiadomień push, a także dokument opisujący niektóre przypadki szczególne związane z powiadomieniami push.

Przyszłość komunikatora push w Chrome i otwartej sieci

W tej sekcji znajdziesz szczegółowe informacje o niektórych elementach tej implementacji w Chrome, o których warto wiedzieć, oraz o tym, czym różni się ona od innych przeglądarek.

Protokół i punkty końcowe Web Push

Zaletą standardu interfejsu Push API jest to, że możesz użyć punktu końcowego, przekazać go na serwer i wysyłać powiadomienia push, wdrażając protokół Web Push.

Web Push Protocol to nowy standard, który mogą stosować dostawcy powiadomień push. Dzięki temu deweloperzy nie muszą się martwić, kto jest dostawcą powiadomień push. Idea polega na tym, że nie trzeba rejestrować się w celu uzyskania kluczy interfejsu API ani wysyłać danych w specjalnym formacie, jak w przypadku FCM.

Chrome była pierwszą przeglądarką, która wdrożyła interfejs Push API. FCM nie obsługuje protokołu Web Push, dlatego Chrome wymaga interfejsu gcm_sender_id i musisz używać interfejsu REST FCM.

Ostatecznym celem Chrome jest przejście na korzystanie z protokołu Web Push w Chrome i FCM.

Do tego czasu musisz wykrywać punkt końcowy „https://fcm.googleapis.com/fcm/send” i obsługiwać go oddzielnie od innych punktów końcowych, czyli formatować dane ładunku w określony sposób i dodawać klucz autoryzacji.

Jak wdrożyć protokół Web Push Protocol?

Firefox Nightly obecnie pracuje nad pushem i prawdopodobnie będzie pierwszą przeglądarką, która wdroży protokół Web Push.

Najczęstsze pytania

Gdzie są specyfikacje?

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

Czy mogę zapobiec powielaniu powiadomień, jeśli moja obecność w internecie ma wiele źródeł lub jeśli działam zarówno w internecie, jak i w środowisku natywnym?

W tej chwili nie możemy rozwiązać tego problemu, ale możesz śledzić postępy w Chromium.

Idealnym rozwiązaniem byłoby posiadanie identyfikatora urządzenia użytkownika, a następnie dopasowanie na stronie serwera identyfikatorów subskrypcji aplikacji natywnej i aplikacji internetowej oraz wybranie, do której z nich wysłać wiadomość push. Możesz to zrobić, wykorzystując rozmiar ekranu, model urządzenia i wygenerowany klucz między aplikacją internetową a aplikacją natywną, ale każde podejście ma swoje wady i zalety.

Dlaczego muszę podać identyfikator gcm_sender_id?

Jest to wymagane, aby przeglądarki Chrome, Opera na Androida i Samsung Browser mogły korzystać z interfejsu API Komunikacji w chmurze Firebase (FCM). Celem jest używanie protokołu Web Push Protocol, gdy standard zostanie sfinalizowany i będzie obsługiwany przez FCM.

Dlaczego nie używać interfejsu Web Sockets ani zdarzeń wysyłanych przez serwer (EventSource)?

Zaletą korzystania z wiadomości push jest to, że nawet po zamknięciu strony pracownik Service Worker się obudzi i może wyświetlić powiadomienie. Połączenie Web Sockets i EventSource zostaje zamknięte po zamknięciu strony lub przeglądarki.

Co zrobić, jeśli nie potrzebuję dostarczania zdarzeń w tle?

Jeśli nie potrzebujesz przesyłania w tle, interfejs Web Sockets jest doskonałym rozwiązaniem.

Kiedy mogę używać powiadomień push bez wyświetlania powiadomień (np. cichych powiadomień w tle)?

Nie wiadomo jeszcze, kiedy ta funkcja będzie dostępna, ale planujemy wdrożenie synchronizacji w tle. Choć nie jest to jeszcze ustalone ani ustalone, toczy się dyskusja na temat włączenia trybu cichego przekazywania z synchronizacją w tle.

Dlaczego wymagane jest HTTPS? Jak mogę obejść ten problem podczas tworzenia aplikacji?

Skrypty service worker wymagają bezpiecznych źródeł, aby mieć pewność, że pochodzą z przeznaczonego źródła i nie są wynikiem ataku typu „człowiek w środku”. Obecnie oznacza to korzystanie z protokołu HTTPS w witrynach produkcyjnych, ale localhost będzie działać podczas tworzenia.

Jak wygląda obsługa przeglądarki?

Chrome działa w wersji stabilnej, a w Firefoksie Nightly pracowano w trybie push. Więcej informacji znajdziesz w sekcji o implementowaniu błędu interfejsu Push API. Możesz śledzić implementację powiadomień tutaj.

Czy mogę usunąć powiadomienie po pewnym czasie?

W tej chwili nie jest to możliwe, ale planujemy dodanie obsługi listy aktualnie widocznych powiadomień. Jeśli masz przypadek użycia, w którym chcesz ustawić czas ważności powiadomienia po jego wyświetleniu, dodaj komentarz, a my przekażemy go zespołowi Chrome.

Jeśli chcesz tylko zablokować wysyłanie powiadomienia push do użytkownika po upływie określonego czasu i nie zależy Ci na tym, jak długo powiadomienie będzie widoczne, możesz użyć parametru czasu życia (TTL) FCM. Więcej informacji znajdziesz tutaj.

Jakie są ograniczenia wiadomości push w Chrome?

W tym poście opisaliśmy kilka ograniczeń:

  • Korzystanie z CCM jako usługi push powoduje powstanie szeregu zastrzeżonych wymagań. Wspólnie pracujemy nad tym, czy w przyszłości uda się znieść niektóre z nich.
  • Gdy otrzymasz powiadomienie push, musisz wyświetlić powiadomienie.
  • W przypadku Chrome na komputerze należy pamiętać, że jeśli przeglądarka nie jest uruchomiona, wiadomości push nie będą odbierane. Jest to inne niż w przypadku ChromeOS i Androida, gdzie wiadomości push są zawsze odbierane.

Czy nie powinniśmy używać interfejsu Permissions API?

Interfejs Permission API jest dostępny w Chrome, ale niekoniecznie we wszystkich przeglądarkach. Więcej informacji znajdziesz tutaj

Dlaczego po kliknięciu powiadomienia Chrome nie otwiera poprzedniej karty?

Ten problem dotyczy tylko stron, które nie są obecnie kontrolowane przez skrypt service worker. Więcej informacji znajdziesz tutaj

Co zrobić, jeśli powiadomienie jest nieaktualne w momencie, gdy urządzenie użytkownika odbierz powiadomienie push?

Gdy otrzymasz powiadomienie push, zawsze musisz wyświetlić powiadomienie. Jeśli chcesz wysłać powiadomienie, ale ma ono być przydatne tylko przez określony czas, możesz użyć parametru „time_to_live” w usługach CCM, aby FCM nie wysyłało powiadomienia push po upływie czasu ważności.

Więcej informacji znajdziesz tutaj

Co się stanie, jeśli wyślę 10 wiadomości push, ale chcę, aby urządzenie otrzymało tylko jedną?

FCM ma parametr „collapse_key”, za pomocą którego możesz poprosić usługę FCM o zastąpienie dowolnej oczekującej wiadomości o tym samym kluczu „collapse_key” nową wiadomością.

Więcej informacji znajdziesz tutaj