Notifiche push sul Web aperto

Matt Gaunt

Se chiedi a un gruppo di sviluppatori quali funzionalità per dispositivi mobili mancano sul web, le notifiche push sono sempre in cima all'elenco.

Le notifiche push consentono agli utenti di attivare gli aggiornamenti tempestivi dai siti che amano e permettono di coinvolgerli nuovamente con contenuti coinvolgenti e personalizzati.

A partire dalla versione 42 di Chrome, l'API Push e l'API Notification sono disponibili per gli sviluppatori.

L'API Push in Chrome si basa su alcune tecnologie diverse, tra cui manifest delle app web e Service Workers. In questo post esamineremo ciascuna di queste tecnologie, ma solo il minimo indispensabile per attivare i messaggi push. Per comprendere meglio alcune altre caratteristiche dei file manifest e le funzionalità offline dei Service worker, fai riferimento ai link riportati sopra.

Vedremo anche cosa verrà aggiunto all'API nelle versioni future di Chrome e alla fine avremo una domanda frequente.

Implementazione della messaggistica push per Chrome

Questa sezione descrive ogni passaggio che devi completare per supportare i messaggi push nella tua applicazione web.

Registra un service worker

Un service worker per implementare i messaggi push per il web dipende dalla base. Il motivo è che, quando viene ricevuto un messaggio push, il browser può avviare un service worker, che viene eseguito in background senza che una pagina sia aperta, e inviare un evento in modo da poter decidere come gestire il messaggio push.

Di seguito è riportato un esempio di come registrare un service worker nella tua applicazione web. Al termine della registrazione, chiamiamo initialiseState(), di cui parleremo a breve.

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

Il gestore dei clic sul pulsante sottoscrive o annulla l'iscrizione dell'utente ai messaggi push. isPushEnabled è una variabile globale che monitora semplicemente la sottoscrizione dei messaggi push in quel momento. e verranno utilizzati come riferimento negli snippet di codice.

Controlliamo quindi che i service worker siano supportati prima di registrare il file service-worker.js, che ha la logica per la gestione di un messaggio push. In questo caso diciamo semplicemente al browser che il file JavaScript è il service worker per il nostro sito.

Configurazione dello stato iniziale

Esempio di UX per i messaggi push attivati e disattivati in Chrome.

Una volta registrato il service worker, dobbiamo impostare lo stato della nostra UI.

Gli utenti si aspettano che una semplice interfaccia utente attivi o disattivi i messaggi push per il sito e si aspetti che siano sempre aggiornati su tutte le modifiche che vengono apportate. In altre parole, se attivano i messaggi push per il tuo sito, abbandonano e tornano una settimana dopo, l'interfaccia utente dovrebbe evidenziare che i messaggi push sono già attivati.

Puoi trovare alcune linee guida per l'esperienza utente in questo documento. In questo articolo ci concentreremo sugli aspetti tecnici.

A questo punto potresti pensare che ci siano solo due stati da gestire: attivato o disabilitato. Tuttavia, esistono altri stati relativi alle notifiche che devi tenere in considerazione.

Diagramma che evidenzia le diverse considerazioni e lo stato del push in Chrome

È necessario controllare una serie di API prima di abilitare il pulsante. Se tutto è supportato, possiamo abilitare l'interfaccia utente e impostare lo stato iniziale in modo da indicare se i messaggi push sono iscritti o meno.

Poiché la maggior parte di questi controlli comporta la disattivazione della UI, devi impostare lo stato iniziale su disabilitato. In questo modo si evita inoltre qualsiasi confusione in caso di problemi con JavaScript della pagina, ad esempio se il file JS non può essere scaricato o l'utente ha disattivato JavaScript.

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

Con questo stato iniziale, possiamo eseguire i controlli descritti sopra nel metodo initialiseState(), ovvero dopo la registrazione del nostro 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);
        });
    });
}

Ecco una breve panoramica di questi passaggi:

  • Verifichiamo che showNotification sia disponibile nel prototipo ServiceWorkerRegistration. Senza di essi non saremo in grado di mostrare una notifica dal nostro service worker quando riceve un messaggio push.
  • Controlliamo qual è l'attuale Notification.permission per assicurarci che non sia "denied". Un'autorizzazione negata significa che non puoi mostrare le notifiche fino a quando l'utente non modifica manualmente l'autorizzazione nel browser.
  • Per verificare se i messaggi push sono supportati, controlliamo che PushManager sia disponibile nell'oggetto finestra.
  • Infine, abbiamo usato pushManager.getSubscription() per verificare se avevamo già un abbonamento o meno. Se lo facciamo, inviamo i dettagli dell'abbonamento al nostro server per assicurarci di avere le informazioni corrette e impostiamo la nostra UI in modo che indichi che i messaggi push sono già attivati o meno. Vedremo quali dettagli sono presenti nell'oggetto abbonamento più avanti in questo articolo.

