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 na pierwszym miejscu.

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 wymaga kilku różnych technologii, w tym plików manifestu aplikacji internetowych i skryptów service worker. W tym poście przyjrzymy się każdej z tych technologii, ale tylko absolutne minimum potrzebne do uruchomienia przekazu 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 przedstawimy odpowiedzi na najczęstsze pytania.

Wdrażanie komunikatów push w Chrome

W tej sekcji opisujemy każdy krok, który należy wykonać, aby obsługiwać przesyłanie wiadomości push w aplikacji internetowej.

Rejestrowanie skryptu Service Worker

Aby wdrożyć wiadomości push w internecie, potrzebny jest skrypt service worker. Dzieje się tak, ponieważ po otrzymaniu wiadomości push przeglądarka może uruchomić skrypt service worker, który działa w tle bez otwierania strony, i wysłać zdarzenie, aby umożliwić Ci podjęcie decyzji, jak obsłużyć ten komunikat push.

Poniżej znajduje się przykład rejestrowania skryptu service worker w aplikacji internetowej. Po 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.');
    }
});

Moduł obsługi kliknięć przycisku subskrybuje lub anuluje subskrypcję wiadomości push przez użytkownika. isPushEnabled to zmienna globalna, która po prostu śledzi, czy wiadomości push są obecnie subskrybowane. Będą przywoływane we wszystkich fragmentach kodu.

Następnie sprawdzamy, czy mechanizmy Service Worker są obsługiwane, zanim zarejestrujesz plik service-worker.js, który zawiera logikę obsługi wiadomości push. Tutaj po prostu informujemy przeglądarkę, że ten plik JavaScript jest skryptem service worker naszej witryny.

Konfigurowanie stanu początkowego

Przykład włączonego i wyłączonego UX w obszarze przesyłania wiadomości push w Chrome.

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

Użytkownicy oczekują, że w prostym interfejsie wiadomości push w Twojej witrynie będą włączone lub wyłączone, a także będzie na bieżąco śledzić wszelkie wprowadzane zmiany. Inaczej mówiąc, jeśli zespół obsługujący wiadomości push w Twojej witrynie, opuścił ją i wrócił tydzień później, interfejs powinien pokazywać, ż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.

Być może myślisz, że są tylko 2 stany: włączone lub wyłączone. Są jednak jeszcze inne stany dotyczące powiadomień, które musisz wziąć pod uwagę.

Schemat przedstawiający różne kwestie i stan przekazywania w Chrome

Istnieje wiele interfejsów API, które musimy sprawdzić, zanim włączymy przycisk. Jeśli wszystko jest obsługiwane, możemy włączyć nasz interfejs i ustawić stan początkowy, aby wskazać, czy wiadomości push są subskrybowane, czy nie.

Ponieważ większość tych testów kończy się wyłączeniem naszego interfejsu, ustaw stan początkowy na wyłączony. Dzięki temu unikniesz też nieporozumień, jeśli wystąpi problem z kodem JavaScript na Twojej stronie – na przykład nie będzie można pobrać pliku JS lub użytkownik wyłączył JavaScript.

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

W stanie początkowym możemy przeprowadzić testy opisane powyżej za pomocą metody initialiseState(), tj. już po zarejestrowaniu skryptu service worker.

// 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ótkie omówienie tych kroków:

  • Sprawdzamy, czy w prototypie ServiceWorkerRegistration jest dostępna właściwość showNotification. Bez niej nie będziemy mogli pokazywać powiadomień od naszego mechanizmu Service Worker o otrzymaniu wiadomości push.
  • Sprawdzamy bieżącą wartość Notification.permission, aby się upewnić, że to nie jest "denied". Odmowa dostępu oznacza, że nie możesz wyświetlać powiadomień, dopóki użytkownik ręcznie nie zmieni uprawnień w przeglądarce.
  • Aby sprawdzić, czy komunikaty push są obsługiwane, sprawdzamy, czy w obiekcie okna jest dostępna właściwość PushManager.
  • Na koniec użyliśmy funkcji pushManager.getSubscription(), aby sprawdzić, czy mamy już subskrypcję. W takim przypadku wysyłamy szczegóły subskrypcji na nasz serwer, aby mieć pewność, że mamy odpowiednie informacje, i ustawiamy w interfejsie użytkownika informację, że przesyłanie wiadomości push jest już włączone. Szczegóły obiektu subskrypcji przyjrzymy się bliżej w dalszej części tego artykułu.

