Innanzitutto, mi scuso per il titolo orribile, ma non potevo non farlo.
In Chrome 44 sono stati aggiunti Notfication.data e ServiceWorkerRegistration.getNotifications() e consentono di aprire / semplificare alcuni casi d'uso comuni quando si gestiscono le notifiche con messaggi push.
Dati di notifica
Notification.data ti consente di associare un oggetto JavaScript a una Notification.
In sostanza, quando ricevi un messaggio push, puoi creare una notifica con alcuni dati, quindi nell'evento notificationclick puoi recuperare la notifica su cui è stato fatto clic e i relativi dati.
Ad esempio, puoi creare un oggetto dati e aggiungerlo alle opzioni di notifica come segue:
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';
var data = {
doge: {
wow: 'such amaze notification data'
}
};
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag,
data: data
})
);
});
Significa che possiamo ottenere le informazioni nell'evento notificationclick:
self.addEventListener('notificationclick', function(event) {
var doge = event.notification.data.doge;
console.log(doge.wow);
});
In precedenza, dovevi nascondere i dati in IndexDB o inserire qualcosa alla fine dell'URL icona.
ServiceWorkerRegistration.getNotifications()
Una richiesta comune degli sviluppatori che si occupano di notifiche push è avere un controllo migliore sulle notifiche visualizzate.
Un caso d'uso di esempio potrebbe essere un'applicazione di chat in cui un utente invia più messaggi e il destinatario visualizza più notifiche. Idealmente, l'app web potrebbe rilevare la presenza di diverse notifiche che non sono state visualizzate e comprimerle in un'unica notifica.
Senza getNotifiche(), la soluzione migliore è sostituire la notifica precedente con l'ultimo messaggio. Con getNotifications(), puoi "chiudere" le notifiche se ne è già visualizzata una, migliorando così l'esperienza utente.
Il codice per farlo è relativamente semplice. All'interno dell'evento push, chiama ServiceWorkerRegistration.get Notifications() per ricevere un array di notifiche correnti e da lì decidere il comportamento giusto, ad esempio comprimere tutte le notifiche o utilizzare il tag Notification.tag.
function showNotification(title, body, icon, data) {
var notificationOptions = {
body: body,
icon: icon ? icon : 'images/touch/chrome-touch-icon-192x192.png',
tag: 'simple-push-demo-notification',
data: data
};
self.registration.showNotification(title, notificationOptions);
return;
}
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
// Since this is no payload data with the first version
// of Push notifications, here we'll grab some data from
// an API and use it to populate a notification
event.waitUntil(
fetch(API_ENDPOINT).then(function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
// Throw an error so the promise is rejected and catch() is executed
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
var title = 'You have a new message';
var message = data.message;
var icon = 'images/notification-icon.png';
var notificationTag = 'chat-message';
var notificationFilter = {
tag: notificationTag
};
return self.registration.getNotifications(notificationFilter)
.then(function(notifications) {
if (notifications && notifications.length > 0) {
// Start with one to account for the new notification
// we are adding
var notificationCount = 1;
for (var i = 0; i < notifications.length; i++) {
var existingNotification = notifications[i];
if (existingNotification.data &&
existingNotification.data.notificationCount) {
notificationCount +=
existingNotification.data.notificationCount;
} else {
notificationCount++;
}
existingNotification.close();
}
message = 'You have ' + notificationCount +
' weather updates.';
notificationData.notificationCount = notificationCount;
}
return showNotification(title, message, icon, notificationData);
});
});
}).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';
return showNotification(title, message);
})
);
});
self.addEventListener('notificationclick', function(event) {
console.log('On notification click: ', event);
if (Notification.prototype.hasOwnProperty('data')) {
console.log('Using Data');
var url = event.notification.data.url;
event.waitUntil(clients.openWindow(url));
} else {
event.waitUntil(getIdb().get(KEY_VALUE_STORE_NAME,
event.notification.tag).then(function(url) {
// At the moment you cannot open third party URL's, a simple trick
// is to redirect to the desired URL from a URL on your domain
var redirectUrl = '/redirect.html?redirect=' +
url;
return clients.openWindow(redirectUrl);
}));
}
});
La prima cosa da sottolineare con questo snippet di codice è che filtriamo le notifiche passando un oggetto filtro a getNotifications(). Ciò significa che possiamo ottenere un elenco di notifiche per un tag specifico (in questo esempio per una conversazione specifica).
var notificationFilter = {
tag: notificationTag
};
return self.registration.getNotifications(notificationFilter)
Quindi controlliamo le notifiche visibili e controlliamo se esiste un numero di notifiche associato a quella notifica e incrementa in base a ciò. In questo modo, se una notifica indica all'utente che ci sono due messaggi da leggere, vogliamo segnalare che ce ne sono tre quando arriva una nuova notifica push.
var notificationCount = 1;
for (var i = 0; i < notifications.length; i++) {
var existingNotification = notifications[i];
if (existingNotification.data && existingNotification.data.notificationCount) {
notificationCount += existingNotification.data.notificationCount;
} else {
notificationCount++;
}
existingNotification.close();
}
Un'ulteriore informazione da sottolineare è che devi chiamare close()
sulla notifica per assicurarti che venga rimossa dall'elenco delle notifiche. Si tratta di un bug di Chrome, poiché ogni notifica viene sostituita dalla successiva perché viene utilizzato lo stesso tag. Al momento questa sostituzione non viene applicata all'array restituito da getNotifications()
.
Questo è solo un esempio di getNotifications() e, come puoi immaginare, questa API offre una serie di altri casi d'uso.
NotificationOptions.vibrate
A partire da Chrome 45, puoi specificare un pattern di vibrazione durante la creazione di una notifica. Sui dispositivi che supportano l'API Vibration, attualmente solo Chrome per Android, puoi personalizzare il pattern di vibrazione che verrà utilizzato quando viene visualizzata la notifica.
Un pattern di vibrazione può essere un array di numeri o un singolo numero che viene trattato come un array di un numero. I valori nell'array rappresentano i tempi in millisecondi, con gli indici pari (0, 2, 4, ...) che indicano la durata della vibrazione e gli indici strani indicano il tempo in cui bisogna fermarsi prima della vibrazione successiva.
self.registration.showNotification('Buzz!', {
body: 'Bzzz bzzzz',
vibrate: [300, 100, 400] // Vibrate 300ms, pause 100ms, then vibrate 400ms
});
Richieste di funzionalità comuni rimanenti
L'unica richiesta di funzionalità comune ancora presente da parte degli sviluppatori è la possibilità di chiudere una notifica dopo un determinato periodo di tempo o di inviare una notifica push con lo scopo di chiudere una notifica se è visibile.
Al momento non esiste un modo per farlo e non è previsto nelle specifiche :( ma il team tecnico di Chrome è a conoscenza di questo caso d'uso.
Notifiche Android
Sul computer puoi creare una notifica con il seguente codice:
new Notification('Hello', {body: 'Yay!'});
Questa funzionalità non è mai stata supportata su Android a causa delle limitazioni della piattaforma: nello specifico, Chrome non può supportare i callback sull'oggetto Notification, ad esempio Stackdriver. Tuttavia, viene utilizzato su computer per visualizzare le notifiche per le app web che potresti avere aperte al momento.
L'unico motivo per cui lo menziono è che in origine un semplice rilevamento delle funzionalità come quello riportato di seguito ti aiutava a supportare il desktop e non causava errori su Android:
if (!'Notification' in window) {
// Notifications aren't supported
return;
}
Tuttavia, con il supporto delle notifiche push ora su Chrome per Android, le notifiche possono essere create da un ServiceWorker, ma non da una pagina web, il che significa che questo rilevamento delle funzionalità non è più appropriato. Se provi a creare una notifica su Chrome per Android, riceverai il seguente messaggio di errore:
_Uncaught TypeError: Failed to construct 'Notification': Illegal constructor.
Use ServiceWorkerRegistration.showNotification() instead_
Al momento, il modo migliore per rilevare le funzionalità per Android e computer è:
function isNewNotificationSupported() {
if (!window.Notification || !Notification.requestPermission)
return false;
if (Notification.permission == 'granted')
throw new Error('You must only call this \*before\* calling
Notification.requestPermission(), otherwise this feature detect would bug the
user with an actual notification!');
try {
new Notification('');
} catch (e) {
if (e.name == 'TypeError')
return false;
}
return true;
}
Può essere utilizzato nel seguente modo:
if (window.Notification && Notification.permission == 'granted') {
// We would only have prompted the user for permission if new
// Notification was supported (see below), so assume it is supported.
doStuffThatUsesNewNotification();
} else if (isNewNotificationSupported()) {
// new Notification is supported, so prompt the user for permission.
showOptInUIForNotifications();
}