Attendiamo che navigator.serviceWorker.ready venga risolto per verificare la presenza di un abbonamento e abilitare il pulsante push perché è solo dopo che il service worker è attivo che puoi effettivamente sottoscrivere i messaggi push.

Il passaggio successivo consiste nel gestire quando l'utente vuole attivare i messaggi push, ma prima di farlo, dobbiamo configurare un progetto di Google Developer Console e aggiungere alcuni parametri al file manifest per utilizzare Firebase Cloud Messaging (FCM), precedentemente noto come Google Cloud Messaging (GCM).

Crea un progetto nella Console per gli sviluppatori di Firebase

Chrome utilizza FCM per gestire l'invio e il recapito dei messaggi push; tuttavia, per utilizzare l'API FCM, devi configurare un progetto nella Console per gli sviluppatori di Firebase.

I passaggi che seguono sono specifici per Chrome, Opera per Android e il browser Samsung su cui utilizzano FCM. Approfondiremo questo aspetto in altri browser più avanti nell'articolo.

Crea un nuovo progetto di sviluppatori Firebase

Per iniziare, devi creare un nuovo progetto su https://console.firebase.google.com/ facendo clic su "Crea nuovo progetto".

Screenshot del nuovo progetto Firebase

Aggiungi un nome al progetto, crea il progetto e verrà visualizzata la dashboard del progetto:

Home page del progetto Firebase

Da questa dashboard, fai clic sull'icona a forma di ingranaggio accanto al nome del progetto nell'angolo in alto a sinistra e fai clic su "Impostazioni progetto".

Menu Impostazioni progetto Firebase

Nella pagina delle impostazioni, fai clic sulla scheda "Cloud Messaging".

Menu di Cloud Messaging per il progetto Firebase

Questa pagina contiene la chiave API per i messaggi push, che utilizzeremo più avanti, e l'ID mittente che dobbiamo inserire nel manifest dell'app web nella sezione successiva.

Aggiungi un manifest dell'app web

Affinché la sottoscrizione push vada a buon fine, dobbiamo aggiungere un file manifest con un campo gcm_sender_id. Questo parametro è richiesto solo dai browser Chrome, Opera per Android e Samsung per poter utilizzare FCM / GCM.

gcm_sender_id viene utilizzato da questi browser quando sottoscrive un dispositivo dell'utente con FCM. Ciò significa che FCM può identificare il dispositivo dell'utente e assicurarsi che l'ID mittente corrisponda alla chiave API corrispondente e che l'utente abbia consentito al tuo server di inviare messaggi push.

Di seguito è riportato un semplicissimo file manifest:

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

Devi impostare il valore gcm_sender_id sull'ID mittente del progetto Firebase.

Dopo aver salvato il file manifest nel progetto (manifest.json è un nome appropriato), fai riferimento al file HTML con il seguente tag nell'intestazione della pagina.

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

Se non aggiungi un manifest web con questi parametri, riceverai un'eccezione quando tenti di iscrivere l'utente al push dei messaggi, con l'errore "Registration failed - no sender id provided" o "Registration failed - permission denied".

Iscriviti alla messaggistica push

Ora che hai configurato il file manifest, puoi tornare al codice JavaScript del tuo sito.

Per iscriverti, devi chiamare il metodo subscribe() sull'oggetto PushManager, a cui accedi tramite ServiceWorkerRegistration.

In questo modo, all'utente verrà chiesto di concedere l'autorizzazione di origine per inviare notifiche push. Senza questa autorizzazione, non potrai iscriverti correttamente.

Se la promise restituita dal metodo subscribe() si risolve, ti verrà assegnato un oggetto PushSubscription che conterrà un endpoint.

L'endpoint dovrebbe essere salvato sul tuo server per ogni utente, poiché ti servirà per inviare messaggi push in un secondo momento.

Il seguente codice consente di iscrivere l'utente ai messaggi 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';
        }
        });
    });
}

A questo punto la tua applicazione web è pronta a ricevere un messaggio push, anche se non succederà nulla finché non aggiungiamo un listener di eventi push al nostro file del service worker.

