En primer lugar, te pido disculpas por ese título tan pésimo, pero no pude.
En Chrome 44, Notfication.data y ServiceWorkerRegistration.getNotifications() y simplifican algunos casos de uso comunes cuando se trabaja con notificaciones con mensajes push.
Datos de notificación
Notification.data te permite asociar un objeto de JavaScript con un Notificación.
A esto se resume que, cuando recibes un mensaje push, puedes crea una notificación con datos y, en el evento notificationclick, puede recibir la notificación en la que se hizo clic y obtener sus datos.
Por ejemplo, crear un objeto de datos y agregarlo a tus opciones de notificación así:
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 que podemos obtener la información en el evento notificationclick:
self.addEventListener('notificationclick', function(event) {
var doge = event.notification.data.doge;
console.log(doge.wow);
});
Antes de esto, tenías que guardar datos en IndexDB o colocar algo al final URL del ícono: eek.
ServiceWorkerRegistration.getNotifications()
Una solicitud habitual de los desarrolladores que trabajan en notificaciones push tener un mejor control de las notificaciones que muestran.
Un ejemplo de caso de uso sería una aplicación de chat donde un usuario envía varios y el destinatario muestra varias notificaciones. Idealmente, la app web podría notar que tienes varias notificaciones que no se han visto y las contrae en una sola notificación.
Sin getNotifications(), lo mejor que puedes hacer es reemplazar el anterior con el último mensaje. Con getNotifications(), puedes “contraer” las notificaciones si ya se muestra, lo que lleva a una experiencia del usuario mucho mejor.
El código para hacerlo es relativamente simple. En el evento push, llama ServiceWorkerRegistration.getNotifications() para obtener un array de Las notificaciones y, a partir de allí, deciden el comportamiento correcto, ya sea contrayendo todas las notificaciones o usando la etiqueta Notification.
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);
}));
}
});
Lo primero a destacar con este fragmento de código es que filtramos notificaciones pasando un objeto de filtro a getNotifications(). Esto significa que puede obtener una lista de notificaciones para una etiqueta específica (en este ejemplo, para un conversación en particular).
var notificationFilter = {
tag: notificationTag
};
return self.registration.getNotifications(notificationFilter)
Luego, miramos las notificaciones visibles y comprobamos es un recuento de notificaciones asociado con esa notificación y se incrementa según sobre eso. De esta manera, si hay una notificación que indica al usuario que hay dos mensajes no leídos, queremos destacar que hay tres mensajes no leídos cuando llega un nuevo envío.
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();
}
Una sutileza a destacar es que debes llamar a close()
en la notificación para
asegúrate de que la notificación se quite de la lista. Este es un error en
Chrome, ya que cada notificación se reemplaza por la siguiente porque la misma etiqueta
y control sobre el uso de sus datos. Por el momento, este reemplazo no se refleja en el array que se muestra
desde getNotifications()
.
Este es solo un ejemplo de getNotifications() y, como puedes imaginar, esta API ofrece una variedad de otros casos de uso.
NotificationOptions.vibrate
A partir de Chrome 45, es posible especificar un patrón de vibración al crear una notificación. En los dispositivos que admiten API de Vibration: actualmente solo Chrome para Android. Esto te permite personalizar el patrón de vibración que cuando se muestre la notificación.
Un patrón de vibración puede ser un array de números o un único número que se trata como un array de un número. Los valores del array representan tiempos en milisegundos, y los índices pares (0, 2, 4, ...) indican cuánto tiempo vibrar, y los índices extraños indican cuánto tiempo hacer una pausa antes de la próxima vibración.
self.registration.showNotification('Buzz!', {
body: 'Bzzz bzzzz',
vibrate: [300, 100, 400] // Vibrate 300ms, pause 100ms, then vibrate 400ms
});
Solicitudes de funciones restantes comunes
La única solicitud de función común que siguen los desarrolladores es la capacidad de cerrar una notificación después de un período determinado o la capacidad de enviar una notificación una notificación solo con el fin de cerrar una notificación si es visible.
Por el momento, no existe una forma de hacer esto y nada de la especificación lo permitirá :( pero el equipo de ingeniería de Chrome conoce este caso de uso.
Notificaciones de Android
En una computadora, puedes crear una notificación con el siguiente código:
new Notification('Hello', {body: 'Yay!'});
Esta función nunca se admitía en Android debido a las restricciones de la plataforma: específicamente, Chrome no admite las devoluciones de llamada en el objeto de notificación como “onclick”. Pero se usa en computadoras para mostrar notificaciones de la Web que tengas abiertas actualmente.
La única razón por la que menciono esto es que, originalmente, una simple detección de funciones como la que se muestra a continuación, te ayudaría a admitir la versión para computadoras de escritorio y no causaría errores en En Android:
if (!'Notification' in window) {
// Notifications aren't supported
return;
}
Sin embargo, dado que ahora es compatible con las notificaciones push en Chrome para Android, pueden crearse desde un ServiceWorker, pero no desde una página web, lo que significa que la detección de atributos ya no es apropiada. Si intentas crear una notificación en Chrome para Android recibirás el siguiente mensaje de error:
_Uncaught TypeError: Failed to construct 'Notification': Illegal constructor.
Use ServiceWorkerRegistration.showNotification() instead_
Por el momento, la mejor manera de detectar funciones para Android y computadoras de escritorio lo siguiente:
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;
}
Se puede usar de la siguiente manera:
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();
}