Poczekaj, aż navigator.serviceWorker.ready zostanie rozwiązany, aby sprawdzić subskrypcję i włączyć przycisk push, ponieważ dopiero wtedy, gdy skrypt service worker jest aktywny, możesz subskrybować wiadomości push.

Następnym krokiem jest obsługa, gdy użytkownik chce włączyć wiadomości push, ale najpierw musimy skonfigurować projekt w Google Developer Console i dodać parametry do pliku manifestu za pomocą Komunikacji w chmurze Firebase (FCM) znanej wcześniej jako Google Cloud Messaging (GCM).

Tworzenie projektu w konsoli programisty Firebase

Chrome używa FCM do obsługi wysyłania i dostarczania wiadomości push. Aby jednak używać interfejsu FCM API, musisz skonfigurować projekt w konsoli programisty Firebase.

Poniższe kroki dotyczą przeglądarek Chrome, Opera na Androida i Samsunga, w których używają FCM. W dalszej części artykułu omówimy działanie tej funkcji w innych przeglądarkach.

Utwórz nowy projekt Firebase Developer

Na początek utwórz nowy projekt na stronie https://console.firebase.google.com/. W tym celu kliknij „Utwórz nowy projekt”.

Zrzut ekranu z nowego projektu Firebase

Dodaj nazwę i utwórz projekt, aby przejść do panelu projektu:

Strona główna projektu Firebase

W tym panelu kliknij ikonę koła zębatego obok nazwy projektu w lewym górnym rogu, a następnie „Ustawienia projektu”.

Menu ustawień projektu Firebase

Na stronie ustawień kliknij kartę „Komunikacja w chmurze”.

Menu Komunikacji w chmurze dotyczące projektu Firebase

Ta strona zawiera klucz interfejsu API do przesyłania komunikatów 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.

Parametr gcm_sender_id jest używany przez te przeglądarki, gdy subskrybują urządzenie użytkownika, korzystając z 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.

Poniżej znajduje się wyjątkowo 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 (dobrze to nazwa pliku manifest.json) odwołać się do niego w kodzie HTML, umieszczając w nagłówku strony poniższy tag.

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

Jeśli nie dodasz pliku manifestu witryny z tymi parametrami, nastąpi wyjątek, gdy spróbujesz zasubskrybować wiadomości push użytkownika, z błędem "Registration failed - no sender id provided" lub "Registration failed - permission denied".

Subskrybowanie wiadomości push

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

Aby zasubskrybować, musisz wywołać metodę subscribe() w obiekcie PushManager, do której dostęp jest uzyskiwany przez ServiceWorkerRegistration.

Spowoduje to wysłanie do użytkownika prośby o przyznanie Twojej źródła uprawnień do wysyłania powiadomień push. Bez tych uprawnień nie możesz rozpocząć subskrypcji.

Jeśli obietnica zwrócona przez metodę subscribe() zostanie zrealizowana, otrzymasz obiekt PushSubscription, który będzie zawierał punkt końcowy.

Punkt końcowy powinien zapisać na serwerze dla każdego użytkownika, ponieważ będzie on potrzebny później do wysyłania wiadomości push.

Ten kod umożliwia subskrybowanie użytkownika w wiadomościach 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';
        }
        });
    });
}

Na tym etapie Twoja aplikacja internetowa jest gotowa do odbierania komunikatów push, ale nic się nie stanie, dopóki nie dodasz detektora zdarzeń push do naszego pliku mechanizmu Service Worker.

Detektor zdarzeń push instancji usługi Service Worker

Po otrzymaniu wiadomości push (o tym, jak faktycznie ją wysłać, dowiesz się w następnej sekcji), do skryptu service worker zostanie wysłane zdarzenie push, w którym 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 zdarzeń push i wyświetla powiadomienie ze wstępnie zdefiniowanym tytułem, treścią, ikoną i tagiem powiadomienia. W tym przykładzie warto wspomnieć o metodzie event.waitUntil(). Ta metoda przyjmuje obietnicę i przedłuża okres życia modułu obsługi zdarzeń (lub można ją traktować jako utrzymanie aktywności skryptu usługi) do momentu spłacenia obietnicy. W tym przypadku obietnica przekazywana do event.waitUntil jest obietnicą zwróconą przez showNotification().

Tag powiadomień działa jak identyfikator unikalnych powiadomień. Jeśli wysłaliśmy 2 wiadomości push do tego samego punktu końcowego z krótkim opóźnieniem między nimi i wyświetlimy powiadomienia z tym samym tagiem, przeglądarka wyświetli pierwsze powiadomienie, a po jego otrzymaniu zastąpi je drugie.

