Click here to Skip to main content
Click here to Skip to main content

Windows 8 Notifications Scheduled Notifications

By , 30 Aug 2012
 

Check out Jim O'Neil's blog here: http://blogs.msdn.com/b/jimoneil/

Also, check out our Windows 8 sponsored section.

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

Time-specific "local" notifications

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.

Design Considerations for Scheduled Notifications Badges? We Don’t Need No Stinkin’ Badges

Badges can’t be a target for scheduled notifications; only tiles and toast are supported.

To Schedule or Not to Schedule

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 your code schedules the notification and when it’s received.

Of course, 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 may confuse a user that subsequently opted in to notifications, because whether a given notification appears depends on the state of the app at the point the notification was constructed (or not) - all quite opaque to the user!

Does Anyone Really Know What Time it Is?

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:

  • You’re in Boston on Monday, and your application schedules a reminder for Tuesday at 3 p.m.
  • You fly to San Francisco Monday afternoon, and upon arrival update your system clock to reflect that you’re now on Pacific Time.
  • On Tuesday, your reminder appears at noon, since there’s a time zone differential of three hours between Boston and San Francisco).

In most cases, this is what you want, 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:

  • Schedule the notification normally; it will occur at noon ("wall time") as long as you don’t change the system clock.
  • Store a notification id, the scheduled time for the notification (noon), and the details of the notification (perhaps even the full XML template) in application data storage.
  • Setup a background task that will run when the time zone changes on the device. (For more information on background tasks, check out the whitepaper and a sample at dev.windows.com which includes a background task specifically tied to the timeZoneChange SystemTriggerType.)
  • In that background task,

If It’s Tuesday, This Must be Belgium

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 years’ worth, but there’s a much better way!

With a MaintenanceTrigger you can set up a background task to run at a regular interval, let’s say every week, by setting the freshnessTime, the number of minutes that elapse until the background task is scheduled. In the background task itself, you’d then schedule the next weekly reminder. There are a few constraints to be aware of though

  • The system has up to 15 minutes from when the freshnessTime elapses to schedule the background task, so leave an adequate bufffer to ensure the notification gets scheduled before it actually occurs!
  • A background task associated with a MaintenanceTrigger only fires when the machine is on battery power. The triggered tasks are, however, buffered so they will fire the next time the machine is plugged in.

The Best Laid Plans...

change! Be sure to include a mechanism in your app for cleaning up notifications that are no longer relevant – like 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, so you could certainly devise an encoding scheme to create such a mapping.

Finding a notification with a given id requires traversing the list of notifications, which you can obtain via a call to GetScheduledTileNotifications or GetScheduledToastNofifications, and then checking each of the notification ids against whatever encoding scheme you’ve devised. A matching notification can be easily removed 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.

The APIs

Constructing the Notification

You’ll use one of two classes for the notification – one for tile and one for toast; each of the class constructors expects two parameters: a completed notification template (see the previous post for a primer) and the localized notification delivery time.

A ScheduledTileNotification includes two additional properties over its local counterpart

  • id is used as a key to identify a given scheduled notification in the list of pending notifications; it’s a string of your choosing of up to 16 characters that you’d use to find a to-be-delivered notification for deletion or modification.
  • deliveryTime (readonly) is the time the notification will occur, expressed relative to Coordinated Universal Time (UTC) and is set using local time semantics when the class is constructed, having been provided as the second argument to the constructor

Each ScheduledToastNofitication likewise includes id and deliveryTime properties, but it also offers ‘snooze’ settings, to provide up to five repetitions of the toast at a defined interval:

  • maximumSnoozeCount is the maximum number of times the toast will appear – up to five – and is set when the notification is created,
  • snoozeInterval is the amount of time that should elapse between each showing of the toast (up to the maximumSnoozeCount), the range is from one minute to on hour, inclusive, and also set when the notification is created.

Scheduling the Notification

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 task in conjunction with notifications.

Clearing the Notification

Once the scheduled notification has ‘hit’, 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 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 or have otherwise been overcome by events. I’ve already broached that subject in the design consideration section above, but here’s a itemization of the key API classes and properties you’d leverage to do so:

  • the id property of a ScheduledToastNotification or ScheduledTileNotification can be set to an meaningful string (of up to 16 characters) to get a handle to a notification that might be modified. If needed, you could use that id value as a unique index to a persistent data store that records additional context about the notification.
  • use the removeFromSchedule method (on ToastNotifier or TileUpdater) to cancel a pending notification that you’ve identified should no longer be delivered.

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 itself 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:

  • allTasks is a collection (a static dictionary to be exact) of the background tasks that the application has registered, via a call to BackgroundTaskBuilder.register
  • since each task has a name property assigned at creation, you can identify the specific task of interest by testing each of the elements of the allTasks collection for the name you assigned to the background task when it was initially registered.
  • when the background task to be cancelled has been identified, pass its reference to unregister along with a Boolean parameter indicating whether you want any currently running instances of the task to be aborted as well. In the context of scheduling a notification, not cancelling it is reasonable. Just be aware that one last notification might have gotten scheduled, but if you cancel the task first and then removeFromSchedule any last second additional notifications, you should be all set.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jim_O'Neil
Software Developer (Senior) Microsoft
United States United States
Member
Jim is a Technology Evangelist for Microsoft who covers the Northeast District, namely, New England and upstate New York. He is focused on engaging with the development community in the area through user groups, code camps, BarCamps, Microsoft-sponsored events, and on-line. Currently Jim's focus is on mobile applications and their integration with cloud services.
 
Jim joined Microsoft in April 2008 after nearly 12 years working for Sybase in a support and sales consultant role for its developer tools, specifically PowerBuilder and EAServer. Prior to that he worked on various DoD projects at MITRE (Bedford, MA) and BDM International (in McLean, VA, now subsumed by Northrop Grumman). Jim received a B.S. in Mathematics and Computer Science from Austin Peay State University and his M.S. in Computer Science from Duke University.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 30 Aug 2012
Article Copyright 2012 by Jim_O'Neil
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid