Aggiunta di notifiche push a un'app web

I messaggi push offrono un modo semplice ed efficace per coinvolgere nuovamente gli utenti. In questo codelab, imparerai ad aggiungere notifiche push alla tua app web.

Cosa imparerai a fare

  • Come iscrivere e annullare l'iscrizione di un utente ai messaggi push
  • Come gestire i messaggi push in arrivo
  • Come visualizzare una notifica
  • Come rispondere ai clic sulle notifiche

Che cosa ti serve

  • Chrome 52 o versioni successive
  • Web Server for Chrome o il tuo web server preferito
  • Un editor di testo
  • Conoscenza di base di HTML, CSS, JavaScript e Chrome DevTools
  • Il codice di esempio (vedi Configurazione).

Scaricare il codice di esempio

Hai due opzioni per ottenere il codice campione di questo codelab:

  • Clona il repository Git:
git clone https://github.com/GoogleChrome/push-notifications.git
  • Scarica il file ZIP:

Scarica il codice sorgente

Se scarichi l'origine come file ZIP, quando lo decomprimi ottieni una cartella principale push-notifications-master.

Installare e verificare il server web

Sebbene tu sia libero di utilizzare il tuo server web, questo codelab è progettato per funzionare bene con l'app Web Server for Chrome. Se non l'hai ancora installata, puoi scaricarla dal Chrome Web Store:

Installare Web Server for Chrome

Dopo aver installato l'app Web Server for Chrome, fai clic sul collegamento App nella barra dei preferiti:

Nella finestra App, fai clic sull'icona del server web:

Successivamente, vedrai questa finestra di dialogo, che ti consente di configurare il server web locale:

Fai clic sul pulsante Scegli cartella e seleziona la cartella app nella cartella push-notifications che hai scaricato. In questo modo, puoi pubblicare il tuo lavoro in corso tramite l'URL mostrato nella sezione URL server web della finestra di dialogo.

Nella sezione Opzioni, seleziona la casella accanto a Mostra automaticamente index.html, come mostrato di seguito:

Poi arresta e riavvia il server spostando il pulsante di attivazione/disattivazione Server web: AVVIATO a sinistra e poi di nuovo a destra.

Fai clic sull'URL del server web per visitare il tuo sito nel browser web. Dovresti visualizzare una pagina simile a questa, anche se la tua versione potrebbe mostrare 127.0.0.1:8887 come indirizzo:

00-push-codelab.png

Aggiorna sempre il service worker

Durante lo sviluppo, è utile assicurarsi che il service worker sia sempre aggiornato e contenga le ultime modifiche.

Per configurare questa funzionalità in Chrome:

  1. Vai alla scheda Push Codelab.
  2. Apri gli strumenti di sviluppo: Ctrl+Maiusc+I su Windows e Linux, Cmd+Opzione+I su macOS.
  3. Seleziona il riquadro Applicazione, fai clic sulla scheda Service worker e seleziona la casella di controllo Aggiorna al ricaricamento. Quando questa casella di controllo è selezionata, il service worker viene aggiornato forzatamente ogni volta che la pagina viene ricaricata.

Codice completato

Nella directory app, noterai che è presente un file vuoto denominato sw.js. Questo file sarà il service worker. Per ora, può rimanere vuoto. Aggiungerai il codice in un secondo momento.

Innanzitutto, devi registrare questo file come service worker.

Viene caricata la pagina app/index.htmlscripts/main.js. In questo file JavaScript registri il service worker.

Aggiungi il codice seguente a scripts/main.js:

if ('serviceWorker' in navigator && 'PushManager' in window) {
  console.log('Service Worker and Push are supported');

  navigator.serviceWorker.register('sw.js')
  .then(function(swReg) {
    console.log('Service Worker is registered', swReg);

    swRegistration = swReg;
  })
  .catch(function(error) {
    console.error('Service Worker Error', error);
  });
} else {
  console.warn('Push messaging is not supported');
  pushButton.textContent = 'Push Not Supported';
}

Questo codice verifica se i service worker e la messaggistica push sono supportati dal tuo browser. Se sono supportati, il codice registra il file sw.js.

Prova

Controlla le modifiche aggiornando la scheda Push Codelab nel browser.

Controlla la console di Chrome DevTools per un Service Worker is registered message, come segue:

Recuperare le chiavi del server delle applicazioni

