In this fifth post of my series on notifications, I’ll start looking at each of the notification delivery mechanisms (local, scheduled, periodic, and push) in turn. The structure and mechanics of creating notification content, which I covered in a previous post, are for the most part independent of the delivery method, so the posts that follow assume a basic understanding of accessing and customizing the various types of notification templates.
Let’s kick it off with Local Notifications!
for Local Notifications
Quick and Easy
Local notifications are the simplest of the four delivery mechanisms and something that every application should consider leveraging. Even if you use a local notification to simply update your tile each time the user opens the application, it highlights your app as being fresh and alive.
For content-focused applications, like photo albums or recipe managers, updating the tile with an image from the last accessed photo, recipe, or whatever can take your application’s Start screen experience from flat to fun!
Design Considerations for Local Notifications
Local notifications for Badges and Tiles: an Oxymoron?
One irony about local badge and tile notifications is that the user cannot, by definition, see them right when they happen! That’s because local notifications only occur while the application is in a running state, and if you’re looking at the Start screen, that app is in a suspended state (or possibly not running at all); check out the Application lifecycle if this has you scratching your head!
The way to interpret this is not that local badge and tile notifications are pointless, but rather that they should be used to deposit information to entice the user to revisit your application every time they view the Start screen. Since there isn’t a definitive application ‘close’ event to rely on (you can only programmatically detect when an application is suspended), don’t save badge and tile updates for some wrap-up process, because there isn’t one!.
You can certainly use the suspending event as a place to make a tile or badge update; however, it’s generally better to include the notification as part of the overall application’s UI workflow versus within a lifecycle event. For example, in that recipe application, update the tile with a photo of grandma’s awesome lasagna when a user selects that recipe in the context of the application, not because it’s the currently loaded recipe when the suspending event occurs.
No Toast for You!
There’s a converse argument to be made about local toast notifications. They can only be triggered and appear while the application is running, and if the application is right there in the foreground on your screen, do you need a toast – or should the application itself organically incorporate that content?
For a Twitter application (granted they wouldn’t be local notifications), I typically don’t want or expect to see toast notifications and my timeline updated, likewise for incoming e-mails while viewing my in-box. Toast is superfluous and can be annoying in that context.
In fact, the Guidelines and checklist for toast notifications explicitly includes the following recommendation:
Don’t raise a toast notification when your application is in the foreground. In that case, consider notifying the user in the context of your app with a Flyout, dialog, app bar, or other inline element. ….
That is a recommendation though, not an edict, which could actually have been enforced by Windows not providing an API for local toast notifications at all. One specific example that I can think of where local toast ‘works’ (although it’s not a Windows 8 application) is the Visual Studio Achievements gamification add-in to our favorite IDE.
Recall that whether a tile will update or a toast will appear is ultimately at the discretion of the user, so never rely on these mechanisms to relay critical information. You can detect the permissibility of notifications – perhaps to forego network service calls or other costly operations required to construct a notification that will never been seen – via the TileUpdater and ToastNotifier classes.
- enabled (0): notification is allowed
- disabledForApplication (1): user has disabled notification for given application
- disabledForUser (2): user or administrator has disabled notifications for current user on the computer
- disabledByGroupPolicy (3): notifications have been disabled by group policy (overriding user’s setting)
- disabledByManiifest (4): application’s manifest setting doesn’t indicate that it’s “Toast Capable”
Triggering the Local Notification
Once you have your notification template content assembled (see my prior post for a primer on doing so), it’s a simple call to one of three methods depending on the notification type:
ToastNotifier.show triggers a toast notification.
Since local notifications are programmatically triggered on demand by the application, cancelling them is tantamount to not triggering the notification in the first place. That said there are few things to keep in mind, since the effects of some notifications can linger beyond their relevancy.
Tile and Badge notifications expire after three days by default, but you can specify an alternative expiration time (see TileNotification.expirationTime and BadgeNotification.expirationTime). Depending on the needs of your application, you may want to explicitly clear either or both – based on new information at launch time. For instance,
- You can use TileUpdater.clear to reset the tile to what was declared in the application’s manifest. You might do this if you determine that the previous content is no longer relevant, but there is nothing new to replace it.
- Similarly, BadgeUpdater.clear removes the badge from the targeted tile; you might use this when activating a subscription-type application to reset the number of unread articles, e-mails, tweets, etc.
It is possible to programmatically hide a toast, but the guidelines counsel you shouldn’t do so “unless absolutely necessary.” A valid scenario might include a long running toast inviting the user to a VOIP chat, but the initiator hangs up before the user responds to the request.