Jeśli chcesz jednocześnie wyświetlić kilka powiadomień, użyj innego tagu lub nie używaj żadnego tagu. Bardziej szczegółowy przykład wyświetlania powiadomienia omówimy w dalszej części tego posta. Na razie posłużmy się prostotą i zobaczmy, czy po wysłaniu wiadomości push wyświetlimy to powiadomienie.

Wysyłanie wiadomości push

Zasubskrybowaliśmy wiadomości push, więc nasz skrypt service worker jest gotowy do wyświetlania powiadomień, więc pora wysłać wiadomość przez FCM.

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

Gdy wysyłasz zmienną PushSubscription.endpoint na swój serwer, punkt końcowy FCM jest wyjątkowy. Ma on na końcu adres URL parametr registration_id.

Przykładowy punkt końcowy to:

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 normalnej przeglądarce wystarczy uzyskać punkt końcowy i wywołać go w standardowy sposób. Działa on 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. W Pythonie możesz użyć np.:

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

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

Po uzyskaniu identyfikatora rejestracji możesz wywołać interfejs FCM API. Dokumenty referencyjne dotyczące FCM API znajdziesz tutaj.

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

  • Podczas wywoływania interfejsu API należy ustawić nagłówek Authorization o wartości key=&lt;YOUR_API_KEY&gt;, gdzie &lt;YOUR_API_KEY&gt; to klucz interfejsu API z projektu Firebase.
    • FCM używa klucza interfejsu API, aby znaleźć odpowiedni identyfikator nadawcy, sprawdzić, czy użytkownik przyznał Ci uprawnienia do Twojego projektu, oraz sprawdzić, czy adres IP serwera znajduje się na liście dozwolonych w tym projekcie.
  • 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 – identyfikatory rejestracji wyodrębnione z punktów końcowych użytkowników.

Zapoznaj się z dokumentacją, aby dowiedzieć się, jak wysyłać wiadomości push z serwera. Aby szybko sprawdzić mechanizm Service Worker, możesz użyć narzędzia cURL do wysłania wiadomości 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.

Powinno wyświetlić się piękne powiadomienie:

    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.

Opracowując logikę backendu, pamiętaj, że nagłówek autoryzacji i format treści POST są powiązane z punktem końcowym FCM, dlatego wykryj, kiedy punkt końcowy dotyczy FCM, i warunkowo dodaj nagłówek i 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 wiadomościach push. Nic. Powodem jest to, że w przyszłej implementacji dane ładunków będą musiały być zaszyfrowane na Twoim serwerze, zanim zostaną wysłane do punktu końcowego przesyłania komunikatów push. Dzięki temu punkt końcowy, niezależnie od tego, jaki jest dostawcą push, nie będzie mógł w łatwy sposób wyświetlić treści wiadomości push. Chroni to też przed innymi lukami w zabezpieczeniach, takimi jak niska weryfikacja certyfikatów HTTPS czy ataki typu „man in the middle” pomiędzy serwerem a dostawcą usług push. Jednak to szyfrowanie nie jest jeszcze obsługiwane, więc tymczasem musisz je pobrać, aby uzyskać informacje potrzebne do wypełnienia powiadomienia.

Bardziej kompletny przykład zdarzenia push

Powiadomienie, które widzieliśmy do tej pory, jest dość proste, ale jeśli chodzi o przykłady, nie radzi sobie z aktualnym zastosowaniem.

W rzeczywistości większość osób będzie chciała uzyskać pewne informacje ze swojego serwera, przed wyświetleniem powiadomienia. Mogą to być dane, które uzupełnią tytuł powiadomienia i komunikat o konkretne informacje lub pójdą o krok dalej i zapiszą w pamięci podręcznej niektóre strony lub dane, tak aby po kliknięciu powiadomienia przez użytkownika wszystko było dostępne od razu po otwarciu przeglądarki, nawet jeśli sieć jest w danym czasie niedostępna.

