Zuerst möchte ich mich für den schrecklichen Titel entschuldigen, aber ich konnte nicht anders.
In Chrome 44 wurden Notfication.data und ServiceWorkerRegistration.getNotifications() hinzugefügt. Dadurch werden einige gängige Anwendungsfälle im Umgang mit Benachrichtigungen mit Push-Nachrichten vereinfacht.
Benachrichtigungsdaten
Mit „Notification.data“ können Sie ein JavaScript-Objekt mit einer Benachrichtigung verknüpfen.
Wenn Sie also eine Push-Nachricht erhalten, können Sie eine Benachrichtigung mit einigen Daten erstellen. Im Ereignis „notificationclick“ können Sie dann die Benachrichtigung abrufen, auf die geklickt wurde, und die zugehörigen Daten abrufen.
So erstellen Sie beispielsweise ein Datenobjekt und fügen es Ihren Benachrichtigungsoptionen hinzu:
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
})
);
});
Das bedeutet, dass wir die Informationen im Ereignis „notificationclick“ abrufen können:
self.addEventListener('notificationclick', function(event) {
var doge = event.notification.data.doge;
console.log(doge.wow);
});
Bisher mussten Sie Daten in IndexDB speichern oder etwas ans Ende der Symbol-URL anhängen – ganz schön umständlich.
ServiceWorkerRegistration.getNotifications()
Eine häufige Anforderung von Entwicklern, die mit Push-Benachrichtigungen arbeiten, ist eine bessere Kontrolle über die angezeigten Benachrichtigungen.
Ein Beispiel für einen Anwendungsfall wäre eine Chat-Anwendung, in der ein Nutzer mehrere Nachrichten sendet und der Empfänger mehrere Benachrichtigungen erhält. Idealerweise sollte die Webanwendung erkennen können, dass Sie mehrere Benachrichtigungen haben, die noch nicht angesehen wurden, und sie zu einer einzigen Benachrichtigung zusammenfassen.
Ohne getNotifications() können Sie die vorherige Benachrichtigung nur durch die neueste Nachricht ersetzen. Mit getNotifications() können Sie die Benachrichtigungen minimieren, wenn bereits eine Benachrichtigung angezeigt wird. Das führt zu einer deutlich besseren Nutzerfreundlichkeit.
Der Code dafür ist relativ einfach. Rufen Sie in Ihrem Push-Ereignis ServiceWorkerRegistration.getNotifications() auf, um ein Array der aktuellen Benachrichtigungen zu erhalten. Entscheiden Sie dann, wie die Benachrichtigungen angezeigt werden sollen, z. B. ob alle minimiert werden sollen oder ob das Notification.tag verwendet werden soll.
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);
}));
}
});
Bei diesem Code-Snippet ist vor allem wichtig, dass wir unsere Benachrichtigungen filtern, indem wir ein Filterobjekt an „getNotifications()“ übergeben. So können wir eine Liste mit Benachrichtigungen für ein bestimmtes Tag abrufen (in diesem Beispiel für eine bestimmte Unterhaltung).
var notificationFilter = {
tag: notificationTag
};
return self.registration.getNotifications(notificationFilter)
Anschließend sehen wir uns die sichtbaren Benachrichtigungen an und prüfen, ob mit dieser Benachrichtigung eine Benachrichtigungszahl verknüpft ist. Daraufhin wird die Anzahl der Benachrichtigungen entsprechend erhöht. Wenn der Nutzer also eine Benachrichtigung erhält, dass er zwei ungelesene Nachrichten hat, möchten wir ihn darauf hinweisen, dass er drei ungelesene Nachrichten hat, wenn eine neue Push-Nachricht eingeht.
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();
}
Wichtig: Sie müssen close()
auf die Benachrichtigung anwenden, damit sie aus der Benachrichtigungsliste entfernt wird. Dies ist ein Fehler in Chrome, da jede Benachrichtigung durch die nächste ersetzt wird, da dasselbe Tag verwendet wird. Derzeit wird dieser Ersatz nicht im zurückgegebenen Array von getNotifications()
berücksichtigt.
Dies ist nur ein Beispiel für getNotifications(). Wie Sie sich vorstellen können, eröffnet diese API eine Reihe weiterer Anwendungsfälle.
NotificationOptions.vibrate
Ab Chrome 45 können Sie beim Erstellen einer Benachrichtigung ein Vibrationsmuster angeben. Auf Geräten, die die Vibration API unterstützen (derzeit nur Chrome für Android), können Sie das Vibrationsmuster anpassen, das beim Anzeigen der Benachrichtigung verwendet wird.
Ein Vibrationsmuster kann entweder ein Zahlenarray oder eine einzelne Zahl sein, die als Array mit einer Zahl behandelt wird. Die Werte im Array geben die Zeit in Millisekunden an. Die geraden Indizes (0, 2, 4, ...) geben an, wie lange vibriert werden soll, und die ungeraden Indizes geben an, wie lange die Pause vor der nächsten Vibration sein soll.
self.registration.showNotification('Buzz!', {
body: 'Bzzz bzzzz',
vibrate: [300, 100, 400] // Vibrate 300ms, pause 100ms, then vibrate 400ms
});
Verbleibende häufige Anfragen zu Funktionen
Die einzige verbleibende häufige Funktionsanfrage von Entwicklern ist die Möglichkeit, eine Benachrichtigung nach einem bestimmten Zeitraum zu schließen oder eine Push-Benachrichtigung zu senden, um eine Benachrichtigung zu schließen, wenn sie sichtbar ist.
Leider ist das derzeit nicht möglich und auch in der Spezifikation ist das nicht vorgesehen. Das Chrome-Entwicklerteam ist sich dieses Anwendungsfalls aber bewusst.
Android-Benachrichtigungen
Auf dem Computer können Sie eine Benachrichtigung mit dem folgenden Code erstellen:
new Notification('Hello', {body: 'Yay!'});
Aufgrund von Einschränkungen der Plattform wurde dies unter Android nie unterstützt. Chrome kann insbesondere die Rückrufe für das Benachrichtigungsobjekt nicht unterstützen, z. B. onclick. Auf dem Computer wird sie jedoch verwendet, um Benachrichtigungen für Web-Apps anzuzeigen, die Sie möglicherweise gerade geöffnet haben.
Ich erwähne das nur, weil ursprünglich eine einfache Funktionserkennung wie die unten beschriebene dazu beigetragen hat, die Desktopversion zu unterstützen und keine Fehler auf Android-Geräten zu verursachen:
if (!'Notification' in window) {
// Notifications aren't supported
return;
}
Da Push-Benachrichtigungen jetzt in Chrome für Android unterstützt werden, können Benachrichtigungen über einen ServiceWorker, aber nicht über eine Webseite erstellt werden. Daher ist diese Funktion nicht mehr geeignet. Wenn Sie versuchen, in Chrome für Android eine Benachrichtigung zu erstellen, erhalten Sie diese Fehlermeldung:
_Uncaught TypeError: Failed to construct 'Notification': Illegal constructor.
Use ServiceWorkerRegistration.showNotification() instead_
Die Funktion „Funktionserkennung“ für Android und Computer lässt sich derzeit am besten so prüfen:
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;
}
So kann es verwendet werden:
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();
}