Listener di eventi push del service worker

Alla ricezione di un messaggio push (parleremo di come inviare un messaggio push nella prossima sezione), viene inviato un evento push nel service worker, a quel punto devi visualizzare una notifica.

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

Questo codice registra un listener di eventi push e visualizza una notifica con un titolo, un corpo del testo, un'icona e un tag di notifica predefiniti. Una sottigliezza da evidenziare in questo esempio è il metodo event.waitUntil(). Questo metodo accetta una promessa ed estende la durata di un gestore di eventi (o può essere considerato come il mantenimento attivo del worker di servizio), fino a quando la promessa viene stabilita. In questo caso, la promessa passata a event.waitUntil è la promessa restituita da showNotification().

Il tag di notifica funge da identificatore di notifiche univoche. Se abbiamo inviato due messaggi push allo stesso endpoint, con un breve ritardo tra l'uno e l'altro, e mostriamo le notifiche con lo stesso tag, il browser mostrerà la prima notifica e la sostituirà con la seconda alla ricezione del messaggio push.

Se vuoi mostrare più notifiche contemporaneamente, utilizza un tag diverso o nessun tag. Analizzeremo un esempio più completo di come mostrare una notifica più avanti in questo post. Per ora, per semplicità, vediamo se l'invio di un messaggio push mostra questa notifica.

Invio di un messaggio push

Ci siamo iscritti ai messaggi push e il nostro service worker è pronto a mostrare una notifica, quindi è il momento di inviare un messaggio push tramite FCM.

Questo vale solo per i browser che utilizzano FCM.

Quando invii la variabile PushSubscription.endpoint al tuo server, l'endpoint per FCM è speciale. Alla fine dell'URL è presente un parametro registration_id.

Un endpoint di esempio potrebbe essere:

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

L'URL di FCM è:

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

registration_id sarebbe:

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

Questa opzione è specifica per i browser che utilizzano FCM. In un browser normale, è sufficiente un endpoint che viene chiamato in modo standard e funziona indipendentemente dall'URL.

Ciò significa che sul server dovrai verificare se l'endpoint è per FCM e, in caso affermativo, estrarre il registry_id. Per farlo in Python, potresti fare:

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

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

Una volta ottenuto l'ID di registrazione, puoi effettuare una chiamata all'API FCM. Puoi trovare la documentazione di riferimento sull'API FCM qui.

Gli aspetti principali da ricordare per le chiamate a FCM sono i seguenti:

  • È necessario impostare un'intestazione Authorization con valore key=&lt;YOUR_API_KEY&gt; quando chiami l'API, dove &lt;YOUR_API_KEY&gt; è la chiave API del progetto Firebase.
    • La chiave API viene utilizzata da FCM per trovare l'ID mittente appropriato, per assicurarsi che l'utente abbia concesso l'autorizzazione per il progetto e infine per assicurarsi che l'indirizzo IP del server sia incluso nella lista consentita per il progetto.
  • Un'intestazione Content-Type appropriata di application/json o application/x-www-form-urlencoded;charset=UTF-8, a seconda che vengano inviati i dati come JSON o come dati del modulo.
  • Un array di registration_ids, questi sono gli ID di registrazione che estrarrai dagli endpoint dagli utenti.

Consulta la documentazione su come inviare messaggi push dal tuo server, ma per un rapido controllo del service worker puoi utilizzare cURL per inviare un messaggio push al tuo browser.

Sostituisci &lt;YOUR_API_KEY&gt; e &lt;YOUR_REGISTRATION_ID&gt; in questo comando cURL con il tuo ed eseguilo da un terminale.

Dovresti ricevere una notifica gloriosa:

    curl --header "Authorization: key=<YOUR_API_KEY>" --header
    "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d
    "{\"registration_ids\":[\"<YOUR_REGISTRATION_ID>\"]}"
Esempio di un messaggio push di Chrome per Android.

Quando sviluppi la logica di backend, ricorda che l'intestazione e il formato di autorizzazione del corpo POST sono specifici dell'endpoint FCM, quindi rileva quando l'endpoint è per FCM, aggiungi l'intestazione e formatta il corpo POST in modo condizionale. Per altri browser (e, speriamo, per Chrome in futuro) dovrai implementare il Web Push Protocol.