W poniższym kodzie pobieramy niektóre dane z interfejsu API, konwertujemy odpowiedź na obiekt i użyjemy jej do wypełnienia 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() spełnia obietnicę, która skutkuje obietnicą zwróconą przez showNotification(). Oznacza to, że nasz odbiornik nie zakończy działania, dopóki asynchroniczne wywołanie fetch() nie zostanie zakończone i wyświetli się 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, z Twojego skryptu service worker wysyłane jest zdarzenie notificationclick. W module obsługi możesz wykonać odpowiednie działanie, np. zaznaczyć kartę 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 otwieramy przeglądarkę na poziomie głównym źródła witryny, ustawiając zaznaczenie na dotychczasowej karcie z tym samym źródłem (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.

Anulowanie subskrypcji urządzenia użytkownika

Po zasubskrybowaniu urządzenia użytkownika otrzymujesz wiadomości push. Jak anulować jego subskrypcję?

Aby anulować subskrypcję na urządzeniu użytkownika, musisz najpierw wywołać metodę unsubscribe() w obiekcie PushSubscription i usunąć punkt końcowy z serwerów (aby nie wysyłać wiadomości push, które nie będą odbierane). 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ą nie być zsynchronizowane między FCM a Twoim serwerem. Upewnij się, że serwer analizuje treść odpowiedzi żądania POST wysyłanego przez interfejs FCM API pod kątem wyników error:NotRegistered i canonical_id, jak opisano w dokumentacji FCM.

Subskrypcje mogą też nie być zsynchronizowane między skryptem service worker a Twoim serwerem. Na przykład po pomyślnym zasubskrybowaniu lub cofnięciu subskrypcji niestabilne połączenie sieciowe może uniemożliwić zaktualizowanie serwera. Użytkownik może też cofnąć uprawnienia do powiadomień, co spowoduje automatyczne anulowanie subskrypcji. W takich przypadkach należy okresowo sprawdzać wynik działania funkcji serviceWorkerRegistration.pushManager.getSubscription() (np. podczas wczytywania strony) i synchronizować go z serwerem. Jeśli nie masz już subskrypcji, możesz dokonać automatycznej subskrypcji i powiadomienia o powiadomieniu == 'granted'.

W narzędziu sendSubscriptionToServer() trzeba wziąć pod uwagę sposób obsługi nieudanych żądań sieciowych podczas aktualizowania narzędzia 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ą wyspecjalizowane funkcje, które to ułatwią (np. standardowy interfejs API do wyzwalania wiadomości push), ale ta wersja już dziś umożliwia rozpoczęcie tworzenia komunikatów push w aplikacjach internetowych.

Debugowanie aplikacji internetowej

Podczas wdrażania komunikatów push błędy będą się znajdować w jednym z 2 miejsc: na Twojej stronie lub w skrypcie service worker.

Błędy na stronie można debugować za pomocą DevTools. Istnieją 2 sposoby debugowania problemów z skryptami service worker:

  1. Otwórz chrome://inspect > Skrypty service worker. Ten widok nie zawiera wielu informacji poza uruchomionymi obecnie skryptami service worker.
  2. Otwórz chrome://serviceworker-internals, aby wyświetlić stan instancji service worker i sprawdzić ewentualne błędy. Ta strona jest tymczasowa, dopóki w Narzędziach deweloperskich nie będzie dostępny podobny zestaw funkcji.

Jedną z najlepszych wskazówek, które mogę dać początkującym użytkownikom Service Worker, jest skorzystanie z pola wyboru o nazwie „Otwórz okno narzędzi deweloperskich i wstrzymaj wykonywanie JavaScriptu przy uruchamianiu mechanizmu Service Worker na potrzeby debugowania”. To pole wyboru dodaje punkt przerwania na początku skryptu service worker i wstrzymanie wykonywania. Dzięki temu możesz wznowić lub przejrzeć skrypt tego skryptu i sprawdzić, czy nie wystąpiły żadne problemy.

Zrzut ekranu pokazujący, gdzie w obiekcie serviceworker-internal znajduje się pole wyboru wstrzymywania wykonywania kodu.

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ź z FCM była skuteczna na wywołanie interfejsu API przez serwer. Będzie to wyglądać 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 widzisz błąd, oznacza to, że coś jest nie tak z identyfikatorem rejestracji FCM i komunikat push nie jest wysyłany do Chrome.

Debugowanie Service Worker w Chrome na Androida

Obecnie debugowanie instancji roboczych 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 dla powiadomień push

Zespół Chrome przygotował dokument ze sprawdzonymi metodami korzystania z powiadomień push oraz dokument opisujący niektóre skrajne przypadki pracy z powiadomieniami push.

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

W tej sekcji znajdziesz szczegółowe informacje o niektórych częściach implementacji Chrome, o których trzeba pamiętać, oraz o tym, co odróżnia je od innych implementacji.

Protokół Web Push Protocol i Endpoints

Największą zaletą standardu Push API jest to, że można pobierać punkty końcowe, przekazywać je na serwer i wysyłać komunikaty push przy użyciu protokołu Web Push Protocol.

Web Push Protocol to nowy standard, który mogą wdrożyć dostawcy usług push. Dzięki temu deweloperzy nie muszą się martwić o to, kto jest dostawcą usługi push. Dzięki temu nie trzeba rejestrować się w celu korzystania z kluczy interfejsu API i wysyłać specjalnie sformatowanych danych, jak ma to miejsce w FCM.

Chrome była pierwszą przeglądarką, w której zaimplementowano interfejs Push API, a FCM nie obsługuje protokołu Web Push Protocol. Dlatego Chrome wymaga gcm_sender_id. W FCM musisz używać interfejsu API zapewniającego spokój.

Ostatnim celem Chrome jest przejście na protokół Web Push Protocol w Chrome i FCM.

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

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

Firefox Nightly pracuje obecnie nad trybem push i prawdopodobnie będzie pierwszą przeglądarką, w której zostanie wdrożony protokół Web Push Protocol.

Najczęstsze pytania

Gdzie są dane techniczne?

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.

Najlepiej byłoby, gdyby po stronie serwera identyfikator urządzenia użytkownika został dopasowany do identyfikatorów subskrypcji aplikacji natywnej i aplikacji internetowej, co pozwala zdecydować, do którego 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 potrzebuję identyfikatora gcm_sender_id?

Jest to wymagane, aby przeglądarki Chrome, Opera na Androida i Samsunga mogły korzystać z interfejsu Firebase Cloud Messaging (FCM) API. Celem jest użycie protokołu Web Push Protocol, gdy standard zostanie sfinalizowany i FCM będzie go obsługiwać.

Dlaczego nie warto używać Web Sockets lub 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ć funkcji push bez pokazywania powiadomień (np. ciche powiadomienia push 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 wymagany jest protokół HTTPS? Jak mogę obejść ten problem na etapie tworzenia aplikacji?

Skrypty service worker wymagają bezpiecznych źródeł, aby mieć pewność, że pochodzą z zamierzonego źródła i nie pochodzą z ataku typu „man in the middle”. Obecnie oznacza to korzystanie z protokołu HTTPS w aktywnych witrynach, chociaż host lokalny będzie działać na etapie programowania.

Jak wygląda obsługa przeglądarek?

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 istnieje jakiś przypadek użycia, który pozwala ustawić datę wygaśnięcia powiadomienia po jego utworzeniu, chętnie się dowiemy, co to jest. Napisz komentarz, a my przekażemy go zespołowi Chrome.

Jeśli chcesz tylko zatrzymać wysyłanie powiadomień push do użytkownika po określonym czasie i nie zależy Ci na tym, jak długo powiadomienie będzie widoczne, możesz użyć parametru czasu życia danych (TTL) w FCM. Więcej informacji znajdziesz tutaj.

Jakie są ograniczenia komunikatów push w Chrome?

Istnieje kilka ograniczeń opisanych w tym poście:

  • Wykorzystanie CCM jako usługi push w Chrome wiąże się z pewnymi zastrzeżonymi wymaganiami. Wspólnie pracujemy nad tym, czy w przyszłości uda się nam rozwiązać niektóre z tych problemów.
  • Po otrzymaniu wiadomości push musisz pokazać powiadomienie.
  • Chrome na komputerze ma jednak pewne ograniczenie, które polega na tym, że jeśli Chrome nie jest uruchomiony, wiadomości push nie są odbierane. Różni się to od systemów ChromeOS i Android, gdzie wiadomości push są zawsze odbierane.

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

Interfejs Permission API jest zaimplementowany w Chrome, ale nie musi działać 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 się stanie, jeśli powiadomienie będzie nieaktualne w chwili otrzymania urządzenia użytkownika?

Po otrzymaniu wiadomości push musisz zawsze pokazywać powiadomienie. Jeśli chcesz wysłać powiadomienie, ale jest ono przydatne tylko przez określony czas, możesz użyć w narzędziu CCM parametru „time_to_live”, dzięki czemu FCM nie wyśle wiadomości push po upływie terminu wygaśnięcia.

Więcej informacji znajdziesz tutaj

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

FCM ma parametr „Zwiń_key”, dzięki któremu można poinformować usługę FCM, że ma zastąpić oczekującą wiadomość, która ma ten sam element „Zwiń_key”, nową wiadomością.

Więcej informacji znajdziesz tutaj