Powiadomienia push w otwartej sieci

Jeśli zapytasz zespół programistów, jakich funkcji urządzeń mobilnych brakuje w internecie, powiadomienia push zawsze będą na pierwszym miejscu.

Powiadomienia push pozwalają użytkownikom wyrazić zgodę na otrzymywanie aktualnych informacji z ulubionych witryn, a Ty możesz skutecznie zachęcać ich do ponownego zaangażowania się, wyświetlając im dostosowane, interesujące treści.

Od wersji 42 Chrome – interfejsy Push API i powiadomienia API są dostępne dla deweloperów.

Interfejs Push API w Chrome korzysta z kilku różnych technologii, w tym z plików manifestu aplikacji internetowych i skryptów Service Worker. W tym poście omówimy każdą z tych technologii. Jest to jednak tylko absolutne minimum, dzięki któremu można wyświetlać komunikaty 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.

Zajmiemy się również tym, co dodamy do tego interfejsu API w kolejnych wersjach Chrome, a na koniec odpowiemy na najczęstsze pytania.

Wdrażanie komunikatów push w Chrome

Ta sekcja zawiera opis wszystkich czynności, które musisz wykonać, aby obsługiwać wiadomości push w Twojej aplikacji internetowej.

Rejestrowanie skryptu service worker

Do wdrożenia wiadomości push w internecie potrzebny jest skrypt service worker. Dzieje się tak dlatego, że po otrzymaniu wiadomości push przeglądarka może uruchomić skrypt service worker, który działa w tle bez otwartej strony, i wysłać zdarzenie, aby umożliwić Ci określenie sposobu obsługi danej wiadomości push.

Poniżej znajduje się przykład rejestracji skryptu service worker w aplikacji internetowej. Po pomyślnym zakończeniu rejestracji wywołujemy funkcję initialiseState(), którą wkrótce omówimy.

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 po kliknięciu przycisku subskrybuje lub anuluje subskrypcję wiadomości push. isPushEnabled to zmienna globalna, która tylko śledzi, czy wiadomości push są aktualnie subskrybowane. Będą odwoływane we wszystkich fragmentach kodu.

Przed zarejestrowaniem pliku service-worker.js, który zawiera logikę obsługi wiadomości push, sprawdzamy, czy mechanizmy Service Worker są obsługiwane. W tym miejscu po prostu informujemy przeglądarkę, że ten plik JavaScript to skrypt service worker naszej witryny.

Konfigurowanie stanu początkowego

Przykład włączonej i wyłączonej funkcji przesyłania wiadomości push w Chrome

Po zarejestrowaniu skryptu service worker musimy skonfigurować stan interfejsu użytkownika.

Użytkownicy spodziewają się prostego interfejsu, który umożliwi im włączanie i wyłączanie komunikatów push w Twojej witrynie. Będą też oczekiwali, że będzie on uwzględniał wszystkie wprowadzane zmiany. Innymi słowy, jeśli klient włączy wiadomości push, opuści witrynę i wróci w późniejszym czasie, a interfejs powinien zaznaczyć, że ta funkcja jest już włączona.

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

W tej chwili może Ci się wydawać, że istnieją tylko 2 stany: „włączone” lub „wyłączone”. Są jednak inne stany dotyczące powiadomień, które musisz wziąć pod uwagę.

Diagram przedstawiający różne uwagi i stan operacji push w Chrome

Jest wiele interfejsów API, które musimy sprawdzić przed włączeniem naszego przycisku. Jeśli wszystko jest obsługiwane, możemy włączyć interfejs i ustawić początkowy stan, aby wskazać, czy wiadomości push są subskrybowane.

Ponieważ większość tych testów powoduje wyłączenie naszego interfejsu, w takim przypadku ustaw stan początkowy jako wyłączony. Pozwala to także uniknąć ewentualnych pomyłek w przypadku problemów z kodem JavaScript strony, np. gdy nie można pobrać pliku JS lub użytkownik wyłączył JavaScript.

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