Uno svantaggio dell'attuale implementazione dell'API Push in Chrome è che non è possibile inviare dati con un messaggio push. No, niente. Il motivo è che, in un'implementazione futura, i dati del payload dovranno essere criptati sul server prima di essere inviati a un endpoint di messaggistica push. In questo modo, l'endpoint, qualunque sia il provider push, non sarà in grado di visualizzare facilmente i contenuti del messaggio push. Ciò protegge anche da altre vulnerabilità, come la scarsa convalida dei certificati HTTPS e gli attacchi man in the middle tra il server e il provider push. Tuttavia, questa crittografia non è ancora supportata, quindi nel frattempo dovrai eseguire un recupero per ottenere le informazioni necessarie per compilare una notifica.

Esempio di evento push più completo

La notifica che abbiamo visto finora è molto basilare e, per quanto riguarda gli esempi, non riesce a coprire un caso d'uso reale.

In realtà, la maggior parte delle persone vorrà ricevere alcune informazioni dal proprio server prima di visualizzare la notifica. Potrebbero essere dati che consentono di completare il titolo e il messaggio della notifica con dati specifici oppure di andare oltre e memorizzare nella cache alcune pagine o dati in modo che, quando l'utente fa clic sulla notifica, tutto sia immediatamente disponibile all'apertura del browser, anche se la rete non è disponibile in quel momento.

Nel codice seguente, recuperiamo alcuni dati da un'API, convertiamo la risposta in un oggetto e li utilizziamo per compilare la notifica.

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

Vale la pena sottolineare ancora una volta che event.waitUntil() mantiene una promessa che genera la promessa restituita da showNotification(), il che significa che il nostro listener di eventi non uscirà finché la chiamata fetch() asincrona non viene completata e viene mostrata la notifica.

Noterai che mostriamo una notifica anche se si verifica un errore. Questo perché, in caso contrario, Chrome mostrerà la propria notifica generica.

Apertura di un URL quando l'utente fa clic su una notifica

Quando l'utente fa clic su una notifica, nel service worker viene inviato un evento notificationclick. All'interno del gestore, puoi intraprendere le azioni appropriate, come impostare lo stato attivo su una scheda o aprire una finestra con un determinato 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('/');
        }
    })
    );
});

Questo esempio apre il browser alla directory principale dell'origine del sito, mettendo in evidenza una scheda con la stessa origine esistente, se esistente, e aprendone una nuova.

Puoi trovare un post dedicato ad alcune cose che puoi fare con l'API Notification qui.

Annullare l'iscrizione al dispositivo di un utente

Hai sottoscritto l'abbonamento sul dispositivo di un utente e l'utente sta ricevendo messaggi push. Ma come puoi fare per annullare l'iscrizione?

Per annullare l'iscrizione al dispositivo di un utente, devi chiamare il metodo unsubscribe() sull'oggetto PushSubscription e rimuovere l'endpoint dai tuoi server (così da non inviare messaggi push che, come sapete, non verranno ricevuti). Il codice seguente si traduce esattamente in questo:

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

Mantenere aggiornato l'abbonamento

Gli abbonamenti potrebbero non essere sincronizzati tra FCM e il tuo server. Assicurati che il tuo server analizzi il corpo della risposta del POST di invio dell'API FCM, cercando i risultati error:NotRegistered e canonical_id, come spiegato nella documentazione di FCM.

Inoltre, gli abbonamenti potrebbero non essere sincronizzati tra il service worker e il server. Ad esempio, una volta completata l'iscrizione o l'annullamento dell'iscrizione, una connessione di rete instabile potrebbe impedirti di aggiornare il server oppure un utente potrebbe revocare l'autorizzazione alle notifiche, il che attiva l'annullamento automatico dell'iscrizione. Gestisci tali casi controllando periodicamente il risultato di serviceWorkerRegistration.pushManager.getSubscription() (ad esempio al caricamento della pagina) e sincronizzandolo con il server. Puoi anche abbonarti di nuovo automaticamente se non hai più un abbonamento e Notification.permission == 'granted'.

In sendSubscriptionToServer() dovrai considerare come gestire le richieste di rete non riuscite durante l'aggiornamento di endpoint. Una soluzione è monitorare lo stato di endpoint in un cookie per determinare se il server ha bisogno dei dettagli più recenti o meno.

Tutti i passaggi precedenti portano a un'implementazione completa dei messaggi push sul web in Chrome 46. Esistono ancora funzionalità specifiche che semplificheranno le cose (come un'API standard per l'attivazione dei messaggi push), ma questa release consente di iniziare a creare messaggi push nelle tue app web oggi stesso.

