Powiadomienia push w otwartej sieci

Jeśli zapytasz grupę deweloperów, jakich funkcji brakuje w internecie na urządzeniach mobilnych, na szczycie listy zawsze znajdą się powiadomienia push.

Powiadomienia push umożliwiają użytkownikom subskrybowanie aktualnych informacji z witryn, które lubią, a także skuteczne ponowne zaangażowanie ich za pomocą spersonalizowanych, angażujących treści.

Od wersji 42 Chrome interfejsy Push APINotification 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 dowiedzieć się więcej o innych funkcjach plików manifestu i możliwościach offline usług workerów, kliknij linki powyżej.

Zastanowimy się też, co zostanie dodane do interfejsu API w przyszłych wersjach Chrome. Na koniec przedstawimy odpowiedzi na najczęściej zadawane 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ę w tle, 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 subskrybentem 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ą w tle dla naszej witryny.

Konfigurowanie stanu początkowego

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

Po zarejestrowaniu pracownika usługi musimy skonfigurować stan interfejsu użytkownika.

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

W tym dokumencie znajdziesz wskazówki dotyczące UX, a w tym artykule skupimy się na aspektach technicznych.

W tym momencie możesz pomyśleć, że są tylko 2 stany: włączony i wyłączony. 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ż wszelkim 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 przeprowadzić kontrole opisane powyżej w metodie 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 powiadomienia 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. W dalszej części tego artykułu omówimy szczegóły obiektu subskrypcji.

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 nazywana Komunikacją w chmurze Google (GCM).

Tworzenie projektu w konsoli Firebase dla deweloperów

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.

Tworzenie nowego projektu dewelopera Firebase

Na początek musisz utworzyć 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 Komunikacja w chmurze w projekcie Firebase

Ta strona zawiera klucz interfejsu API do obsługi powiadomień push, którego użyjemy później, oraz identyfikator nadawcy, który musimy umieścić w pliku manifestu aplikacji internetowej w kolejnym rozdziale.

Dodawanie pliku manifestu aplikacji internetowej

Aby subskrypcja powiadomień push działała prawidłowo, musimy dodać plik manifestu z polem gcm_sender_id. Ten parametr jest wymagany tylko w przypadku przeglądarek Chrome, Opera na Androida i Samsung Browser, aby mogły one korzystać z usług FCM lub 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 sprawdzić, czy identyfikator nadawcy jest zgodny z odpowiednim kluczem interfejsu API, oraz czy użytkownik zezwolił Twojemu serwerowi na wysyłanie do niego powiadomień 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>"
}

Wartość parametru gcm_sender_id musi odpowiadać identyfikatorowi nadawcy w Twoim projekcie 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

Gdy masz już skonfigurowany plik manifestu, możesz wrócić do kodu JavaScript witryny.

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

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

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 wyświetlania powiadomień, przeglądarka wyświetli pierwsze powiadomienie i zastąpi je drugim powiadomieniem, gdy otrzyma wiadomość push.

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ń, więc nadszedł czas na wysłanie wiadomości push przez 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 na serwerze musisz sprawdzić, czy punkt końcowy jest przeznaczony do FCM. Jeśli tak, wyodrębnij identyfikator registration_id. 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 kwestie, o których należy pamiętać podczas wywoływania FCM:

  • Podczas wywołania interfejsu API musisz ustawić nagłówek Authorization (Autoryzacja) o wartości key=&lt;YOUR_API_KEY&gt;, gdzie &lt;YOUR_API_KEY&gt; to klucz interfejsu 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 tego projektu.
  • odpowiedni nagłówek Content-Type: application/json lub application/x-www-form-urlencoded;charset=UTF-8, w zależności od tego, czy dane są wysyłane w formacie JSON, czy w postaci danych formularza.
  • Tablica registration_ids – to identyfikatory rejestracji, które wyodrębniasz z punktów końcowych użytkowników.

Zapoznaj się z dokumentacją dotyczącą 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.

Zastąp w tym poleceniu cURL wartości &lt;YOUR_API_KEY&gt;&lt;YOUR_REGISTRATION_ID&gt; własnymi wartościami, a potem uruchom je w terminalu.

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. Dlatego wykryj, kiedy punkt końcowy jest przeznaczony dla FCM, i warunkowo dodaj nagłówek oraz sformatuj treść żądania POST. W przypadku innych przeglądarek (i być może w przyszłości Chrome) musisz zaimplementować protokół Web Push.