Przy takim stanie początkowym możemy przeprowadzić testy opisane powyżej w metodzie initialiseState(), tj. po zarejestrowaniu naszego 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 zasada showNotification jest dostępna w prototypie ServiceWorkerRegistration. Bez niego nie możemy pokazać powiadomienia od naszego skryptu service worker o odbiorze wiadomości push.
  • Sprawdzamy obecną wartość Notification.permission, aby upewnić się, że nie jest to "denied". Odmowa dostępu oznacza, że nie możesz wyświetlać powiadomień, dopóki użytkownik nie zmieni uprawnień w przeglądarce ręcznie.
  • Aby sprawdzić, czy komunikaty push są obsługiwane, sprawdzamy, czy element PushManager jest dostępny w obiekcie window.
  • Na koniec skorzystaliśmy z pushManager.getSubscription(), aby sprawdzić, czy mamy już subskrypcję. Następnie przekazujemy szczegóły subskrypcji na nasz serwer, aby mieć pewność, że mamy odpowiednie informacje, i określamy w interfejsie użytkownika, czy funkcja push jest już włączona. W dalszej części artykułu omówimy szczegóły obiektu subskrypcji.

Czekamy na rozwiązanie navigator.serviceWorker.ready, aby sprawdzić subskrypcję i włączyć przycisk push, ponieważ dopiero po aktywowaniu skryptu service worker możesz zasubskrybować wiadomości push.

Następnym krokiem jest informacja o tym, że użytkownik chce włączyć komunikaty push, ale zanim to zrobimy, musimy skonfigurować projekt w Google Developers Console i dodać do pliku manifestu kilka parametrów, aby umożliwić korzystanie z Firebase Cloud Messaging (FCM) (dawniej Google Cloud Messaging (GCM).

Tworzenie projektu w Konsoli programisty Firebase

Chrome używa usługi FCM do wysyłania i dostarczania komunikatów push. Aby jednak korzystać z interfejsu FCM API, musisz skonfigurować projekt w konsoli programisty Firebase.

Poniższe kroki dotyczą przeglądarek Chrome, Opera na Androida i przeglądarki Samsung, w których używana jest usługa FCM. Działanie takiego narzędzia w innych przeglądarkach zostanie omówione w dalszej części artykułu.

Tworzenie nowego projektu programisty Firebase

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

Zrzut ekranu nowego projektu Firebase

Aby otworzyć panel projektu, dodaj jego nazwę i utwórz go.

Strona główna projektu Firebase

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

Menu ustawień projektu Firebase

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

Menu wiadomości w chmurze w projekcie Firebase

Ta strona zawiera klucz interfejsu API do komunikatów push, którego użyjemy później, oraz identyfikator nadawcy, który musimy umieścić w pliku manifestu aplikacji internetowej w następnej sekcji.

Dodaj plik manifestu aplikacji internetowej

W przypadku wiadomości push musimy dodać plik manifestu z polem gcm_sender_id, aby subskrypcja push zakończyła się powodzeniem. Ten parametr jest wymagany tylko przez Chrome, Opera na Androida i przeglądarkę Samsung, ponieważ umożliwia korzystanie z FCM / GCM.

Te przeglądarki używają identyfikatora gcm_sender_id, gdy subskrybuje urządzenie użytkownika w FCM. Oznacza to, że FCM może zidentyfikować urządzenie użytkownika i sprawdzić, czy Twój identyfikator nadawcy jest zgodny z odpowiednim kluczem interfejsu API, a użytkownik zezwolił Twojemu serwerowi na wysyłanie komunikatów push.

Poniżej znajduje się 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>"
}

Ustaw wartość gcm_sender_id na identyfikator nadawcy z projektu Firebase.

Po zapisaniu pliku manifestu w projekcie (dobra nazwa to manifest.json), odwoływanie się do niego w kodzie HTML za pomocą poniższego tagu w nagłówku strony.

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

Jeśli nie dodasz pliku manifestu internetowego z tymi parametrami, próba zasubskrybowania wiadomości push przez użytkownika spowoduje wystąpienie błędu "Registration failed - no sender id provided" lub "Registration failed - permission denied".

Subskrybuj Push Messaging

Po skonfigurowaniu pliku manifestu możesz wrócić do kodu JavaScript swojej witryny.

Aby zasubskrybować, musisz wywołać metodę subscribe() w obiekcie PushManager, do którego możesz uzyskać dostęp przez ServiceWorkerRegistration.

Spowoduje to poproszenie użytkownika o przyznanie Twojemu punktowi początkowego uprawnień do wysyłania powiadomień push. Bez tych uprawnień nie możesz zasubskrybować kanału.

Jeśli obietnica zwrócona przez metodę subscribe() zadziała, 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ędzie on później potrzebny do wysyłania wiadomości push.

Ten kod pozwala zasubskrybować wiadomości 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';
        }
        });
    });
}

W tym momencie Twoja aplikacja internetowa jest gotowa do odbioru wiadomości push, ale nic się nie stanie, dopóki nie dodamy detektora zdarzeń push do pliku skryptu service worker.

Detektor zdarzeń push w mechanizmie Service Worker

Po otrzymaniu wiadomości push (opisanej w następnej sekcji, jak wysłać wiadomość push), zostanie wysłane zdarzenie pushdo skryptu service worker, które musi 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, tekstem, ikoną i tagiem powiadomienia. W tym przykładzie warto zwrócić uwagę na metodę event.waitUntil(). Ta metoda przyjmuje obietnicę i wydłuża okres działania modułu obsługi zdarzeń (lub można ją traktować jako utrzymanie działania instancji roboczej usługi) do czasu spłacenia obietnicy. W tym przypadku obietnica przekazana do event.waitUntil jest zwróconą obietnicą z showNotification().

Tag powiadomienia służy jako identyfikator niepowtarzalnych powiadomień. Jeśli wyślesz 2 komunikaty push do tego samego punktu końcowego (z krótkim opóźnieniem między nimi) i wyświetli powiadomienie z tym samym tagiem, przeglądarka wyświetli pierwsze powiadomienie i zastąpi je drugim po otrzymaniu wiadomości push.

Jeśli chcesz wyświetlać wiele powiadomień jednocześnie, użyj innego tagu lub nie używaj żadnego tagu. Pełniejszy przykład wyświetlania powiadomienia omówimy w dalszej części tego posta. Na razie zostawmy prosto i sprawdźmy, czy wysłanie wiadomości push spowoduje wyświetlenie tego powiadomienia.

Wysyłanie wiadomości push

Subskrybujemy wiadomości push, a nasz skrypt service worker jest gotowy do wyświetlania powiadomień, dlatego czas na wysłanie wiadomości 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 specjalny. Na końcu adresu URL znajduje się parametr registration_id.

Przykładowy punkt końcowy może wyglądać tak:

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

Adres URL FCM:

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

registration_id to:

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

Problem dotyczy tylko przeglądarek korzystających z FCM. W normalnej przeglądarce uzyskujesz po prostu punkt końcowy, który wywołasz w standardowy sposób. Działa on niezależnie od adresu URL.

Oznacza to, że na serwerze musisz sprawdzić, czy punkt końcowy jest przeznaczony dla FCM, a jeśli tak, wyodrębnić identyfikator rejestracji. Możesz to zrobić w Pythonie, na przykład:

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. Dokumentacja referencyjna dotycząca interfejsu FCM API znajdziesz tutaj.

Oto najważniejsze kwestie, o których należy pamiętać podczas wywoływania funkcji FCM:

  • Podczas wywoływania interfejsu API musisz 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 do znajdowania odpowiedniego identyfikatora nadawcy, sprawdzania, czy użytkownik przyznał Ci uprawnienia do projektu, a na koniec sprawdź, 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 przesyłasz dane w formacie JSON czy w formie formularza.
  • Tablica registration_ids – to identyfikator rejestracji, który należy wyodrębnić z punktów końcowych użytkowników.

Zajrzyj do dokumentacji na temat wysyłania wiadomości push z serwera. Aby sprawdzić działanie skryptu service worker, możesz wysłać wiadomość do przeglądarki za pomocą cURL.

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

Zobaczysz doskonałe 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

Podczas opracowywania logiki backendu pamiętaj, że nagłówek i format treści POST są specyficzne dla punktu końcowego FCM, więc wykrywaj, kiedy punkt końcowy jest przeznaczony dla FCM, i warunkowo dodaj nagłówek i sformatuj treść POST. W innych przeglądarkach (i, w przyszłości, w Chrome) konieczne będzie wdrożenie protokołu 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łości dane ładunku będą musiały być zaszyfrowane na serwerze, zanim zostaną wysłane do punktu końcowego komunikatów push. Dzięki temu punkt końcowy niezależnie od jego dostawcy nie będzie mógł łatwo wyświetlić treści wiadomości push. Chroni to również przed innymi lukami w zabezpieczeniach, takimi jak niewłaściwa weryfikacja certyfikatów HTTPS i ataki typu „man in the middle” między Twoim serwerem a dostawcą usługi push. To szyfrowanie nie jest jeszcze obsługiwane, więc w międzyczasie musisz pobrać dane, aby uzyskać informacje potrzebne do wypełnienia powiadomienia.

