Aggiungere 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 iscriversi e annullare l'iscrizione di un utente per i 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 per Chrome o il tuo server web preferito
  • Un editor di testo
  • Conoscenza di base di HTML, CSS, JavaScript e Chrome DevTools
  • Il codice di esempio (vedi "Configurazione iniziale").

Scarica il codice di esempio

Sono disponibili due opzioni per ottenere il codice di esempio in 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, decomprimi l'origine per ottenere una cartella principale push-notifications-master.

Installare e verificare il server web

Anche se puoi utilizzare il tuo server web senza costi, questo codelab è progettato per funzionare bene con il server web per l'app Chrome. Se non hai ancora installato l'app, scaricala dal Chrome Web Store:

Installare Web Server per Chrome

Dopo aver installato l'app Web Server per Chrome, fai clic sulla scorciatoia App nella barra dei Preferiti:

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

Visualizzerai questa finestra di dialogo, che ti consente di configurare il tuo 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 svolgere i lavori in corso tramite l'URL mostrato nella sezione URL server web della finestra di dialogo.

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

Interrompi e riavvia il server facendo scorrere il pulsante di attivazione/disattivazione Web Server: AVVIATO verso sinistra e poi di nuovo verso destra.

Fai clic sull'URL del server web per visitare il tuo sito nel browser web. Dovresti vedere 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 abbia le ultime modifiche.

Per configurare questa funzionalità in Chrome:

  1. Vai alla scheda Push codelab.
  2. Apri DevTools: Ctrl-Maiusc-I su Windows e Linux, Cmd-Opzione-I su macOS.
  3. Seleziona il riquadro Applicazione, fai clic sulla scheda Service worker, quindi seleziona la casella di controllo Aggiorna al ricaricamento. Quando questa casella di controllo è abilitata, il service worker viene aggiornato forzatamente ogni volta che la pagina si ricarica.

Codice completato

Nella directory app, nota che hai un file vuoto denominato sw.js. Questo file sarà il tuo service worker. Per ora può rimanere vuoto. Aggiungerai il codice in seguito.

Per prima cosa, devi registrare questo file come service worker.

La pagina app/index.html carica scripts/main.js. Registri il service worker in questo file JavaScript.

Aggiungi il seguente codice 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 controlla se il browser supporta i service worker e i messaggi push. Se sono supportati, il codice registra il tuo file sw.js.

Prova

Verifica le modifiche aggiornando la scheda Push codelab nel browser.

Verifica l'eventuale presenza di Service Worker is registered message nella console di Chrome DevTools:

Recupera le chiavi server delle applicazioni

Per lavorare con questo codelab, devi generare le chiavi server delle applicazioni. Puoi eseguire questa operazione sul sito companion: web-push-codelab.glitch.me

Qui puoi generare una coppia di chiavi pubblica e privata.

push-codelab-04-companion.png

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

const applicationServerPublicKey = '<Your Public Key>';

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

Codice completato

Al momento, il pulsante Attiva dell'app web è disattivato e non può essere selezionato. Questo perché è buona norma disattivare il pulsante push per impostazione predefinita e attivarlo dopo aver appreso che i messaggi push sono supportati dal browser e che tu possa verificare se l'utente è attualmente iscritto o meno alla messaggistica.

Dovrai creare due funzioni in scripts/main.js:

  • initializeUI, per verificare se l'utente è attualmente iscritto
  • updateBtn, per attivare il pulsante e modificare il testo a seconda che l'utente sia iscritto o meno

Aggiungi una funzione initializeUI a main.js come segue:

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 tuo nuovo metodo utilizza il metodo swRegistration del passaggio precedente, riceve la proprietà pushManager e richiama getSubscription() in merito.

pushManager. getSubscription() restituisce una promessa che si risolve con l'abbonamento corrente, se presente. In caso contrario, restituisce null. In questo modo puoi verificare se l'utente è già iscritto, impostare il valore di isSubscribed e chiamare il numero 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 modifica il testo del pulsante a seconda che l'utente sia iscritto 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 Pushlab. Dovresti vedere che il pulsante Attiva messaggistica push è ora abilitato (puoi fare clic) e dovresti vedere User is NOT subscribed nella console.