Wadą obecnej implementacji interfejsu Push API w Chrome jest to, że nie można wysyłać żadnych danych w ramach wiadomości 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.

Pełniejszy przykład zdarzenia push

Otrzymane do tej pory powiadomienie jest dość podstawowe i w przypadku próbek niezbyt dobrze odzwierciedla rzeczywiste przypadki użycia.

Większość użytkowników zechce uzyskać pewne informacje z serwera, zanim wyświetli powiadomienie. Mogą to być dane, które wypełniają tytuł i wiadomość powiadomienia, lub 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ź w 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.

Zauważysz, że wyświetlamy powiadomienie nawet wtedy, gdy wystąpi błąd. Jeśli tego nie zrobimy, Chrome wyświetli własne powiadomienie.

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ą.

W tym wpisie znajdziesz informacje o tym, co możesz robić za pomocą interfejsu Notification API.

Anulowanie 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). Poniżej znajduje się kod, który wykonuje dokładnie te czynności:

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 parsuje treść odpowiedzi żądania POST interfejsu FCM API, aby znaleźć wyniki 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 endpoint w pliku cookie, aby określić, czy serwer potrzebuje najnowszych informacji.

Wszystkie powyższe kroki prowadzą do pełnej implementacji wiadomości push w internecie w Chrome 46. Nadal istnieją specyfikacje funkcji, 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ę przekazać 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. Dzięki temu możesz 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 ramach usługi serviceworker-internals.

Jeśli problem dotyczy interakcji FCM z zdarzeniem push w serwisie workera, nie możesz wiele zrobić, aby go usunąć, ponieważ nie masz możliwości sprawdzenia, czy Chrome otrzymało jakieś dane. 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"}]}

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

Debugowanie usług Service Worker w Chrome na Androida

Obecnie debugowanie usług działających w tle w Chrome na Androida nie jest oczywiste. Otwórz stronę chrome://inspect, znajdź swoje urządzenie i poszukaj elementu na liście o nazwie „Worker pid:...”, który zawiera adres URL Twojego workera usługi.

Zrzut ekranu pokazujący, gdzie znajdują się usługi w Chrome Inspect

UX powiadomień push

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

Przyszłość powiadomień 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ć wiadomości push, wdrażając protokół Web Push Protocol.

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 osobno 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?

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 dublowaniu powiadomień, jeśli moja obecność w internecie ma wiele źródeł lub jeśli mam zarówno obecność w internecie, jak i w wersji natywnych?

Obecnie nie ma rozwiązania 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ć na podstawie rozmiaru ekranu, modelu urządzenia lub udostępnionego klucza wygenerowanego przez aplikację internetową i aplikację natywnych, ale każde z tych rozwiązań ma swoje wady i zalety.

Dlaczego muszę podać identyfikator gcm_sender_id?

Jest to konieczne, 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 jeśli strona jest zamknięta, usługa workera zostanie uruchomiona i będzie mogła wyświetlić powiadomienie. Po zamknięciu strony lub przeglądarki połączenia WebSockets i EventSource są zamykane.

Co zrobić, jeśli nie potrzebuję obsługi zdarzeń w tle?

Jeśli nie potrzebujesz przesyłania w tle, możesz skorzystać z Web Sockets.

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

Nie znamy jeszcze daty udostępnienia tej funkcji, ale zamierzamy wdrożyć synchronizację w tle. Chociaż nie podjęliśmy jeszcze decyzji ani nie mamy specyfikacji, rozważamy wdrożenie cichego pusha 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 przypadku produkcyjnych witryn, ale localhost będzie działać podczas tworzenia.

Jak wygląda obsługa przeglądarki?

Chrome obsługuje to w swojej stabilnej wersji, a Mozilla pracuje nad obsługą w wersji Nightly. Więcej informacji znajdziesz w błędzie implementacji interfejsu Push API. Ich implementację powiadomień możesz śledzić tutaj.

Czy po upływie określonego czasu mogę usunąć powiadomienie?

Obecnie nie jest to możliwe, ale planujemy dodać obsługę wyświetlania 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 Chrome nie otwiera poprzedniej karty, gdy klikam powiadomienie?

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