Przykład bardziej kompletnego wydarzenia push

Powiadomienie, które widzimy do tej pory, jest dość podstawowe, a jeśli chodzi o próbki, niewiele im brakuje do rzeczywistego zastosowania.

W rzeczywistości większość użytkowników chce uzyskać pewne informacje od swojego serwera przed wyświetleniem powiadomienia. Mogą to być dane, które mają nam służyć do wpisania czegoś konkretnego w tytule powiadomienia lub wiadomości. Można też zrobić krok dalej i zapisać niektóre strony lub dane w pamięci podręcznej, by 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 momencie niedostępna.

W poniższym kodzie pobieramy dane z interfejsu API, konwertujemy odpowiedź na obiekt i wykorzystujemy ją 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
        });
    })
    );
});

Ponownie warto podkreślić, że funkcja event.waitUntil() przyjmuje obietnicę, której rezultatem jest obietnica zwrócona przez interfejs showNotification(). Oznacza to, że nasz detektor zdarzeń nie zakończy się do czasu zakończenia asynchronicznego wywołania fetch() i wyświetlenia powiadomienia.

Zauważysz, że powiadomienie jest wyświetlane nawet wtedy, gdy wystąpił błąd. Jeśli tego nie zrobimy, Chrome wyświetli ogólne powiadomienie.

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

Gdy użytkownik kliknie powiadomienie, w skrypcie service worker wysyłane jest zdarzenie notificationclick. W obrębie modułu 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 otwierany jest w przeglądarce katalog główny źródła witryny przez skupienie istniejącej karty tego samego pochodzenia (jeśli taka istnieje) i otwarcie nowej.

W poście poświęconym tym, co możesz zrobić dzięki interfejsowi Notification API, znajdziesz post.

Anulowanie subskrypcji urządzenia użytkownika

Masz subskrypcję na urządzeniu użytkownika i dostaje on wiadomości push. Jak możesz jednak anulować ich subskrypcję?

Najważniejsze, co trzeba zrobić, aby anulować subskrypcję na urządzeniu użytkownika, to wywołanie metody unsubscribe() w obiekcie PushSubscription i usunięcie punktu końcowego z serwerów (dzięki czemu nie wysyłasz wiadomości push, o których wiesz, że nie będą odbierane). Poniższy kod odpowiada dokładnie tak:

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

Dbanie o aktualność subskrypcji

Subskrypcje mogą nie być zsynchronizowane między FCM a Twoim serwerem. Upewnij się, że serwer analizuje treść odpowiedzi wysyłanego żądania POST interfejsu FCM API w poszukiwaniu wyników error:NotRegistered i canonical_id, tak jak to opisano w dokumentacji FCM.

Subskrypcje mogą też nie być zsynchronizowane między skryptem service worker a Twoim serwerem. Na przykład po zasubskrybowaniu lub anulowaniu subskrypcji niestabilne połączenie sieciowe może uniemożliwiać zaktualizowanie serwera albo użytkownik może anulować uprawnienia do powiadomień, co spowoduje automatyczne anulowanie subskrypcji. Aby sobie z nimi radzić, okresowo sprawdzaj wyniki funkcji serviceWorkerRegistration.pushManager.getSubscription() (np. podczas wczytywania strony) i synchronizuj je z serwerem. Jeśli nie masz już subskrypcji i nie masz już subskrypcji, możesz też odnowić subskrypcję automatycznie.

W sendSubscriptionToServer() musisz zastanowić się, jak postępujesz w przypadku nieudanych żądań sieciowych podczas aktualizowania endpoint. Jednym z rozwiązań jest śledzenie stanu endpoint w pliku cookie, aby określić, czy serwer potrzebuje najnowszych informacji.

