Windows 8.1

Building an Alarm App in Windows 8.1

Tony Champion

Among the hundreds of new features in Windows 8.1 is the concept of an alarm app. In a nutshell, an alarm app is a Windows Store app that can schedule toast notifications to the second. Due to the way Windows processes toasts, this isn’t an accuracy offered to most apps. In this article, I’ll explore the concept of an alarm app and look at what it takes to develop one of your own.

What Is an Alarm App?

Before looking under the hood of an alarm app, it’s important to consider what type of apps would make good alarm apps. The key is to consider the accuracy of delivering notifications. For example, it isn’t necessary for a calendar app to notify the user of a friend’s birthday at an exact second. However, there are several types of apps that do require this accuracy.

The most obvious choice is a good old-fashioned alarm clock app. When a user sets an alarm, your app needs to notify the user at that moment. You can now create more accurate time-management apps, such as a Pomodoro app, with an alarm app. An alarm app could also be used in short interval workouts, such as Tabata, where the timing of rounds and rests is extremely important.

All Windows Store app developers should be familiar with the Windows 8 concept of lock screen apps. Apps that are placed on the lock screen are allowed to post updates to the lock screen. In addition, a lock screen app has access to more capabilities than a typical app. This is important when your app needs to do things such as update the lock screen or run many of the available background tasks.

The need for the additional capabilities in lock screen apps is a direct result of changes in Windows 8 to improve performance and battery life. Windows is designed to prevent apps from running when they aren’t being used and to consolidate tasks when possible. For this reason, you’ll find scheduled events, such as background tasks and notifications, will always run at an approximate time. Windows batches these updates and runs them when it has a process ready to do the work.

In Windows 8 you could define up to seven apps to be on the lock screen at any given time. Included in these seven slots was a special slot for a detailed status app. A device might have seven lock screen apps that can display badges or text, but only one app that’s able to provide a custom UI to the lock screen. Windows 8.1 keeps this setup and adds the alarm app as a special new type of lock screen app. Figure 1 shows the new “Lock screen apps” settings part of the PC settings screen. Like the detailed status app, each device can only have a single alarm app at a time.

Lock Screen Part of PC Settings
Figure 1 Lock Screen Part of PC Settings

The sole difference between an alarm app and other lock screen apps is the ability to provide alarm toast notifications to the user within a second of the scheduled delivery time. As previously mentioned, submitting or scheduling a toast in a Windows Store app doesn’t guarantee when that toast will be delivered. It’s delivered in an approximate time frame, but the exact time is up to Windows. If an app is identified by the user as the alarm app, scheduled toasts are delivered exactly on time.

Setting Up an Alarm App

Before an app can be selected as an alarm app, the app manifest must be properly configured. If the manifest doesn’t include the required features, then attempting to set the app as the alarm app in code will generate an error and the user won’t have the option to set the app manually.

Because an alarm app schedules toasts, you first need to enable toasts. You can do this in the manifest designer in the Application UI tab. A toast-capable dropdown box can be found in the Notifications section under Visual Assets. The Notifications section can be found under All Image Assets as well as the Badge Logo subgroup. To enable toasts for the app, you should set the toast-capable dropdown to Yes.

The other property in the Notifications section is the ability to enable lock screen notifications for the app. As mentioned earlier, the alarm app is a special type of lock screen app; therefore the app must be configured to be on the lock screen. You should set the lock screen notifications dropdown to either Badge or Badge and Tile Text.

Once you’ve enabled lock screen notifications on an app, the manifest needs to have a few additional items. For example, a badge logo must be assigned to the app. The logo is required to be a 24x24 pixel image, and like all logos in a Windows Store app, you can specify various-scale sizes to handle Windows resolution scaling. Figure 2 shows an example of the manifest designer with toasts and lock screen notifications enabled.

Notifications Section of the Manifest Designer
Figure 2 Notifications Section of the Manifest Designer

Any app that has lock screen notifications enabled must also declare a background task in the app manifest. The interesting part of this requirement is that you don’t need to actually implement a background task in a lock screen app; it just has to be declared.

A background task is declared in the Declarations section of the app manifest designer. In the Available Declarations, select Background Tasks and click Add. The background task for a lock screen app must support one of the following task types: Control channel, Timer, Push notification or Location. In the App settings section of the background task, you must set either the Entry point or Start page value. In a XAML app that’s using the background task, the Entry point is set to the class that implements the IBackgroundTask interface. If the app isn’t actually implementing a background task, the value can be set to anything. Figure 3 shows a properly configured background task to enable an app to be added to the lock screen.

Configuring a Background Task
Figure 3 Configuring a Background Task