Per utilizzare questo codelab, devi generare le chiavi del server delle applicazioni. Puoi farlo sul sito complementare: web-push-codelab.glitch.me

Qui puoi generare una coppia di chiavi pubblica e privata.

push-codelab-04-companion.png

Copia la chiave pubblica in scripts/main.js sostituendo il valore <Your Public Key>:

const applicationServerPublicKey = '<Your Public Key>';

Importante: non devi mai inserire la tua chiave privata nella tua app web.

Codice completato

Al momento, il pulsante Attiva dell'app web è disattivato e non è possibile farci clic sopra. Questo perché è buona norma disattivare il pulsante di notifica per impostazione predefinita e attivarlo dopo aver verificato che le notifiche push sono supportate dal browser e che puoi controllare se l'utente è attualmente iscritto o meno alle notifiche.

Dovrai creare due funzioni in scripts/main.js:

  • initializeUI, per verificare se l'utente ha attualmente un abbonamento
  • updateBtn, per attivare il pulsante e modificare il testo a seconda che l'utente sia abbonato o meno

Aggiungi una funzione initializeUI a main.js in questo modo:

function initializeUI() {
  // Set the initial subscription value
  swRegistration.pushManager.getSubscription()
  .then(function(subscription) {
    isSubscribed = !(subscription === null);

    if (isSubscribed) {
      console.log('User IS subscribed.');
    } else {
      console.log('User is NOT subscribed.');
    }

    updateBtn();
  });
}

Il nuovo metodo utilizza swRegistration del passaggio precedente, recupera la proprietà pushManager e chiama getSubscription().

pushManager. getSubscription() restituisce una promessa che viene risolta con l'abbonamento corrente, se presente. In caso contrario, restituisce null. In questo modo, puoi verificare se l'utente è già abbonato, impostare il valore di isSubscribed e poi chiamare updateBtn() per aggiornare il pulsante.

Aggiungi la funzione updateBtn() a main.js:

function updateBtn() {
  if (isSubscribed) {
    pushButton.textContent = 'Disable Push Messaging';
  } else {
    pushButton.textContent = 'Enable Push Messaging';
  }

  pushButton.disabled = false;
}

Questa funzione attiva il pulsante e ne modifica il testo a seconda che l'utente sia abbonato o meno.

L'ultima cosa da fare è chiamare initializeUI() quando il service worker è registrato in main.js:

navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
  console.log('Service Worker is registered', swReg);

  swRegistration = swReg;
  initializeUI();
})

Prova

Aggiorna la scheda Push Codelab. Dovresti vedere che il pulsante Attiva messaggistica push è ora attivo (puoi farci clic) e dovresti vedere User is NOT subscribed nella console.

Man mano che avanzi nel resto di questo codelab, dovresti vedere il testo del pulsante cambiare ogni volta che ti abboni o annulli l'abbonamento.

Codice completato

Al momento, il pulsante Attiva messaggistica push non fa molto. Risolviamo il problema.

Nella funzione initializeUI(), aggiungi un listener di clic per il pulsante:

function initializeUI() {
  pushButton.addEventListener('click', function() {
    pushButton.disabled = true;
    if (isSubscribed) {
      // TODO: Unsubscribe user
    } else {
      subscribeUser();
    }
  });

  // Set the initial subscription value
  swRegistration.pushManager.getSubscription()
  .then(function(subscription) {
    isSubscribed = !(subscription === null);

    updateSubscriptionOnServer(subscription);

    if (isSubscribed) {
      console.log('User IS subscribed.');
    } else {
      console.log('User is NOT subscribed.');
    }

    updateBtn();
  });
}

Quando l'utente fa clic sul pulsante, lo disattivi per assicurarti che non possa fare clic una seconda volta, poiché l'iscrizione alle notifiche push può richiedere un po' di tempo.

Poi chiami subscribeUser() se l'utente non è attualmente abbonato. Per farlo, devi incollare il seguente codice in scripts/main.js:

function subscribeUser() {
  const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
  swRegistration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: applicationServerKey
  })
  .then(function(subscription) {
    console.log('User is subscribed.');

    updateSubscriptionOnServer(subscription);

    isSubscribed = true;

    updateBtn();
  })
  .catch(function(error) {
    console.error('Failed to subscribe the user: ', error);
    updateBtn();
  });
}

Vediamo cosa fa questo codice e come iscrive l'utente alla messaggistica push.