Po wykonaniu wszystkich powyższych czynności w Chrome 46 możesz w pełni wdrożyć komunikaty push w sieci. Istnieją funkcje, które ułatwią Ci pracę (np. standardowy interfejs API do wyzwalania komunikatów push), ale ta wersja pozwala już dziś tworzyć komunikaty push w aplikacjach internetowych.

Jak debugować aplikację internetową

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

Błędy na stronie można naprawić za pomocą DevTools. Istnieją 2 możliwości debugowania problemów z skryptem service worker:

  1. Otwórz chrome://inspect > Skrypty service worker. Ten widok nie zawiera wielu informacji innych niż obecnie uruchomione mechanizmy Service Worker.
  2. Otwórz chrome://serviceworker-internals, aby wyświetlić stan mechanizmów Service Worker i sprawdzić ewentualne błędy. Ta strona jest tymczasowa, dopóki w Narzędziach deweloperskich nie będzie podobny zestaw funkcji.

Jedną z najlepszych wskazówek, które mogę przekazać każdemu, kto nie ma doświadczenia z mechanizmami Service Worker, jest zaznaczenie pola wyboru „Otwórz okno Narzędzi deweloperskich i wstrzymaj wykonywanie kodu JavaScript przy uruchamianiu skryptu service worker na potrzeby debugowania”. To pole wyboru spowoduje dodanie punktu przerwania na początku działania skryptu service worker i wstrzymanie wykonywania. Pozwala to wznowić działanie skryptu service worker lub sprawdzić, czy nie wystąpił jakiś problem.

Zrzut ekranu pokazujący, gdzie znajduje się pole wyboru wstrzymania wykonywania w skrypcie service worker-internals.

Jeśli wygląda na to, że istnieje problem między FCM a zdarzeniem push Twojego skryptu service worker, niewiele możesz zrobić, by go debugować, bo nie ma możliwości sprawdzenia, czy Chrome cokolwiek otrzymał. Najważniejsze jest, aby odpowiedź z FCM była skuteczna, gdy serwer wywoła interfejs API. Będzie to wyglądać 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, będzie to oznaczać, że coś jest nie tak z identyfikatorem rejestracji w FCM, a wiadomość push nie jest wysyłana do Chrome.

Debugowanie skryptu service worker w Chrome na Androida

Obecnie debugowanie skryptu service worker w Chrome na Androida nie jest oczywiste. Przejdź na stronę chrome://inspect, znajdź swoje urządzenie i znajdź na liście element o nazwie „Worker pid:....” z adresem URL skryptu service worker.

Zrzut ekranu pokazujący, gdzie znajdują się mechanizmy Service Worker w ramach inspekcji Chrome

UX dla powiadomień push

Zespół Chrome przygotował dokument ze sprawdzonymi metodami w zakresie korzystania z powiadomień push, a także dokument na temat kilku skrajnych przypadków korzystania z powiadomień push.

Przyszłość komunikatów push w Chrome i otwartej sieci

W tej sekcji omawiamy wybrane aspekty tej implementacji Chrome, o których warto wiedzieć i czym będzie się ona różniła od innych implementacji przeglądarek.

Protokół Web Push Protocol i punkty końcowe

Piękno standardu Push API polega na tym, że możesz pobierać punkty końcowe, przekazywać je na serwer i wysyłać wiadomości push za pomocą protokołu Web Push Protocol.

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

Chrome jako pierwsza przeglądarka wdrożyła interfejs Push API, a FCM nie obsługuje protokołu Web Push Protocol, dlatego Chrome wymaga gcm_sender_id, a w FCM musisz używać interfejsu API spokoju.

Ostatecznym celem Chrome jest wykorzystanie protokołu 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, np. sformatować dane ładunku w określony sposób i dodać klucz autoryzacji.

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

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

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 witryna ma wiele źródeł lub jeśli jestem obecna zarówno w internecie, jak i w rodzinie?

W tej chwili nie ma rozwiązania, ale możesz śledzić postępy w Chromium.

Idealny scenariusz to udostępnienie identyfikatora urządzenia użytkownika, a następnie po stronie serwera dopasowanie identyfikatorów subskrypcji aplikacji natywnej i aplikacji internetowej oraz wybranie, do którego chcesz wysłać wiadomość push. Można to zrobić na podstawie rozmiaru ekranu, modelu urządzenia oraz wygenerowanego klucza między aplikacją internetową a aplikacją natywną, ale każde z tych rozwiązań ma swoje wady i zalety.