The final step in configuring the app manifest is to identify the app as an alarm app. You do this by adding an alarm extension in the manifest. Unfortunately, it isn’t possible to add this extension through the manifest designer; it must be done by hand. In order to do that, you must first get to the underlying XML of the package manifest. Do this by right-clicking package.appxmanifest in the Solution Explorer and selecting View Code.

The XML in a Windows 8.1 app manifest will use two namespaces. The first namespace (which is the default) contains the elements defined in Windows 8. The second namespace must be added and is identified by the m2 prefix. It includes additions and changes added in Windows 8.1. Because the alarm app feature is new to Windows 8.1, you need to add an “8.1” extension to the Extensions collection within the Application element. The Category property of the new extension should be set to windows.alarm. Here’s an example of what the Extensions collection should look like with the new extension and the previously declared background task:

<Extensions>
  <Extension Category="windows.backgroundTasks" 
      EntryPoint="App">
    <BackgroundTasks>
      <Task Type="timer" />
    </BackgroundTasks>
  </Extension>
  <m2:Extension Category="windows.alarm" />
</Extensions>

Requesting Alarm Access

Once the appropriate settings and declarations have been made, your app can then request access to be set as the alarm app for the device. The user can do this manually from the PC Settings; however, your app can request access through the Windows Runtime (WinRT).

The Windows Runtime includes a static AlarmApplicationManager class in the Windows.ApplicationModel.Background namespace. This class has a RequestAccessAsync method that will prompt the user for permission to set the app as the device alarm app, as shown in Figure 4. If a different app is currently identified as the alarm app, it will be replaced by the current one if the user selects Yes when prompted.

An Alarm App Permission Prompt
Figure 4 An Alarm App Permission Prompt

The RequestAccessAsync method returns an AlarmAccessStatus enum that has three valid values: Denied, AllowedWithWakeup­Capability and AllowedWithoutWakeupCapability. This is impor­tant if you’re creating alarm apps for things such as morning wakeup alarms. If the device is in sleep mode and it isn’t configured to allow toast notifications to wake it, then your alarms won’t fire.

It’s important to remember that Windows 8 puts the user in control of a device. As shown in Figure 1, a user can easily change the alarm app. Your challenge is that each app can only request access from the AlarmApplicationManager once. If the app makes a second request for access—for this user and device—it won’t prompt the user and will only return the current alarm status of the app. Once your app has been denied, replaced by a different app or manually removed by the user, your only option is to inform the user that the app needs to be manually added back as the alarm app for the device.

The AlarmApplicationManager also includes a GetAccessStatus method that returns the current alarm status of the machine. As with the RequestAccessAsync method, it returns an AlarmAccessStatus enum and is a great way to determine what’s going on with the device. For example, your app could inform the user if notifications won’t wake up the device.

Scheduling Alarms

Alarms are actually just a scheduled toast notification with a little more kick. The process of scheduling an alarm is identical to scheduling a toast notification, the only difference being the notification XML. The XML used to define a notification will contain information about its appearance as well as any included features.

A toast can be either just text or a combination of text and an image, as defined by one of the templates provided by the Windows Runtime. There are currently eight different XML templates from which you can choose. As of this writing, Windows 8.1 doesn’t support custom toast layouts, so you must select from one of the provided templates.

The type and layout of a toast is defined in a block of XML. The XML identifies the toast template to use, the text and image with which to populate the template, and several other options that I’ll discuss later. Here’s an example of a basic toast notification:

<toast duration="long">
  <visual>
    <binding template="ToastText02">
      <text id="1">Sample Toast App</text>
      <text id="2">The is a sample message.</text>
    </binding>
  </visual>
</toast>

There are several ways to generate the toast template. The Windows Runtime will create an XmlDocument of each template from the ToastNotificationManager, which can be found in the Windows.UI.Notification namespace. The ToastNotificationManager has a static GetTemplateContent method that takes a ToastTemplateType enum that has a value for each of the available templates. Here’s an example of how to get an XmlDocument of the previous example:

XmlDocument content =
  ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
content.DocumentElement.SetAttribute("duration", "long");
var textLines = content.GetElementsByTagName("text");
textLines[0].InnerText = "Sample Toast App";
textLines[1].InnerText = "The is a sample message.";

This is a great starting point; however, depending on your usage, it can be a bit cumbersome. This is why any additions or modifications to the template will normally be done using the XmlDocument API. This can lead to quite a few lines of code for a few simple additions. With this in mind, it isn’t uncommon to find the XML built up as a string and then loaded into an XmlDocument once the template is complete. Figure 5 shows how to achieve the equivalent of the previous example by generating the XML as a string.

Figure 5 Generating XML As a String