Man mano che procedi con il resto di questo codelab, dovresti vedere che il testo del pulsante cambia ogni volta che ti iscrivi o annulli l'iscrizione.

Codice completato

Attualmente, il pulsante Attiva modalità Push non funziona 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 l'utente non possa fare clic la seconda volta, poiché l'iscrizione ai messaggi push può richiedere del tempo.

Chiamata a subscribeUser() se l'utente non è attualmente iscritto. In questo caso, 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();
  });
}

Analizziamo il comportamento di questo codice e in che modo l'utente può iscriversi ai messaggi push.

Innanzitutto, prendi la chiave pubblica del server di applicazioni, che è codificata in base all'URL sicuro di Base64, e la convertirai in UInt8Array, perché questo è l'input previsto della chiamata a subscribe(). La funzione urlB64ToUint8Array() si trova nella parte superiore di scripts/main.js.

Dopo aver convertito il valore, chiami il metodo subscribe() sulla pushManager di il tuo service worker, trasmettendo la chiave pubblica del server dell'applicazione e il valore userVisibleOnly: true.

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

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

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

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

Se questi passaggi hanno avuto esito positivo, la promessa di subscribe() verrà risolta con un PushSubscription. Se l'utente non concede l'autorizzazione o se si sono verificati problemi di iscrizione, la promessa verrà rifiutata con un errore. Questo ti fornirà la seguente catena di promesse nel tuo codelab:

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, ricevi un abbonamento e consideri l'utente come abbonato oppure rilevi un errore e lo registri alla console. In entrambi gli scenari, chiami updateBtn() per verificare che il pulsante sia riattivato e che abbia il testo appropriato.

In un'applicazione reale, la funzione updateSubscriptionOnServer() è il posto in cui invii i dati di 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 Codelab, aggiorna la pagina e fai clic sul pulsante. Dovresti vedere un prompt di autorizzazione come il seguente:

Se concedi l'autorizzazione, dovresti vedere User is subscribed registrato nella console. Il testo del pulsante diventerà Disattiva Messaggi push e potrai visualizzare l'abbonamento come dati JSON in fondo alla pagina.

Codice completato

Una cosa che non hai ancora gestito è ciò che accade se l'utente blocca la richiesta di autorizzazione. È necessaria un'attenzione unica perché se l'utente blocca l'autorizzazione, l'app web non sarà in grado di mostrare di nuovo la richiesta di autorizzazione e l'utente non potrà abbonarsi. Devi almeno disattivare il pulsante in modo che l'utente sappia che non può essere utilizzato.

Il posto più evidente per la gestione di questo scenario è la funzione updateBtn(). È sufficiente controllare il valore Notification.permission, ad esempio:

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ò essere abbonato e non puoi fare altro, pertanto la disattivazione definitiva del pulsante è l'approccio migliore.

Prova

Poiché hai già concesso l'autorizzazione alla tua app web dal passaggio precedente, devi fare clic sulla i in un cerchio nella barra degli URL e cambiare l'autorizzazione Notifiche in Utilizza il valore predefinito globale (Chiedi).

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

Con questa modifica, puoi iscriverti all'utente e occuparti dei possibili scenari di autorizzazione.

Codice completato

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

Quando attivi un messaggio push, il browser riceve il messaggio push, determina il motivo per cui è destinato il push, riattiva il service worker e invia un evento push. Devi ascoltare l'evento e mostrare una notifica come risultato.

Aggiungi il seguente codice al tuo 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 push eventi nel tuo service worker aggiungendo un listener di eventi:

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

A meno che tu non abbia mai giocato con i web worker, self è probabilmente una novità. In un file di service worker, self fa riferimento al service worker stesso.

Quando viene ricevuto un messaggio push, il chiamante dell'evento viene chiamato e crei una notifica chiamando showNotification() nella proprietà registration del service worker. showNotification() richiede un title; puoi anche assegnargli un oggetto options per impostare un messaggio, un'icona e un badge. Il badge viene utilizzato su Android solo al momento della scrittura.

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

