Monday, February 25, 2013

Rich Notifications in Chrome Packaged Apps


Several modern application platforms provide mechanisms for notifying the user of interesting events. Android, iOS, Mac OSX, Windows - they all have a fairly common, standard way of organizing notifications and displaying them to the user.

With the release of Chrome Canary M27, the Chrome Packaged Apps platform joins that club by providing the Rich Notifications API on ChromeOS and Windows (Mac and Linux to follow soon). This API goes beyond the web-standard HTML notifications system by allowing more visually rich notifications to be displayed (since the official W3C spec recently removed support for HTML-based notifications). The API is fairly flexible, allowing developers to specify one of four basic layout templates and register for events that happen on individual notifications.

Note: although the API is fairly stable and will soon be exiting the experimental phase, it is still undergoing changes. Use with caution.


The API supports 4 types of notifications:

  • Simple - an icon and some text content
  • Basic - icon and text content, and up to two buttons
  • Image - icon, text, and image, and up to two buttons
  • List - icon and list content, and up to two buttons

Chrome Notifications User Experience

Chrome Notifications are displayed according to the underlying OS’s conventions. On Windows, for example, the notification appears as a “toast” pop-up in the lower right corner of the screen:


Notifications can contain images in addition to text:




In addition to the notifications themselves, the Chrome Notifications API provides a notifications center that organizes the notifications by criteria such as date, priority, etc.

The Notifications API

The API itself is fairly simple. Notifications can be created, updated, and deleted using straightforward methods:
function create(DOMString notificationId, NotificationOptions options, 
    CreateCallback callback);
function update(DOMString notificationId, NotificationOptions options, 
    UpdateCallback callback);
function delete(DOMString notificationId, DeleteCallback callback);

A few things to note when using the API:

  1. The notificationId parameter is a string of your choosing, as long as it is unique (which is required to keep the notifications center from becoming confused).
  2. The NotificationOptions structure defines the content of the notification - its type, title, message, buttons, and so on.
  3. Some of the NotificationOptions properties allow you to specify URLs for images; they currently do not accept data:// URLs (though this is planned). In addition, you can use the chrome.runtime.getURL() method to retrieve an app- or extension-relative path to an image resource included with your package.
  4. Although the API provides parameters such as priority, the API does not make any guarantees as to how such parameters will affect the display of notifications - they are just hints to the system (for example, the OS may decide that a low priority notification merely lights up the notification center icon instead of displaying it). Currently, normal priority notifications (0) are displayed for 7 seconds, higher priority (1 and 2) are displayed for 25 seconds.
  5. The update() method can be used to transform a notification from one type into another, such as from "simple" to "image". Very cool.
  6. As with many other Chrome APIs, this one is asynchronous - it uses callbacks to indicate to the calling program the result of each function.

Example:
var path = chrome.runtime.getURL("/images/myicon.png");
var options = {
   templateType : "simple",
   title: "Simple Notification",
   message: "Just a text message and icon",
   iconUrl : path,
   priority: 0
};

chrome.experimental.notification.create("id1", options, crCallback);

function crCallback(notID) {
   console.log("Succesfully created " + notID + " notification");
}

Notification Events

In addition to the API functions to create, update, and delete notifications, your program can register to listen for notification events. There are currently five such events.

  • onDisplayed - the notification was created and displayed to the user
  • onError - there was an error with the notification
  • onClosed - the notification was closed, either due to a system timeout or by the user (and it is possible to distinguish the difference)
  • onClicked - the body of the notification itself was clicked
  • onButtonClicked - the user clicked on one of the buttons in the notification (this event fires on the notification itself, and the index of the clicked button is a parameter).

Events are registered using the typical addListener() method for Chrome events:
chrome.experimental.notification.onDisplayed.addListener(fDisplayed);
chrome.experimental.notification.onClicked.addListener(notClicked);
chrome.experimental.notification.onButtonClicked.addListener(notBtnClk);

function fDisplayed(notID) {
   console.log("The notification '" + notID + 
       "' was displayed to the user");
}
function notClicked(notID) {
   console.log("The notification '" + notID + "' was clicked");
}
function notBtnClk(notID, iBtn) {
   console.log("The notification '" + notID + "' had button " + iBtn + " clicked");
}

Summary

The Chrome Rich Notifications API marks another step in the process of bringing native-app-like capabilities to Chrome Packaged Apps and Extensions. To get started, check out our example on the GoogleChromeGithub. Consider adding support for this API in your next project to give your users an experience that is more tightly integrated with their OS and in line with what they’ve come to expect from native applications!