Come eseguire il debug della tua app web

Durante l'implementazione dei messaggi push, i bug risiedono in due posizioni: la tua pagina o il service worker.

È possibile eseguire il debug dei bug nella pagina utilizzando DevTools. Per eseguire il debug dei problemi dei service worker, hai due opzioni:

  1. Vai a chrome://inspect > Service worker. Questa visualizzazione non fornisce molte informazioni oltre ai service worker attualmente in esecuzione.
  2. Vai a chrome://serviceworker-internals. Da qui puoi visualizzare lo stato dei Service worker e visualizzare eventuali errori. Questa pagina è temporanea finché DevTools non viene fornito un insieme di funzionalità simile.

Uno dei migliori suggerimenti che posso dare a chiunque non abbia familiarità con i service worker è utilizzare la casella di controllo "Apri la finestra DevTools e metti in pausa l'esecuzione di JavaScript all'avvio del service worker per il debug". Questa casella di controllo aggiungerà un punto di interruzione all'inizio del service worker e metterà in pausa l'esecuzione. In questo modo potrai riprendere o eseguire lo script del service worker e controllare se si sono verificati problemi.

Screenshot che mostra dove si trova la casella di controllo per mettere in pausa l&#39;esecuzione per gli elementi serviceworker-internal.

Se sembra esserci un problema tra FCM e l'evento push del tuo service worker, non puoi fare molto per eseguire il debug del problema poiché non puoi sapere se Chrome ha ricevuto qualcosa. La cosa fondamentale da assicurare è che la risposta da FCM abbia esito positivo quando il server effettua una chiamata API. Sarà simile a questo:

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

Osserva la risposta "success": 1. Se al contrario viene visualizzato un errore, significa che qualcosa non va con l'ID di registrazione FCM e che il messaggio push non viene inviato a Chrome.

Debug dei Service worker su Chrome per Android

Al momento il debug dei service worker su Chrome per Android non è ovvio. Devi accedere a chrome://inspect, trovare il tuo dispositivo e cercare una voce dell'elenco con il nome "pid worker:...." che contiene l'URL del service worker.

Screenshot che mostra dove si trovano i Service worker in Chrome Inspector

UX per le notifiche push

Il team di Chrome ha messo a punto un documento sulle best practice per l'esperienza utente delle notifiche push, nonché un documento che illustra alcuni dei casi limite relativi all'utilizzo delle notifiche push.

Il futuro della messaggistica push su Chrome e sul web aperto

Questa sezione descrive un po' in dettaglio alcune parti specifiche di Chrome di questa implementazione che dovresti conoscere e le differenze rispetto ad altre implementazioni del browser.

Web Push Protocol ed endpoint

Il bello dello standard dell'API Push è che dovresti essere in grado di trasferire l'endpoint al tuo server e inviare messaggi push implementando il Web Push Protocol.

Il Web Push Protocol è un nuovo standard che i provider di servizi push possono implementare. Questo consente agli sviluppatori di non doversi preoccupare di chi sia il provider push. L'idea è che in questo modo non sarà necessario registrarsi per chiavi API e inviare dati con formattazione speciale, come si fa con FCM.

Chrome è stato il primo browser a implementare l'API Push e FCM non supporta il protocollo Web Push, motivo per cui Chrome richiede gcm_sender_id e è necessario utilizzare l'API RESTful per FCM.

L'obiettivo finale di Chrome è passare all'utilizzo del protocollo Web Push con Chrome e FCM.

Fino ad allora, devi rilevare l'endpoint "https://fcm.googleapis.com/fcm/send" e gestirlo separatamente dagli altri endpoint, ad esempio formattando i dati del payload in modo specifico e aggiungendo la chiave di autorizzazione.

Come implementare il protocollo web push?

Firefox Nightly è attualmente in fase di push e sarà probabilmente il primo browser a implementare il Web Push Protocol.

Domande frequenti

Dove sono le specifiche?

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

Posso evitare la duplicazione di notifiche se la mia presenza sul web ha più origini o se ho sia una presenza web che una presenza nativa?

Al momento non esiste una soluzione a questo problema, ma puoi seguire i progressi su Chromium.

Lo scenario ideale sarebbe avere un qualche tipo di ID per il dispositivo di un utente e poi, sul lato server, far corrispondere gli ID abbonamento dell'app nativa e dell'app web e decidere a quale inviare un messaggio push. Puoi farlo tramite le dimensioni dello schermo, il modello del dispositivo, condividendo una chiave generata tra l'app web e l'app nativa, ma ogni approccio presenta vantaggi e svantaggi.