Innanzitutto, prendi la chiave pubblica del server delle applicazioni, che è codificata in Base64 con protezione dell'URL, e convertila in un UInt8Array, perché questo è l'input previsto della chiamata subscribe(). La funzione urlB64ToUint8Array() si trova nella parte superiore di scripts/main.js.

Dopo aver convertito il valore, chiama il metodo subscribe() sul pushManager del service worker, passando la chiave pubblica del server delle applicazioni e il valore userVisibleOnly: true.

const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: applicationServerKey
})

Il parametro userVisibleOnly garantisce che verrà visualizzata una notifica ogni volta che viene inviato un messaggio push. Al momento, questo valore è obbligatorio e deve essere true.

La chiamata a subscribe() restituisce una promessa che verrà risolta dopo i seguenti passaggi:

  1. L'utente ha concesso l'autorizzazione per visualizzare le notifiche.
  2. Il browser ha inviato una richiesta di rete a un servizio push per ottenere i dati necessari per generare un PushSubscription.

La promessa subscribe() verrà risolta con un PushSubscription se questi passaggi sono andati a buon fine. Se l'utente non concede l'autorizzazione o se si verifica un problema con l'abbonamento, la promessa verrà rifiutata con un errore. Nel codelab avrai la seguente catena di promesse:

swRegistration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: applicationServerKey
})
.then(function(subscription) {
  console.log('User is subscribed.');

  updateSubscriptionOnServer(subscription);

  isSubscribed = true;

  updateBtn();

})
.catch(function(err) {
  console.log('Failed to subscribe the user: ', err);
  updateBtn();
});

In questo modo, ottieni un abbonamento e consideri l'utente come abbonato oppure rilevi un errore e lo registri nella console. In entrambi gli scenari, chiami updateBtn() per assicurarti che il pulsante sia riattivato e contenga il testo appropriato.

In un'applicazione reale, la funzione updateSubscriptionOnServer() è il punto in cui invieresti i dati dell'abbonamento a un backend, ma per il codelab visualizzi semplicemente l'abbonamento nella tua UI. Aggiungi la seguente funzione a scripts/main.js:

function updateSubscriptionOnServer(subscription) {
  // TODO: Send subscription to application server

  const subscriptionJson = document.querySelector('.js-subscription-json');
  const subscriptionDetails =
    document.querySelector('.js-subscription-details');

  if (subscription) {
    subscriptionJson.textContent = JSON.stringify(subscription);
    subscriptionDetails.classList.remove('is-invisible');
  } else {
    subscriptionDetails.classList.add('is-invisible');
  }
}

Prova

Vai alla scheda Push Codelab, aggiorna la pagina e fai clic sul pulsante. Dovresti visualizzare una richiesta di autorizzazione simile a questa:

Se concedi l'autorizzazione, dovresti visualizzare User is subscribed registrato nella console. Il testo del pulsante cambierà in Disattiva messaggistica push e potrai visualizzare l'abbonamento come dati JSON nella parte inferiore della pagina.

Codice completato

Una cosa che non hai ancora gestito è cosa succede se l'utente blocca la richiesta di autorizzazione. Questa operazione richiede un'attenzione particolare perché se l'utente blocca l'autorizzazione, la tua app web non potrà mostrare nuovamente la richiesta di autorizzazione e non potrà iscrivere l'utente. Devi almeno disattivare il pulsante, in modo che l'utente sappia che non può essere utilizzato.

Il luogo più ovvio per gestire questo scenario è la funzione updateBtn(). Tutto quello che devi fare è controllare il valore di Notification.permission, come segue:

function updateBtn() {
  if (Notification.permission === 'denied') {
    pushButton.textContent = 'Push Messaging Blocked';
    pushButton.disabled = true;
    updateSubscriptionOnServer(null);
    return;
  }

  if (isSubscribed) {
    pushButton.textContent = 'Disable Push Messaging';
  } else {
    pushButton.textContent = 'Enable Push Messaging';
  }

  pushButton.disabled = false;
}

Sai che se l'autorizzazione è denied, l'utente non può iscriversi e non puoi fare altro, quindi disattivare definitivamente il pulsante è l'approccio migliore.

Prova

Poiché hai già concesso l'autorizzazione per la tua app web nel passaggio precedente, devi fare clic sulla i in un cerchio nella barra degli URL e modificare l'autorizzazione Notifiche in Usa impostazione predefinita globale (Chiedi).