string textLine1 = "Sample Toast App";
string textLine2 = "This is a sample message.";
string contentString =
  "<toast duration=\"long\">\n" +
    "<visual>\n" +
      "<binding template=\"ToastText02\">\n" +
        "<text id=\"1\">" + textLine1 + "</text>\n" +
        "<text id=\"2\">" + textLine2 + "</text>\n" +
      "</binding>\n" +
    "</visual>\n" +
  "</toast>\n";
XmlDocument content = new Windows.Data.Xml.Dom.XmlDocument();
content.LoadXml(contentString);

If you’re going this route, you should be careful of two things. First, you must make sure you’re generating properly formatted XML—take care to escape any special characters that might be included in the string. Second, make sure you follow the schema of the toast notification. The Windows Dev Center provides the full specifications for the schema at bit.ly/172oYCO.

All of the previous examples have one element that isn’t part of the default template. You might have noticed the duration attribute on the toast element has been set to long. Because you’re creating alarm toast notifications, you don’t want the alarm to appear and then vanish without user interaction. Setting the duration to long will keep the toast on the screen for up to 25 seconds.

Once you have your XML configured and loaded into an XmlDocument, you can schedule your toast. The first step is to create an instance of a ScheduledToastNotification. You need two things to create a ScheduledToastNotification: the XmlDocument containing the toast definition and a time for the toast to be scheduled.

The ScheduledToastNotification is scheduled with a ToastNotifier. An instance of a ToastNotifier is created from the ToastNotification­Manager class using the static CreateToastNotifier method. A call to the ToastNotifier AddToSchedule method will then schedule your toast to be delivered. Toasts typically are created as the result of some user action, such as pressing a button, or an event that’s raised within the app. Here’s an example of creating and scheduling a toast for 1 minute from the current time:

ToastNotifier toastNotifier =
  ToastNotificationManager.CreateToastNotifier();
var scheduledToast = new ScheduledToastNotification(
  content, DateTime.Now.AddMinutes(1));
toastNotifier.AddToSchedule(scheduledToast);

The resulting toast that’s generated can be seen in Figure 6. Notice it should look like most toasts you’ve seen in Windows.

A Basic Toast Notification
Figure 6 A Basic Toast Notification

A toast notification might fail for a few different reasons. The most frequent reason is that the XML is improperly formatted. This can be caused by having an incorrect template id or not defining all of the required attributes, so it’s important to make sure you get the XML right.

If you attempt to schedule a toast for a time that has already passed, an exception will be thrown during the AddToSchedule call. If you’re scheduling a toast for a few seconds in the future, make sure the time calculation is one of the last things you do. Setting a time for 2 seconds from now and then taking 4 seconds to execute code before actually scheduling that toast will throw an exception.

Finally, your app can only have 4,096 toasts scheduled at a time. I know your first thought is, “no way that will happen,” but for an alarm app it’s easier to do than you might think. Suppose you have an alarm app that allows the user to schedule a daily alarm. If your code schedules multiple daily alarms for each day for the next year, then 12 daily alarms will max you out. This means you need to make sure your algorithms for scheduling alarms are thought out and that you manage the alarms once they’re created.

Managing and Removing Alarms

To successfully build an alarm app, you need to have the ability to review and remove any scheduled alarms. The ToastNotifier can accomplish both of these tasks. Calling the GetScheduledToastNotifications method will return a read-only list of ScheduledToastNotifications. The collection will only contain scheduled notifications for the current app.

To remove a scheduled notification, the notification to be removed should be passed to the RemoveFromSchedule method. Between these two methods, you can maintain your scheduled notifications. Once a notification has been posted and then dismissed by the user, it will no longer appear in the app’s collection of notifications and won’t count toward the maximum number of allowed scheduled notifications. Here’s how to clear out all of the scheduled notifications:

var toastNotifier = ToastNotificationManager.CreateToastNotifier();
var notifications = toastNotifier.GetScheduledToastNotifications();
// Remove each notification from the schedule
foreach (var notification in notifications)
{
  toastNotifier.RemoveFromSchedule(notification);
}

You could put this code in a command or event handler tied to a Clear All button, for example.

Adding Commands

If your app is currently the alarm app for the device, then the previous example that generated the toast shown in Figure 6 will display on time, but Figure 6doesn’t look much like an alarm, does it? Primarily, you’re missing a couple of common features for an alarm: snooze and dismiss. By default, clicking on the toast or swiping it will dismiss it; however, an alarm needs to be a bit more intuitive.

In addition to the <toast> element supporting a <visual> child element, it also supports a <commands> element. This element allows you to add predefined commands to the toast. The element itself supports a single optional scenario attribute. The scenario attribute can be set to either alarm or incomingCall. For my purpose here, it will always be set to alarm.

The <commands> element contains a collection of individual <command> elements. Each command must have an id attribute identifying what type of command it is. For an alarm, this must be either snooze or dismiss. By adding a commands section to your previous toast, your toast now looks a bit more like an alarm and has the ability to not only be dismissed but to snooze as well. Here’s the newly generated toast code (you can see the results of this code in Figure 7):