Perché ho bisogno di un gcm_sender_id?

Questo passaggio è necessario per consentire a Chrome, Opera per Android e al browser Samsung di utilizzare l'API Firebase Cloud Messaging (FCM). L'obiettivo è utilizzare il protocollo Web Push Protocol una volta finalizzato lo standard e FCM può supportarlo.

Perché non utilizzare Web Socket o Eventi inviati dal server (EventSource)?

Il vantaggio dell'utilizzo dei messaggi push è che, anche se la pagina è chiusa, il service worker verrà svegliato e potrà mostrare una notifica. La connessione di Web Socket e EventSource viene chiusa alla chiusura della pagina o del browser.

Che cosa succede se non mi serve la pubblicazione degli eventi in background?

Se non hai bisogno della pubblicazione in background, i Web Socket sono un'ottima opzione.

Quando posso utilizzare le notifiche push senza mostrare notifiche (ad esempio push in background silenziosa)?

Non esiste una tempistica per la disponibilità di questa funzionalità, ma esiste un intento di implementare la sincronizzazione in background e, sebbene questa funzionalità non sia decisa o specifica, si discute dell'attivazione del push silenzioso con sincronizzazione in background.

Perché è necessario il protocollo HTTPS? Come posso risolvere questo problema durante lo sviluppo?

I Service worker richiedono origini sicure per garantire che lo script del service worker provenga dall'origine prevista e che non sia derivata da un attacco man in the middle. Attualmente, ciò significa utilizzare HTTPS sui siti attivi, anche se localhost funzionerà durante lo sviluppo.

Come si presenta il supporto dei browser?

Chrome supporta la versione stabile, mentre è in corso la fase di elaborazione di Mozilla in Firefox Nightly. Per saperne di più, consulta il bug relativo all'implementazione dell'API Push. Puoi monitorare l'implementazione delle notifiche qui.

Posso rimuovere una notifica dopo un determinato periodo di tempo?

Al momento non è possibile, ma prevediamo di aggiungere l'assistenza per ricevere un elenco delle notifiche attualmente visibili. Se hai un caso d'uso per impostare una scadenza per le notifiche dopo che è stata visualizzata, ci piacerebbe sapere di cosa si tratta, quindi aggiungi un commento e provvederemo a ritrasmetterlo al team di Chrome.

Se devi interrompere l'invio di una notifica push all'utente solo dopo un determinato periodo di tempo e non ti interessa per quanto tempo la notifica rimane visibile, puoi utilizzare il parametro Time to Live (ttl) di FCM, scopri di più qui.

Quali sono le limitazioni dei messaggi push in Chrome?

Questo post presenta alcune limitazioni:

  • L'utilizzo di CCM da parte di Chrome come servizio push crea una serie di requisiti proprietari. Stiamo lavorando per vedere se alcuni di questi problemi possono essere migliorati in futuro.
  • Devi mostrare una notifica quando ricevi un messaggio push.
  • Chrome su computer c'è l'avvertenza che, se Chrome non è in esecuzione, i messaggi push non verranno ricevuti. A differenza di ChromeOS e Android, i messaggi push verranno sempre ricevuti.

Non dovremmo usare l'APIPermissions?

L'API Permission è implementata in Chrome, ma non sarà necessariamente disponibile in tutti i browser. Puoi scoprire di più qui.

Perché Chrome non apre la scheda precedente quando faccio clic su una notifica?

Questo problema riguarda solo le pagine che non sono attualmente controllate da un service worker. Puoi scoprire ulteriori informazioni qui.

Cosa succede se una notifica non è aggiornata nel momento in cui il dispositivo dell'utente ha ricevuto il push?

Devi sempre mostrare una notifica quando ricevi un messaggio push. Se vuoi inviare una notifica ma è utile solo per un determinato periodo di tempo, puoi utilizzare il parametro "time_to_live" su CCM in modo che FCM non invii il messaggio push se supera la data di scadenza.

Puoi trovare ulteriori dettagli qui.

Che cosa succede se invio 10 messaggi push ma voglio che il dispositivo ne riceva solo uno?

FCM dispone di un parametro "Comprimi_key" che può essere utilizzato per indicare a FCM di sostituire qualsiasi messaggio in attesa con la stessa "compressione_chiave" con il nuovo messaggio.

Puoi trovare ulteriori dettagli qui.