Dopo aver modificato questa impostazione, aggiorna la pagina, fai clic sul pulsante Attiva messaggistica push e seleziona Blocca nella finestra di dialogo delle autorizzazioni. Il pulsante verrà disattivato e verrà visualizzato il testo Messaggi push bloccati.

Con questa modifica, ora puoi iscrivere l'utente, dopo aver gestito i possibili scenari di autorizzazione.

Codice completato

Prima di scoprire come inviare un messaggio push dal backend, devi considerare cosa succede effettivamente quando un utente abbonato riceve un messaggio push.

Quando attivi un messaggio push, il browser lo riceve, individua il service worker a cui è destinato, lo riattiva e invia un evento push. Devi ascoltare questo evento e mostrare una notifica come risultato.

Aggiungi il codice seguente al file sw.js:

self.addEventListener('push', function(event) {
  console.log('[Service Worker] Push Received.');
  console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);

  const title = 'Push Codelab';
  const options = {
    body: 'Yay it works.',
    icon: 'images/icon.png',
    badge: 'images/badge.png'
  };

  event.waitUntil(self.registration.showNotification(title, options));
});

Analizziamo questo codice. Stai ascoltando gli eventi push nel service worker aggiungendo un listener di eventi:

self.addEventListener('push', ... );

A meno che tu non abbia già utilizzato i web worker, self è probabilmente una novità. In un file service worker, self fa riferimento al service worker stesso.)

Quando viene ricevuto un messaggio push, viene chiamato il listener di eventi e crei una notifica chiamando showNotification() sulla proprietà registration del service worker. showNotification() richiede un title; puoi anche fornire un oggetto options per impostare un corpo del messaggio, un'icona e un badge. (Al momento della stesura, il badge viene utilizzato solo su Android.)

const title = 'Push Codelab';
const options = {
  body: 'Yay it works.',
  icon: 'images/icon.png',
  badge: 'images/badge.png'
};
self.registration.showNotification(title, options);

L'ultima cosa da trattare nella gestione degli eventi push è event.waitUntil(). Questo metodo accetta una promessa per consentire al browser di mantenere attivo e in esecuzione il service worker finché la promessa passata non è stata risolta.

Per rendere il codice precedente un po' più facile da capire, puoi riscriverlo nel seguente modo:

const notificationPromise = self.registration.showNotification(title, options);
event.waitUntil(notificationPromise);

Ora che hai esaminato l'evento push, proviamone uno.

Prova

Con la gestione degli eventi push nel service worker, puoi attivare un evento push fittizio per testare cosa succede quando viene ricevuto un messaggio.

Nella tua app web, iscriviti alla messaggistica push e assicurati di visualizzare User IS subscribed nella console. Nel riquadro Applicazione di DevTools, nella scheda Service worker, fai clic sul pulsante Push:

Dopo aver fatto clic su Push, dovresti visualizzare una notifica come questa:

Nota: se questo passaggio non funziona, prova ad annullare la registrazione del service worker con il link Annulla registrazione nel riquadro Applicazione di DevTools, attendi l'interruzione del service worker e poi ricarica la pagina.

Codice completato

Se fai clic su una di queste notifiche, noterai che non succede nulla. Puoi gestire i clic sulle notifiche ascoltando gli eventi notificationclick nel service worker.

Per iniziare, aggiungi un ascoltatore notificationclick in sw.js:

self.addEventListener('notificationclick', function(event) {
  console.log('[Service Worker] Notification click received.');

  event.notification.close();

  event.waitUntil(
    clients.openWindow('https://developers.google.com/web')
  );
});

Quando l'utente fa clic sulla notifica, viene chiamato il listener di eventi notificationclick.

Il codice chiude innanzitutto la notifica su cui è stato fatto clic:

event.notification.close();

Viene quindi aperta una nuova finestra o scheda, che carica l'URL https://developers.google.com/web. Puoi modificarlo.

event.waitUntil(
    clients.openWindow('https://developers.google.com/web/')
  );

event.waitUntil() garantisce che il service worker non venga terminato dal browser prima che venga visualizzata la nuova finestra o scheda.

Prova

Prova di nuovo ad attivare un messaggio push in DevTools e fai clic sulla notifica. Ora vedrai la notifica chiudersi e una nuova scheda aprirsi.

Hai visto che la tua app web è in grado di mostrare una notifica utilizzando DevTools e hai esaminato come chiuderla con un clic. Il passaggio successivo consiste nell'inviare un messaggio push effettivo.

Normalmente, ciò richiederebbe l'invio di un abbonamento da una pagina web a un backend. Il backend attiverà quindi un messaggio push effettuando una chiamata API all'endpoint nella sottoscrizione.

Questo argomento non rientra nell'ambito di questo codelab, ma puoi utilizzare il sito complementare (web-push-codelab.glitch.me) per attivare un messaggio push effettivo. Incolla l'abbonamento in fondo alla pagina:

Quindi, incollalo nel sito complementare nell'area di testo Abbonamento a Invia a:

In Testo da inviare, aggiungi la stringa che vuoi inviare con il messaggio push.

Fai clic sul pulsante Invia messaggio push.

Dovresti quindi ricevere un messaggio push. Il testo che hai utilizzato verrà registrato nella console.

In questo modo avrai la possibilità di testare l'invio e la ricezione dei dati e di manipolare le notifiche di conseguenza.

L'app complementare è solo un server di nodi che utilizza la libreria web-push per inviare messaggi. Ti consigliamo di consultare l'organizzazione web-push-libs su GitHub per vedere quali librerie sono disponibili per l'invio di messaggi push. Questo gestisce molti dettagli per attivare i messaggi push.

Puoi visualizzare tutto il codice del sito complementare qui.

Codice completato

L'unica cosa che manca è la possibilità di annullare l'iscrizione di un utente alle notifiche push. Per farlo, devi chiamare il numero unsubscribe() su un PushSubscription.

Nel file scripts/main.js, modifica il listener di clic pushButton in initializeUI() nel seguente modo:

pushButton.addEventListener('click', function() {
  pushButton.disabled = true;
  if (isSubscribed) {
    unsubscribeUser();
  } else {
    subscribeUser();
  }
});

Tieni presente che ora chiamerai una nuova funzione unsubscribeUser(). In questa funzione, ottieni l'abbonamento attuale e chiami unsubscribe(). Aggiungi il seguente codice a scripts/main.js:

function unsubscribeUser() {
  swRegistration.pushManager.getSubscription()
  .then(function(subscription) {
    if (subscription) {
      return subscription.unsubscribe();
    }
  })
  .catch(function(error) {
    console.log('Error unsubscribing', error);
  })
  .then(function() {
    updateSubscriptionOnServer(null);

    console.log('User is unsubscribed.');
    isSubscribed = false;

    updateBtn();
  });
}

Analizziamo questa funzione.

Per prima cosa, ottieni l'abbonamento attuale chiamando il numero getSubscription():

swRegistration.pushManager.getSubscription()

Restituisce una promessa che viene risolta con un PushSubscription, se esiste; altrimenti, restituisce null. Se esiste un abbonamento, chiami unsubscribe(), che invalida PushSubscription.

swRegistration.pushManager.getSubscription()
.then(function(subscription) {
  if (subscription) {
    // TODO: Tell application server to delete subscription
    return subscription.unsubscribe();
  }
})
.catch(function(error) {
  console.log('Error unsubscribing', error);
})

La chiamata a unsubscribe() restituisce una promessa, poiché il completamento può richiedere un po' di tempo. Restituisci la promessa in modo che il successivo then() nella catena attenda il completamento di unsubscribe(). Aggiungi anche un gestore catch nel caso in cui la chiamata a unsubscribe() generi un errore. Dopodiché, potrai aggiornare la UI.

.then(function() {
  updateSubscriptionOnServer(null);

  console.log('User is unsubscribed.');
  isSubscribed = false;

  updateBtn();
})

Prova

Dovresti essere in grado di premere Attiva messaggistica push o Disattiva messaggistica push nella tua app web e i log mostreranno l'utente che si iscrive e si disiscrive.

Congratulazioni per aver completato questo codelab.

Questo codelab ti ha mostrato come iniziare ad aggiungere notifiche push alla tua app web. Se vuoi scoprire di più su cosa possono fare le notifiche web, consulta questi documenti.

Se vuoi implementare le notifiche push sul tuo sito, ti potrebbe interessare aggiungere il supporto per browser precedenti o non conformi agli standard che utilizzano GCM. Scopri di più qui.

Further reading

Post del blog pertinenti