L'ultimo aspetto da trattare nella gestione degli eventi di push è event.waitUntil(). Questo metodo garantisce l'abilitazione del browser per mantenere attivo il service worker fino alla risoluzione della promessa.

Per semplificare la comprensione del codice riportato sopra, puoi riscriverlo come segue:

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

Ora che hai superato l'evento push, testiamo un evento push.

Prova

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

Nella tua app web, iscriviti ai messaggi push e assicurati di visualizzare l'app User IS subscribed nella console. Nel riquadro Application (Applicazione) di DevTools, fai clic sul pulsante Push nella scheda Service worker.

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

Nota: se questo passaggio non funziona, prova ad annullare la registrazione del service worker con il link Unregister nel pannello dell'applicazione DevTools. Attendi che il service worker venga interrotto 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.

Inizia aggiungendo un listener 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, verrà chiamato il listener di eventi notificationclick.

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

event.notification.close();

Si apre una nuova finestra o scheda, caricando l'URL https://developers.google.com/web. Non esitare a modificarlo.

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

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

Prova

Prova ad attivare di nuovo un messaggio push in DevTools e fai clic sulla notifica. Vedrai la notifica chiusa e si aprirà una nuova scheda.

Hai notato che la tua app web è in grado di mostrare una notifica utilizzando DevTools e hai visto 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 nell'abbonamento.

Questo elemento non rientra nell'ambito di questo codelab, ma puoi usare il sito companion (web-push-codelab.glitch.me) per attivare un messaggio push effettivo. Incolla l'abbonamento nella parte inferiore della pagina:

Quindi, incolla questo valore nel sito companion nell'area di testo Abbonamento a cui inviare:

Nella sezione Testo da inviare, aggiungi la stringa che vuoi inviare insieme al messaggio push.

Fai clic sul pulsante Invia messaggio push.

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

In questo modo potresti avere la possibilità di testare la ricezione e la ricezione di dati e, di conseguenza, di manipolare le notifiche.

L'app complementare è solo un server dei nodi che utilizza la libreria web-push per inviare messaggi. Vale la pena esaminare l'organizzazione web-push-libs su GitHub per vedere quali librerie sono disponibili per inviare messaggi push per te. oltre a gestire numerosi dettagli per attivare i messaggi push.

Qui puoi vedere tutto il codice del sito companion.

Codice completato

Ciò che manca è la possibilità di annullare l'iscrizione di un utente in modalità push. Per farlo, devi chiamare unsubscribe() su un PushSubscription.

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

Noterai che stai per chiamare una nuova funzione unsubscribeUser(). In questa funzione, ricevi l'abbonamento corrente e lo 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.

Innanzitutto, ricevi l'abbonamento attuale chiamando il numero getSubscription():

swRegistration.pushManager.getSubscription()

Restituisce una promessa che si risolve con un valore PushSubscription se ne esiste uno; altrimenti restituisce null. Se hai un abbonamento, non riceverai un abbonamento a unsubscribe(), il che rende PushSubscription non valido.

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

Chiamare unsubscribe() restituisce una promessa, perché potrebbe essere necessario un po' di tempo. Tu restituisci questa promessa, per cui il prossimo then() nella catena attende che unsubscribe() venga completato. Aggiungi anche un gestore di ricezione dei lead qualora la chiamata a unsubscribe() generi un errore. In seguito, puoi aggiornare l'interfaccia utente.

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

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

  updateBtn();
})

Prova

Dovresti essere in grado di premere Attiva messaggio push o Disattiva Messaggi push nella tua app web e i log mostreranno l'utente che è stato iscritto e ha annullato l'iscrizione.

Congratulazioni, hai completato il codelab!

Questo codelab ti ha spiegato come iniziare a utilizzare le notifiche push nella tua app web. Se vuoi saperne di più su ciò che possono fare le notifiche web, consulta questi documenti.

Se vuoi implementare le notifiche push sul tuo sito, potrebbe essere utile aggiungere il supporto dei browser meno recenti o dei browser non conformi agli standard che utilizzano GCM. Scopri di più qui.

Ulteriori letture

Post del blog pertinenti