<toast duration="long">
  <visual>
    <binding template="ToastText02">
      <text id="1">Sample Toast App</text>
      <text id="2">The is a sample message.</text>
    </binding>
  </visual>
  <commands scenario="alarm">
    <command id="snooze"/>
    <command id="dismiss"/>
  </commands>
</toast>

An Alarm Toast Notification
Figure 7 An Alarm Toast Notification

Setting the Snooze

By default, Windows sets the snooze time for an alarm at 9 minutes. However, you can define the duration of the snooze in the ScheduledToastNotification class. This class has a second constructor with two additional parameters. The first is the length of time for the snooze. The snooze interval is defined as a TimeSpan and can range anywhere from 1 to 60 minutes.

The second new parameter is the maximum number of times the user can hit the snooze on the alarm. Setting this value to zero will allow the user to hit the snooze an unlimited amount of times. Here’s an example of setting the snooze frequency:

DateTime scheduledTime = DateTime.Now.AddMinutes(1);
TimeSpan snoozeInterval = TimeSpan.FromMinutes(5);
var scheduledToast = new ScheduledToastNotification(
  content, scheduledTime, snoozeInterval, 0);

Changing the Alarm Sound

If the user has enabled sound for notifications, then each toast will make the same “ding” sound when a toast message is displayed. This causes a few problems when it comes to creating an alarm app. First, the user gets used to hearing the same sound for all notifications. This means an alarm can fade into the noise of the other notifications and not stand out. The second issue is that usually an alarm continues to make sound until the user acknowledges it. Therefore, you want an alarm to have some type of looping sound.

Fortunately, the toast definition also supports an <audio> element that allows you to customize the sound made when the toast appears. The <audio> element has two attributes: src and loop. Before you get too excited, the value of the src attribute must be one of the predefined values supplied by Windows. This means you can’t provide custom audio for your toast notifications, but you do have a decent collection of sounds from which to choose.

The value of src must be one of 25 predefined values. The sounds are broken up into looping and non-looping categories. The looping sounds are constructed to seamlessly loop and should be used when creating a looping audio notification. There are 10 alarm looping sounds and 10 incoming call looping sounds provided. A complete list of the predefined values can be found at bit.ly/16HV2xm.

If you want to play a looping sound, the loop attribute must be set to true. In addition, the duration attribute on the <toast> element must be set to long in order to give the sound time to play. Figure 8 shows an example of setting a custom looping audio sound for your toast.

Figure 8 Setting a Custom Looping Audio Sound for a Toast

<toast duration="long">
  <visual>
    <binding template="ToastText02">
      <text id="1">Sample Toast App</text>
      <text id="2">The is a sample message.</text>
    </binding>
  </visual>
  <commands scenario="alarm">
    <command id="snooze"/>
    <command id="dismiss"/>
  </commands>
  <audio src="ms-winsoundevent:Notification.Looping.Alarm2"
     loop="true" />
</toast>

If you don’t want your toast to play any sound, you can set a silent attribute to true. This will override any default settings on displaying toasts. Figure 9 shows how it’s used.

Figure 9 Setting the Silent Attribute So a Toast Doesn’t Play Any Sound

<toast duration="long">
  <visual>
    <binding template="ToastText02">
      <text id="1">Sample Toast App</text>
      <text id="2">The is a sample message.</text>
    </binding>
  </visual>
  <commands scenario="alarm">
    <command id="snooze"/>
    <command id="dismiss"/>
  </commands>
  <audio silent="true" />
</toast>

Thinking Beyond Your App

You can take an alarm app in many different directions. Because each device can only have a single alarm app, it’s important to think beyond your app. If the scope of your app is too limited, then the user might replace it with a different app. This, of course, depends on the purpose for your app and its target audience. Consider things such as using the Share Target contract to allow other apps to schedule alarms through your app.

With the addition of the alarm app feature in Windows 8.1, you can now create a wide range of time-based apps with the accuracy expected by the user. I’ve shown what it takes to get you up and running with an alarm app. Now, no more hitting the snooze button. Go out and create the next amazing alarm app!


Tony Champion is president of Champion DS and is a Microsoft MVP. He’s active in the community as a speaker, blogger and author. He maintains a blog at tonychampion.net and can be reached via e-mail at tony@tonychampion.net.

Thanks to the following technical expert for reviewing this article: Pete Brown (Microsoft)
Pete Brown is a program manager in the Client and Devices evangelism team, focusing on XAML and modern apps across all Windows devices. His focus is on helping developers build beautiful, high-quality, apps that enable creativity. He's on twitter at @pete_brown and on the web at 10rem.net.

 

Rate: