Hopefully, you’ve had a chance to review my previous post on Local Notifications as it sets the foundation nicely for taking the next step to scheduling notifications to occur at some point in the future – when the application itself may or may not be actually running.
Bookmark-worthy References for Scheduled Notifications
Guidelines and checklist
Tiles guidelines and checklist
Toast guidelines and checklist
Sample: Scheduled notifications
Whitepaper: Background tasks
Taking the step from a local notification to a scheduled one is pretty simple; a scheduled notification is more or less a local notification with a specific delivery time attached to it. Given that there is no guarantee that the application will be running when that time arrives, a scheduled notification can actually fire when the application itself isn’t running.
Any time-management application is an obvious candidate for incorporating scheduled notifications, but don’t hesitate to think outside-of-the-box. Reminders may be equally valuable in many applications that don’t sport a calendar as the user interface; a financial management application, for instance, could alert you regarding upcoming tax or other filing deadlines.
Badges can’t be a target for scheduled notifications; only tiles and toast are supported.
In my previous post on Local Notifications, I mentioned that you can detect whether tile or toast notifications are enabled and perhaps decide whether or not to bother sending them. With scheduled notifications, there’s a bit of a twist, because the user's settings could change between the point the code schedules the notification and when it’s received.
As a result, notifications that do get scheduled may not appear because the user subsequently either opted out of tile updates via the app bar or turned off all notifications via PC Settings. Conversely, if your application uses the setting property to decide not to schedule a notification, say for a sports league practice application, you could confuse a user who subsequently opted in to notifications and might now be expecting to see a reminder.
There’s no harm in always scheduling the notification and letting the state of the system at the point the notification occurs determine what the user sees (or doesn’t). If it turns out that a notification that was previous scheduled, but has not yet occurred, shouldn’t be shown, you can programmatically remove it.
Whenever time is involved, things get complicated! What time zone? What about Daylight Savings Time, British Summer Time, and other similar wrinkles?
When you schedule a notification, the delivery time (and expiration time for tiles) that you specify is localized, but the underlying notification mechanism converts it to Coordinated Universal Time (UTC). The time of the notification is set at the point the notification is constructed, which yields a scenario like this:
In most cases, this is what you’d expect and desire, but what if you want more of a locale independent reminder – you have medication you need to take at noon and would like to have a toast notification alert you at noon, regardless of what time zone you happen to be in? That’s takes a little more work because the notification time isn’t absolute but rather is dependent on your local settings. Here’s one way you could go about this:
You can schedule up to 4096 notifications for an application, so for recurring tasks – say a reminder to fill out a timecard every Friday – you could just schedule a year or so worth of reminders ahead of time and then maybe include a separate “meta-reminder” in a year to schedule the next year’s worth, but there’s a much better way!
With a MaintenanceTrigger you can initiate a background task to run at a regular interval, let’s say every week. In the background task itself, you’d then schedule the next weekly reminder. There are a few constraints to be aware of though:
change! Be sure to include a mechanism in your app for cleaning up notifications that are no longer relevant such as a reminder for a meeting that’s been cancelled. Consider using the id property to link a notification with a content item if changes to that item may require modifying the notification. An id is a 16 character string of your choosing giving you the flexibility to devise an encoding scheme for such a mapping.
Finding a notification with a given id requires traversing the list of notifications and then checking each of the notification ids against whatever encoding scheme you’ve devised. Matching notifications can be easily deleted via TileUpdater.removeFromSchedule or ToastNotifier.removeFromSchedule.
Lastly, if you’ve engaged a MaintenanceTrigger for a recurring notification, and you no longer want the notifications to occur, be sure to unregister the background task.
You’ll use one of two classes for the notification (depending on the notification type, toast or tile). Each of the class constructors expects two parameters: a completed notification template (see my prior post for a primer) and the localized notification delivery time.
A ScheduledTileNotification includes two additional properties over its local counterpart
Each ScheduledToastNofitication likewise includes id and deliveryTime properties, but it also offers ‘snooze’ settings to repeat the notification at a defined interval:
Once the scheduled notification instance has been constructed, it’s a simple call to the addToSchedule method of the appropriate notifier class, either ToastNotifier or TileUpdater. Remember, badges can’t be updated via scheduled notifications.
For recurring notifications, as mentioned above, you may want to leverage a MaintenanceTrigger to schedule the next notification in the sequence. Full coverage of background tasks is a bit out of scope for this post, but the SDK background task code sample and whitepaper should provide insight into how to use tasks in conjunction with notifications.
After the scheduled notification has arrived, the same semantics for clearing it that apply to local notifications apply here. Specifically, you can reset (or more technically clear) a tile to the state specified in the application’s manifest, and you can programmatically hide a toast, keeping in mind that the guidelines discourage doing so.
More interesting (and challenging) is clearing notifications that are scheduled to occur but should be removed since they are no longer relevant. I’ve already broached that subject in the design considerations section above, but here’s a itemization of the key API classes and properties you’d leverage to do so:
In more sophisticated scenarios, when you’ve engaged a background task to set up a recurring toast or tile notification, you’ll need to cancel the background task as well. I’d recommend doing this first and then cleaning up any notifications that may have been scheduled as a follow on step. To disable the background task, you’ll leverage a few of the methods and properties of BackgroundTaskRegistration:
Check out the Scheduled notifications sample on the Windows Dev Center; it includes functionality for the snooze feature as well as querying and removing notifications that are scheduled for the future (but have since been deemed obsolete).
Although the Background task sample doesn’t deal with notifications directly, it provides good insight into the patterns and practices for setting up recurring tasks tied to system event, like a time zone change. I’d also recommend reading the Background task whitepaper for more insight into this important facet of a Window 8 application’s lifecycle.