Do czego potrzebny jest identyfikator gcm_sender_id?

Jest to wymagane, aby przeglądarki Chrome, Opera na Androida i przeglądarki Samsung mogły korzystać z interfejsu Firebase Cloud Messaging (FCM) API. Celem jest użycie protokołu Web Push Protocol po utworzeniu standardu i jego obsłudze przez FCM.

Dlaczego nie można używać funkcji Web Sockets ani zdarzeń wysłanych przez serwer (EventSource)?

Zaletą wiadomości push jest to, że nawet po zamknięciu strony skrypt service worker zostanie wybudzony i będzie mógł wyświetlić powiadomienie. Połączenia WebSockets i EventSource są zamykane w momencie zamknięcia strony lub przeglądarki.

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

Jeśli nie chcesz korzystać z usługi dostarczania poczty w tle, dobrym rozwiązaniem tego problemu są Web Sockets.

Kiedy mogę używać funkcji push bez pokazywania powiadomień (tj. z cichego push w tle)?

Nie wiemy jeszcze, kiedy ta funkcja będzie dostępna, ale istnieje zamiar wdrożenia synchronizacji w tle. Chociaż nie określono ani sprecyzowaliśmy, jak to wygląda, w dalszym ciągu trwa dyskusja na temat włączenia cichej wiadomości z synchronizacją w tle.

Dlaczego do tego potrzebny jest protokół HTTPS? Jak mogę obejść ten problem na etapie tworzenia aplikacji?

Mechanizmy Service Worker wymagają bezpiecznych źródeł, aby mieć pewność, że skrypt skryptu service worker pochodzi z zamierzonego źródła i nie pochodzi z ataku typu „man in the middle”. Obecnie oznacza to używanie protokołu HTTPS w aktywnych witrynach, chociaż lokalny host będzie działać w trakcie programowania.

Jak wygląda obsługa przeglądarek?

Chrome obsługuje stabilną wersję przeglądarki Mozilla, a w przeglądarce Firefox Nightly pracujemy w trybie push. Więcej informacji znajdziesz w artykule o implementowaniu interfejsu API Push. Implementację powiadomień możesz śledzić tutaj.

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

W tej chwili nie jest to możliwe, ale planujemy wprowadzić obsługę listy obecnie widocznych powiadomień. Jeśli masz przypadek użycia, który pozwala ustawić datę ważności powiadomienia po jego utworzeniu, chętnie dowiemy się, co to jest. Dodaj więc swój komentarz, a my przekażemy go zespołowi Chrome.

Jeśli chcesz tylko zapobiec wysyłaniu powiadomienia push do użytkownika po upływie określonego czasu i nie interesuje Cię, jak długo powiadomienie pozostaje widoczne, możesz użyć parametru FCM (czas życia) (ttl) – więcej informacji znajdziesz tutaj.

Jakie są ograniczenia funkcji wiadomości push w Chrome?

Oto kilka ograniczeń opisanych w tym poście:

  • Zastosowanie w Chrome CCM jako usługi push wiąże się z kilkoma zastrzeżonymi wymaganiami. Wspólnie sprawdzamy, czy niektóre z nich uda się osiągnąć w przyszłości.
  • Po otrzymaniu wiadomości push należy wyświetlić powiadomienie.
  • W Chrome na komputerze występują błędy – jeśli nie jest uruchomiona, komunikaty push nie są odbierane. Różni się to od systemu ChromeOS i Androida, w których 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 być dostępny 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 otrzymania przez urządzenie użytkownika powiadomienia push?

Zawsze musisz pokazać powiadomienie po otrzymaniu wiadomości push. Jeśli chcesz wysłać powiadomienie, ale jest ono przydatne tylko przez określony czas, możesz użyć parametru „time_to_live” w CCM. Dzięki temu FCM nie wyśle wiadomości push po upływie określonego czasu.

Więcej informacji znajdziesz tutaj

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

W FCM znajduje się parametr „Zwiń_key”, przy użyciu którego można poinstruować FCM, aby zastąpić każdą oczekującą wiadomość z tym samym kluczem „Zwiń_key” nową wiadomością.

Więcej informacji znajdziesz tutaj