Ten eerste bied ik mijn excuses aan voor die vreselijke titel, maar dat kon niet.
In Chrome 44 zijn Notfication.data en ServiceWorkerRegistration.getNotifications() toegevoegd en openen/vereenvoudigen enkele veelvoorkomende gebruiksscenario's bij het omgaan met meldingen met pushberichten.
Meldingsgegevens
Met Notification.data kunt u een JavaScript-object aan een melding koppelen.
Waar dit in feite op neerkomt, is dat wanneer u een pushbericht ontvangt, u een melding met enkele gegevens kunt maken, en vervolgens in de notificatieklikgebeurtenis de melding kunt krijgen waarop is geklikt en de gegevens ervan kunt ophalen.
U kunt bijvoorbeeld een gegevensobject maken en dit als volgt aan uw meldingsopties toevoegen:
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
})
);
});
Betekent dat we de informatie in de notificatieklik-gebeurtenis kunnen krijgen:
self.addEventListener('notificationclick', function(event) {
var doge = event.notification.data.doge;
console.log(doge.wow);
});
Voordien moest u gegevens in IndexDB opslaan of iets aan het einde van de pictogram-URL plaatsen - eek.
ServiceWorkerRegistration.getNotifications()
Een veelvoorkomend verzoek van ontwikkelaars die aan pushmeldingen werken, is om betere controle te hebben over de meldingen die ze weergeven.
Een voorbeeld van een gebruiksscenario is een chattoepassing waarbij een gebruiker meerdere berichten verzendt en de ontvanger meerdere meldingen weergeeft. Idealiter zou de webapp kunnen opmerken dat er meerdere meldingen zijn die niet zijn bekeken, en deze samenvoegen tot één melding.
Zonder getNotifications() kun je het beste de vorige melding vervangen door het nieuwste bericht. Met getNotifications() kunt u de meldingen "samenvouwen" als er al een melding wordt weergegeven, wat leidt tot een veel betere gebruikerservaring.
De code om dit te doen is relatief eenvoudig. Roep binnen uw push-gebeurtenis ServiceWorkerRegistration.getNotifications() aan om een reeks huidige meldingen op te halen en van daaruit het juiste gedrag te bepalen, of dat nu het samenvouwen van alle meldingen is of het gebruik van de 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);
}));
}
});
Het eerste dat we benadrukken met dit codefragment is dat we onze meldingen filteren door een filterobject door te geven aan getNotifications(). Dit betekent dat we een lijst met meldingen kunnen krijgen voor een specifieke tag (in dit voorbeeld voor een bepaald gesprek).
var notificationFilter = {
tag: notificationTag
};
return self.registration.getNotifications(notificationFilter)
Vervolgens bekijken we de zichtbare meldingen en controleren we of er een aantal meldingen aan die melding is gekoppeld en op basis daarvan een verhoging. Op deze manier willen we, als er één melding is die de gebruiker vertelt dat er twee ongelezen berichten zijn, erop wijzen dat er drie ongelezen berichten zijn wanneer er een nieuwe push binnenkomt.
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();
}
Een subtiliteit om te benadrukken is dat u close()
voor de melding moet aanroepen om ervoor te zorgen dat de melding uit de meldingenlijst wordt verwijderd. Dit is een bug in Chrome omdat elke melding wordt vervangen door de volgende omdat dezelfde tag wordt gebruikt. Op dit moment wordt deze vervanging niet weerspiegeld in de geretourneerde array van getNotifications()
.
Dit is slechts één voorbeeld van getNotifications() en zoals u zich kunt voorstellen, opent deze API een reeks andere gebruiksscenario's.
Meldingsopties.trillen
Vanaf Chrome 45 kun je een trilpatroon opgeven bij het maken van een melding. Op apparaten die de Vibration API ondersteunen (momenteel alleen Chrome voor Android) kun je hiermee het trilpatroon aanpassen dat wordt gebruikt wanneer de melding wordt weergegeven.
Een trillingspatroon kan een reeks getallen zijn, of een enkel getal dat wordt behandeld als een reeks van één getal. De waarden in de array vertegenwoordigen tijden in milliseconden, waarbij de even indices (0, 2, 4, ...) aangeven hoe lang er moet worden getrild, en de oneven indices hoe lang er moet worden gepauzeerd vóór de volgende trilling.
self.registration.showNotification('Buzz!', {
body: 'Bzzz bzzzz',
vibrate: [300, 100, 400] // Vibrate 300ms, pause 100ms, then vibrate 400ms
});
Resterende algemene functieverzoeken
Het enige overgebleven veel voorkomende functieverzoek van ontwikkelaars is de mogelijkheid om een melding na een bepaalde tijdsperiode te sluiten of de mogelijkheid om een pushmelding te sturen met als doel een melding alleen te sluiten als deze zichtbaar is.
Op dit moment is er geen manier waarop u dit kunt doen en niets in de specificaties dat dit toestaat :( maar het technische team van Chrome is op de hoogte van dit gebruiksscenario.
Android-meldingen
Op desktop kunt u een melding maken met de volgende code:
new Notification('Hello', {body: 'Yay!'});
Dit werd nooit ondersteund op Android vanwege beperkingen van het platform: Chrome kan met name de callbacks op het Notification-object, zoals onclick, niet ondersteunen. Maar het wordt op het bureaublad gebruikt voor het weergeven van meldingen voor webapps die u momenteel mogelijk geopend heeft.
De enige reden dat ik het vermeld is dat oorspronkelijk een eenvoudige functiedetectie zoals hieronder je zou helpen de desktop te ondersteunen en geen fouten op Android te veroorzaken:
if (!'Notification' in window) {
// Notifications aren't supported
return;
}
Nu echter ondersteuning voor pushmeldingen in Chrome voor Android beschikbaar is, kunnen meldingen worden gemaakt vanuit een ServiceWorker, maar niet vanaf een webpagina, wat betekent dat deze functiedetectie niet langer geschikt is. Als u probeert een melding te maken in Chrome voor Android, ontvangt u deze foutmelding:
_Uncaught TypeError: Failed to construct 'Notification': Illegal constructor.
Use ServiceWorkerRegistration.showNotification() instead_
De beste manier om detectie voor Android en desktop op dit moment uit te voeren, is door het volgende te doen:
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;
}
Dit kan als volgt worden gebruikt:
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();
}