Windows Phone 8 Succinctly: Tiles, Notifications, and Multitasking

In this tutorial, we're going to focus on live apps. Live apps are one of the core concepts in Windows Phone development, and to properly create a quality experience, many factors are involved, like notifications, agents, and Tiles.

The Multitasking Approach

As we’ve seen in the application life cycle discussed earlier in this series, applications are suspended when they are not in the foreground. Every running process is terminated, so the application can’t execute operations while in the background.

There are three ways to overcome this limitation:

  • Push notifications, which are sent by a remote service using an HTTP channel. This approach is used to send notifications to users, update a Tile, or warn users that something has happened.
  • Background agents, which are services connected to our application that can run from time to time under specific conditions. These services can also be used for push notification scenarios—in this case, remote services are not involved—but they can also perform other tasks as long as they use supported APIs.
  • Alarms and reminders, which display reminders to the user at specific dates and times.

Let’s see in detail how they work.

Push Notifications

Push notifications are messages sent to the phone that can react in many ways based on the notification type. There are three types of push notifications:

  • Raw notifications can store any type of information, but they can be received only if the associated application is in the foreground.
  • Toast notifications are the most intrusive ones, since they display a message at the top of the screen, along with a sound and a vibration. Text messages are a good example of toast notifications.
  • Tile notifications can be used to update the application’s Tile.

There are three factors involved in the push notification architecture:

  • The Windows Phone application, which acts as a client to receive notifications.
  • The server application, which can be a web application or a service, that takes care of sending the notifications. Usually, the server stores a list of all the devices that are registered to receive notifications.
  • The Microsoft Push Notification Service (MPNS), which is a cloud service offered by Microsoft that is able to receive notifications from the server application and route them to the Windows Phone clients.
Microsofts Push Notification Architecture

Every Windows Phone application receives push notifications using a channel, which is identified by a unique URI. The server application will send notifications to the registered clients by sending an XML string to this URI using a POST command. The MPNS will take care of routing the requests to the proper devices.

Here is a sample of a URI that represents a channel:

Note: MPNS usage is free, but limited to 500 notifications per day per single device. If you need to exceed this limitation, you have to buy a TLS digital certificate, which you’ll need to submit during the certification process and to digitally sign your server’s application. This way, you’ll also be able to support SSL to encrypt the notification’s channel.

Sending a Notification: The Server

As already mentioned, notifications are sent using an HTTP channel with a POST command. The benefit is that it relies on standard technology, so you’ll be able to create a server application with any development platform.

The HTTP request that represents a notification has the following features:

  • It’s defined using XML, so the content type of the request should be text/xml.
  • A custom header called X-WindowsPhone-Target, which contains the notification’s type (toast, Tile, or raw).
  • A custom header called X-NotificationClass, which is the notification’s priority (we’ll discuss this more in-depth later).

Let’s see how the different push notifications are structured in detail.

Toast Notifications

The following sample shows the XML needed to send a toast notification:

There are three parameters to set:

  • wp:Text1 is the notification’s title.
  • wp:Text2 is the notification’s text.
  • wp:Param is the optional notification deep link; when this is set, the application is opened automatically on the specified page with one or more query string parameters that can be used to identify the notification’s context.

When you prepare the request to send over HTTP, the X-WindowsPhone-Target header should be set to toast, while the X-NotificationClass header supports the following values:

  • 2 to send the notification immediately.
  • 12 to send the notification after 450 seconds.
  • 22 to send the notification after 900 seconds.
A Toast Notification

Tile Notifications

Tile notifications are used to update either the main Tile or one of the secondary Tiles of the application. We won’t describe the XML needed to send the notification here: Tiles are more complex than the other notification types since Windows Phone 8 supports many templates and sizes. We’ll look at the XML that describes Tile notifications later in the Tiles section of the article.

To send a Tile notification, the X-WindowsPhone-Target header of the HTTP request should be set to tile, while the X-NotificationClass header supports the following values:

  • 1 to send the notification immediately.
  • 11 to send the notification after 450 seconds.
  • 21 to send the notification after 900 seconds.

Raw Notifications

Raw notifications don’t have a specific XML definition since they can deliver any kind of data, so we can include our own definition.

To send a raw notification, the X-WindowsPhone-Target header of the HTTP request should be set to raw, while the X-NotificationClass header supports the following values:

  • 3 to send the notification immediately.
  • 13 to send the notification after 450 seconds.
  • 23 to send the notification after 900 seconds.

Sending the Request and Managing the Response

The following sample code shows an example of how to send a toast notification using the HttpWebRequest class, one of the basic .NET Framework classes for performing network operations:

The XML definition is simply stored in a string. We’re going to change just the node values that store the notification’s title and text. Then, we start to prepare the HTTP request by using the HttpWebRequest class. We add the custom headers, define the content’s length and type (text/xml), and specify the method to use (POST).

In the end, by using the GetRequestStream() method, we get the stream location to write the request’s content, which is the notification’s XML. Then we send it by calling the GetResponse() method, which returns the status of the request. By analyzing the response we are able to tell whether or not the operation was successful. 

The response’s analysis involves the status code and three custom headers:

  • The response’s status code returns generic information that tells you whether the request has been received. It’s based on the standard HTTP status codes. For example, 200 OK means that the request has been successfully received, while 404 Not Found means that the URI was invalid.
  • The X-NotificationStatus header tells you if the MPNS has received the request using the values Received, Dropped, QueueFull, and Supressed.
  • The X-DeviceConnectionStatus header returns the device status when the request is sent: Connected, Inactive, Disconnected, or TempDisconnected.
  • The X-SubscriptionStatus header returns if the channel is still valid (Active) or not (Expired). In the second case, we shouldn’t try to send it again, since it doesn’t exist anymore.

The combination of these parameters will help you understand the real status of the operation. The MSDN documentation features descriptions of all the possible combinations.

It’s important to correctly manage the notifications because MPNS doesn’t offer any automatic retry mechanism. If a notification is not delivered, MPSN won’t try again to send it, even if the operation failed for a temporary reason (for example, the device wasn’t connected to the Internet). It’s up to you to implement a retry mechanism based on the response.

PushSharp: A Push Notification Helper Library

As you can see, sending push notifications is a little bit tricky since it requires you to manually set headers, XML strings, etc. Some developers have worked on wrappers that hide the complexity of manually defining the notification by exposing high-level APIs so that you can work with classes and objects.

One of the most interesting wrappers is called PushSharp, which can be simply installed on your server project using NuGet. The biggest benefits of this library are:

  • It’s a generic .NET library that supports not only Windows Phone, but the most common platforms that use push notifications, like Windows Store apps, iOS, Android, and Blackberry. If you have a cross-platform application, it will make your life easier in managing a single-server application that is able to send notifications to different kinds of devices.
  • It’s totally compatible with Windows Phone 8, so it supports not only toast and raw notifications, but also all the new Tile templates and sizes.

The following sample shows how simple it is to send a toast notification using this library:

Every notification type is represented by a specific class, which exposes a property for every notification feature. In the previous sample, the WindowsPhoneToastNotification class offers properties to set the notification’s title, text, and deep link.

The channel URI location to send the notification is set in the EndPointUrl property. Once everything is set, you can send it by creating a PushBroker object, which represents the dispatcher that takes care of sending notifications. First, you have to register for the kind of notifications you want to send. Since we’re working with Windows Phone, we use the RegisterWindowsPhoneService() method. Then, we can queue the notification by simply passing it to the QueueNotification() method. It will be automatically sent with the priority you’ve set.

The approach is the same if you want to send a Tile. You have three different classes based on the Tile’s template, WindowsPhoneCycleTileNotification, WindowsPhoneFlipTileNotification, and WindowsPhoneIconicTileNotification; or WindowsPhoneRawNotification for a raw notification.

In the end, the PushBroker class exposes many events to control the notification life cycle, like OnNotificationSent which is triggered when a notification is successfully sent, or OnNotificationFailed which is triggered when the sending operation has failed.

Receiving Push Notifications: The Client

The base class that identifies a push notification channel is called HttpNotificationChannel and exposes many methods and events that are triggered when something connected to the channel happens.

Note: To receive push notifications you’ll need to enable the ID_CAP_PUSH_NOTIFICATION capability in the manifest file.

Every application has a single unique channel, identified by a keyword. For this reason, it should be created only the first time the application subscribes to receive notifications; if you try to create a channel that already exists, you’ll get an exception. To avoid this scenario, the HttpNotificationChannel class offers the Find() method, which returns a reference to the channel.

In the previous sample, the channel is created only if the Find() method fails and returns a null object. The HttpNotificationChannel class exposes many methods to start interacting with push notifications; they should be called only if the channel doesn’t already exist. In the sample we see the Open() method which should be called to effectively create the channel, and which automatically subscribes to raw notifications. 

If we want to be able to receive toast and Tile notifications, we need to use two other methods offered by the class: BindToShellToast() and BindToShellTile(). The following sample shows a complete initialization:

Beyond offering methods, the HttpNotificationChannel class also offers some events to manage different conditions that can be triggered during the channel life cycle.

The most important one is called ChannelUriUpdated, which is triggered when the channel creation operation is completed and the MPNS has returned the URI that identifies it. This is the event in which, in a regular application, we will send the URI to the server application so that it can store it for later use. It’s important to subscribe to this event whether the channel has just been created, or already exists and has been retrieved using the Find() method. From time to time, the URI that identifies the channel can expire. In this case, the ChannelUriUpdated event is triggered again to return the new URI.

The following sample shows a full client initialization:

As you can see, the ChannelUriUpdated event returns a parameter with the ChannelUri property, which contains the information we need. In the previous sample, we just display the URI channel to the user.

There are two other events offered by the HttpNotificationChannel class that can be useful:

  • HttpNotificationReceived is triggered when the application has received a raw notification.
  • ShellToastNotificationReceived is triggered when the application receives a toast notification while it is open. By default, toast notifications are not displayed if the associated application is in the foreground.

The HttpNotificationReceived event receives, in the parameters, the object that identifies the notification. The content is stored in the Body property, which is a stream since raw notifications can store any type of data. In the following sample, we assume that the raw notification contains text and display it when it’s received:

The ShellNotificationReceived event, instead, returns in the parameters a Collection object, which contains all the XML nodes that are part of the notification. The following sample shows you how to extract the title and the description of the notification, and how to display them to the user:

Managing Errors

If something goes wrong when you open a notification channel, you can subscribe to the ErrorOccurred event of the HttpNotificationChannel class to discover what’s happened.

The event returns a parameter that contains information about the error, like ErrorType, ErrorCode, ErrorAdditionalData, and Message.

The following list includes the most common conditions that can lead to a failure during the channel opening:

  • To preserve battery life and performance, Windows Phone limits the maximum number of channels that are kept alive at the same time. If the limit has been reached and you try to open a new channel, you’ll get the value ChannelOpenFailed as ErrorType.
  • The received notification can contain a message which is badly formatted; in this case the ErrorType will be MessageBadContent.
  • You can send too many notifications at the same time; in this case, they are rejected with the NotificationRateTooHigh error.
  • To preserve battery power, notifications can be received only if the battery isn’t critical; in this case, you’ll get a PowerLevelChanged error.

The ErrorAdditionalData property can contain additional information about the error. For example, if you get a PowerLevelChanged error, you’ll be informed of the current battery level (low, critical, or normal).

Background Agents

Push notifications are the best way to interact with the user when the application is not running since they offer the best experience and, at the same time, preserve battery life. However, the experience is limited to notifications: you can’t execute any other operation, like fetching data from a web service or reading a file from the local storage. Moreover, for certain scenarios in which you don’t require instant notifications, creating the required server infrastructure can be too expensive. Think, for example, of a weather application: it’s not critical that the forecast is updated immediately when the forecasts change.

For all these scenarios, Windows Phone 7.5 has introduced background agents, which are special services periodically executed by Windows Phone, even when the application is not running. There are two types of periodic background agents: periodic and audio. In the New Project section of Visual Studio, you’ll find many templates for all the supported agent types. In this section we’ll see how periodic agents work in detail.

Tip: Even if a background agent is a separate Visual Studio project, it shares the same resources with the foreground application. For example, they share the same local storage, so you’re able to read data created by the application in the agent, and vice versa.

Agent Limits

There are some limitations that background agents have to satisfy. The most important one is connected to timing, since agents can run only in a specific time frame for a limited amount of time. We’ll discuss this limitation later since there are some differences according to the background agent type you’re going to use.

The first limitation concerns supported APIs: only a limited number of APIs can be used in a background agent. Basically, all the APIs that are related to the user interface are prohibited since agents can’t interact with the application interface. You can find the complete list of unsupported APIs in the MSDN documentation.

The second limitation is about memory: a background agent can’t use more than 11 MB of memory, otherwise it will be terminated. It’s important to highlight that during the testing process (when the Visual Studio debugger is attached), the memory limit will be disabled, and the background agent won’t be terminated if it has used more than 11 MB. You’ll have to test it in a real environment if you want to make sure the limit isn’t reached.

The third and final limitation is about timing: a background agent is automatically disabled 14 days after it has been initialized by the connected application. There are two ways to overcome this limitation:

  • The user keeps using the application; the agent can be renewed for another 14 days every time the application is opened.
  • The agent is used to send notifications to update the main application’s Tile or the lock screen; every time the agent sends a notification it will be automatically renewed for another 14 days.

It’s important to keep in mind that if the background agent execution consecutively fails twice (because it exceeded the memory limit or raised an unmanaged exception), it’s automatically disabled; the application will have to reenable it when it’s launched.

Periodic Agents

Periodic agents are used when you need to execute small operations frequently. They are typically executed every 30 minutes (the execution interval can sometimes be shortened to every 10 minutes to coincide with other background processes to save battery life), and they can run for up to 25 seconds. Users are able to manage periodic agents from the Settings panel and disable the ones they don’t need. Periodic agents are automatically disabled if the phone is running in Battery Saver mode; they’ll be automatically restored when sufficient battery power is available.

Periodic agents are identified by the PeriodicTask class, which belongs to the Microsoft.Phone.Scheduler namespace.

Resource Intensive Agents

Resource intensive agents have been created for the opposite scenario: long-running tasks that are executed occasionally. They can run for up to 10 minutes, but only if the phone is connected to a Wi-Fi network and an external power source.

These agents are perfect for tasks like data synchronization. In fact, they are typically executed during the night, when the phone charging. Other than the previous conditions, in fact, the phone shouldn’t be in use. The lock screen should be activated and no other operations (like phone calls) should be performing.

Resource intensive agents are identified by the ResourceIntensiveTask, which is also part of the Microsoft.Phone.Scheduler namespace.

Creating a Background Agent

As already mentioned, background agents are defined in a project separate from the front-end application. Periodic agents share the same template and architecture, and the Windows Phone application will decide to register them as PeriodicTask or ResourceIntensiveTask objects.

To create a background agent, you’ll have to add a new project to the solution that contains your Windows Phone application. In the Add New Project window you’ll find a template called Windows Phone Scheduled Task Agent in the Windows Phone section.

The project already contains the class that will manage the agent; it’s called ScheduledAgent and it inherits from the ScheduledTaskAgent class. The class already implements a method and an event handler.

The method, called OnInvoke(), is the most important one. It’s the method that is triggered when the background agent is executed, so it contains the logic that performs the operations we need. The following sample shows how to send a toast notification from a background agent:

It’s important to highlight the NotifyComplete() method, which should be called as soon as the agent has completed all the operations. It notifies the operating system that the task has completed its job and that the next scheduled task can be executed. The NotifyComplete() method determines the task’s status. If it’s not called within the assigned time—25 seconds for periodic tasks or 10 minutes for resource intensive tasks—the execution is interrupted.

There’s another way to complete the agent’s execution: Abort(). This method is called when something goes wrong (for example, the required conditions to execute the agent are not satisfied) and the user needs to open the application to fix the problem.

The event handler is called UnhandledException and is triggered when an unexpected exception is raised. You can use it, for example, to log the error.

The previous sample shows you how to send local toast notifications. A toast notification is identified by the ShellToast class. You simply have to set all the supported properties (Title, Content, and optionally NavigationUri, which is the deep link). In the end, you have to call the Show() method to display it.

Like remote notifications, local toasts are supported only if the application is in the background. The previous code works only inside a background agent. If it’s executed by a foreground application, nothing happens.

Registering the Agent

The background agent is defined in a separate project, but is registered in the application. The registration should be done when the application starts, or in the settings page if we give users the option to enable or disable it within the application.

The base class to use when working with background agents is ScheduledActionService, which represents the phone’s scheduler. It takes care of registering all the background agents and maintaining them during their life cycle.

The first step is to define which type of agent you want to use. As previously mentioned, the background agent architecture is always the same; the type (periodic or resource intensive) is defined by the application.

In the first case you’ll need to create a PeriodicTask object, and in the second case, a ResourceIntensive task object. Regardless of the type, it’s important to set the Description property, which is text displayed to users in the Settings page. It’s used to explain the purpose of the agent so users can decide whether or not to keep it enabled.

In both cases, background agents are identified by a name, which is passed as a parameter of the class. This name should be unique across all the tasks registered using the PhoneApplicationService class; otherwise you’ll get an exception.

The basic operation to add a task is very simple:

The first operation checks whether the agent is already scheduled by using the Find() method of the ScheduledActionService class, which requires the task’s unique name. This operation is required if we want to extend the agent’s lifetime. If the agent does not exist yet or is not scheduled (the IsScheduled property is false), we first remove it from the scheduler and then add it since the ScheduledActionService class doesn’t offer a method to simply update a registered task. The add operation is done using the Add() method, which accepts either a PeriodicTask or a ResourceIntensiveTask object.

Now the task is scheduled and will be executed when the appropriate conditions are satisfied. If you’re in the testing phase, you’ll find the LaunchForTest() method useful; it forces the execution of an agent after a fixed amount of time. In the previous sample, the agent identified by the name PeriodicTask is launched after five seconds. The LaunchForTest() method can also be executed in the OnInvoke() event inside the background agent, allowing you to easily simulate multiple executions.

In the previous sample you can see that we’ve used conditional compilation to execute the LaunchForTest() method only when the application is launched in debug mode. This way, we make sure that when the application is compiled in release mode for publication to the Windows Store, the method won’t be executed; otherwise, you’ll get an exception if the method is called by an application installed from the Store.

Managing Errors

Background agents are good examples of the philosophy behind Windows Phone:

  • Users are always in control; they can disable whatever background agents they aren’t interested in through the Settings page.
  • Performance and battery life are two crucial factors; Windows Phone limits the maximum number of registered background agents.

For these reasons, the agent registration process can fail, so we need to manage both scenarios. The following code shows a more complete sample of a background agent’s initialization:

The difference in the previous sample is that the Add() operation is executed inside a try / catch block. This way, we are ready to catch the InvalidOperationException error that might be raised.

We can identify the scenario by the exception message:

  • BNS Error: The action is disabled. The user has disabled the agent connected to our application in the Settings page. In this case, we have to warn the user to enable it again in the Settings page before trying to register it.
  • BSN Error: The maximum number of ScheduledActions of this type have already been added. The user has reached the maximum number of agents allowed to be installed on phone. In this case, we don’t have to do anything; Windows Phone will display a proper warning message.
A Background Agent Disabled by the User in the Settings Page

Moreover, the ScheduledTask class (which is the base class that PeriodicTask and ResourceIntensiveTask inherit from) offers some properties for understanding the status of the last execution, such as LastScheduledTime which contains the date and time of the last execution, and LastExitReason which stores the last execution status.

Specifically, LastExitReason is very useful for knowing if the last execution completed successfully (Completed), if it exceeded the memory limit (MemoryQuotaExceeded) or the time limit (ExecutionTimeExceeded), or if an unhandled exception occurred (UnhandledException).

Background Audio Agent

There’s a special kind of background agent that works differently than periodic agents: audio agents, which are used in audio-related applications to keep playing audio when the app is closed. The goal is to offer a similar experience to the native Music + Videos Hub; even when the app is not in the foreground, users are able to keep listening to their music library.

A Background Audio Player

Again, the background agent is defined in a different project than the foreground application. However: 

  • The agent doesn’t need to be initialized in the foreground application using the ScheduledActionService class like we did for periodic agents.
  • There aren’t time limitations. The agent runs every time users interact with the music controls, and it never expires. The only limitation is that the triggered operation should complete within 30 seconds.
  • There is a memory limitation, but the cap is higher: 20 MB (keep in mind that the memory limit isn’t activated when the Visual Studio debugger is connected).
  • In this scenario, the background agent is not just a companion, but the core of the application; it manages all interactions with the music playback, regardless of whether they occur in the foreground application or the native embedded player.

Interacting With the Audio

The core class to reproduce background audio is called BackgroundAudioPlayer, which identifies the built-in Windows Phone audio player. There’s just one instance of the player within the system, and it can’t be shared. If users launch another application that uses a background audio agent (including the native Music + Videos Hub), it takes control over the audio reproduction. As we’re going to see soon, the BackgroundAudioPlayer class is used both in the foreground app and in the background agent to interact with the music playback.

The audio tracks played by a background audio agent are represented by the AudioTrack class. Each track, other than the resource to play, contains all the metadata like the title, artist, and album title.

The track’s path is set in the Source property, which can be either a remote file or a file stored in the local storage. However, most of the properties can be set directly when the AudioTrack object is created, like in the following sample:

With the previous code, in addition to setting the source file, we also immediately set information like the title, the artist, and the album. A useful available property is called PlayerControls, which can be used to set which controls (Play, Pause, Forward, etc.) are available for the track. This way, if you’re developing an application connected to an online radio, for example, you can automatically block options that are not supported (like the skip track button).

Creating the Agent

Visual Studio offers two templates to create background audio agents: Windows Phone Audio Playback Agent and Windows Phone Audio Streaming agent. They share the same purpose; their difference is that the Windows Phone Audio Streaming agent is required for working with media streaming codecs that are not natively supported by the platform.

A background audio agent’s project already comes with a class called AudioAgent, which inherits from the AudioPlayerAgent class. As we saw with periodic agents, the class automatically implements some methods that are used to interact with the agent. The most important ones are OnUserAction() and OnPlayStateChanged().

OnUserAction() is triggered every time users manually interact with the music playback, such as pausing a track or pressing the skip track button in the foreground application or the background player.

The method returns some parameters that can be used to understand the context and perform the appropriate operations:

  • a BackgroundAudioPlayer object, which is a reference to the background audio player
  • an AudioTrack object, which is a reference to the track currently playing
  • a UserAction object, which is the action triggered by the user

The following sample shows a typical implementation of the OnUserAction() method:

Usually with a switch statement, you’ll monitor every supported user interaction, which is stored in the UserAction object. Then, you respond using the methods exposed by the BackgroundAudioPlayer class. Play and Pause are the simplest states to manage; SkipNext and SkipPrevious usually require more logic, since you have to get the previous or next track to play in the list from your library.

Note that background audio agents also require the NotifyComplete() method execution as soon as we’ve finished to manage the operation; it should be called within 30 seconds to avoid termination.

The OnPlayStateChanged() method is triggered automatically every time the music playback state is changed, but not as a direct consequence of a manual action. For example, when the current track ends, the agent should automatically start playing the next track in the list.

The method’s structure is very similar to the OnUserAction() method. In addition to a reference to the background player and the current track in this case, you’ll get a PlayState object, which notifies you about what’s going on.

The following sample shows a typical implementation of the method:

Tip: Background audio agents are not kept in memory all the time, but instead are launched only when the music playback state changes. If you need to persist some data across the different executions, you’ll need to rely on the local storage.

The Foreground Application

We’ve seen how all the main playback logic is managed directly by the background agent. The foreground application, in most of the cases, is just a visual front end for the agent.

To understand the playback state (and to properly update the UI) we need to use, again, the BackgroundAudioPlayer class we’ve seen. The difference is that, in the foreground application, we need to use the Instance singleton to get access to it.

The methods exposed by the class are the same, so we can use it to play, pause, or change the music playback state (for example, if we want to connect these operations to input controls like buttons).

The BackgroundAudioPlayer exposes an important event called PlayStateChanged, which is triggered every time the playback state changes. We can use it to update the visual interface (for example, if we want to display the track currently playing).

The following sample shows how the PlayStateChanged event is used to change the behavior of the play/pause button and to display to some metadata about the currently playing track:

The previous code should be familiar; you have access to all the properties we’ve seen in the background agent, like PlayerState to identify the current playback state, or Track to identify the currently playing track. Track isn’t just a read-only property. If we want to set a new track to play in the application, we can simply assign a new AudioTrack object to the Track property of the BackgroundAudioPlayer instance.

Alarms and Reminders

Alarms and reminders are simple ways to show reminders to users at a specified date and time, as the native Alarm and Calendar applications do.

They work in the same way. The APIs belong to the Microsoft.Phone.Scheduler namespace, and they inherit from the base ScheduledNotification class. There are some properties in common between the two APIs:

  • Content: The reminder description.
  • BeginTime: The date and time the reminder should be displayed.
  • RecurrenceType: Sets whether it’s a recurrent or one-time reminder.
  • ExpirationTime: The date and time a recurrent reminder expires.

Every reminder is identified by a name, which should be unique across all the alarms and reminders created by the application. They work like background agents; their life cycle is controlled by the ScheduledActionService class, which takes care of adding, updating, and removing them.

Alarms are identified by the Alarm class and used when to show a reminder that doesn’t have a specific context. Users will be able to snooze or dismiss it. A feature specific to alarms is that they can play a custom sound, which is set in the Sound property.

The following sample shows how to create and schedule an alarm:

The sample creates an alarm that is scheduled 15 seconds after the current date and time, and uses a custom sound that is an MP3 file inside the Visual Studio project.

Reminders, instead, are identified by the Reminder class and are used when the notification is connected to a specific context, in a similar way that calendar reminders are connected to an appointment.

The context is managed using the NavigationUri property, which supports a deep link. It’s the page (with optional query string parameters) that is opened when users tap the reminder’s title.

The previous code schedules a reminder that opens a page called DetailPage.xaml. Using the navigation events described earlier in this series, you’ll be able to get the query string parameters and load the requested data. Notice also that the Reminder class offers a Title property, which is not supported by alarms.

Live Tiles

Live Tiles are, without a doubt, the most unique Windows Phone feature, and one you won’t find on any other platform. They are called Live Tiles because they aren’t simply shortcuts to open applications; they can be updated with local or remote notifications to display information without forcing users to open the application. Many kinds of applications take advantage of this feature, like weather apps that display the forecast, news apps that display the latest headlines, and movie apps that display upcoming movie titles.

Windows Phone 8 has introduced many new features regarding Tiles, like new templates and new sizes.

An application can use three different sizes for Tiles: small, medium, and wide. As developers, we’ll be able to customize the Tile’s content according to the size so that, for example, the wide Tile can display more info than the small Tile.

Various Tile Sizes

Windows Phone 8 has also introduced three different templates to customize a Tile: flip, cycle, and iconic. It’s important to note that you can choose only one template for your application; it must be declared in the manifest file, in the Application UI section. Once you’ve set it, you won’t be able to change it at run time, and all the Tiles you’re going to create or update will have to use that template. In addition, you can choose the features (Tiles, pictures, etc.) to use for the main Tile in the Application UI section; this information will be used until a notification updates it.

In the following sections we’ll examine every available template in detail. For each one we’ll discuss the architecture and code needed to update it with a notification. For remote notifications, we’ll see the required XML. For local notifications, we’ll look at the APIs to use in the application or in a background agent.

In both cases, all the fields that define a Tile are optional. If you don’t set some of them, those properties will simply be ignored. On the other hand, if a field that was previously set is not updated with a notification, the old value will be kept.

Flip Template

Flip is the standard Windows Phone template, and the only one that was already available in Windows Phone 7. With this template you can display text, counters, and images on the front of the Tile. Periodically, the Tile will rotate or “flip” to show the opposite side, which can display different text or images.

Anatomy of a Tile Using the Flip Template

As you can see from the previous figure, you can customize both front and rear sides of the Tile. If you want to include an image, you have to use one of the following sizes:

  • Small: 159 × 159
  • Medium: 336 × 336
  • Wide: 691 × 336 

A flip template Tile is identified by the FlipTileData class. The following sample shows how to use it to define a Tile that can be managed by code.

The following code shows how the same Tile is represented using the XML definition needed for remote notifications:

Notice the Action attribute that is set for many nodes. If you set it without assigning a value to the node, it will simply erase the previous value so that it reverts to the default.

Cycle Template

The cycle template can be used to create a visual experience similar to the one offered by the Photos Hub. Up to nine pictures can cycle on the front side of the Tile.

Anatomy of a Tile Using the Cycle Template

The cycle template offers fewer ways to customize the Tile than the other two templates since its focus is the images. The image sizes are the same as those used for the flip template:

  • Small: 159 × 159
  • Medium: 336 × 336
  • Wide: 691 × 336

A cycle template is identified by the CycleTileData class, as shown in the following sample:

The following XML can used to send remote notifications to update Tiles based on the cycle template:

Iconic Template

The iconic template is used to create Tiles that emphasize the counter. Many native applications such as Mail, Messaging, and Phone use this template. In this template, the counter is bigger and easier to see.

Anatomy of a Tile Using the Cycle Template

The iconic template features two main differences from the flip and cycle templates. The first is that full size images are not supported; instead, you can specify an icon image, which is displayed near the counter. There are just two images sizes required:

  • Small and Wide Tiles: 110 × 110
  • Medium Tile: 202 × 202

The other difference is that it’s possible to customize the background color (the only way to do this with the other templates is to use an image with the background color you prefer). If you don’t set a background color, the template will automatically use the phone’s theme.

An iconic Tile is represented by the IconicTileData template, as shown in the following sample:

The following sample is the XML representation for remote push notifications in a Tile that uses the iconic template:

Working With Multiple Tiles

The previous code, in addition to being supported in the application or in a background agent to update the main Tile, can also be used to create multiple Tiles—a feature introduced in Windows Phone 7.5. Secondary Tiles behave like the main ones: they can be updated by notifications and moved or deleted from the Start screen.

The difference is that secondary Tiles have a unique ID, which is the Tile’s deep link. The main Tile always opens the application’s main page, while secondary Tiles can open another page of the application and include one or more query string parameters to identify the context. For example, a weather application can create Tiles for the user’s favorite cities, and every Tile will redirect the user to the forecast page for the selected city.

The base class to interact with Tiles is called ShellTile, which belongs to the Microsoft.Phone.Shell namespace.

Creating a secondary Tile is simple: you call the Create() method by passing the Tile’s deep link and the Tile itself, using one of the classes we’ve seen before. The following sample shows how to create a secondary Tile using the flip template:

When the application is opened using this Tile, you’ll be able to understand the context and display the proper information using the OnNavigatedTo method and the NavigationContext class we used earlier in this series.

Note: To avoid inappropriate usage of secondary Tiles, every time you create a new Tile the application will be closed to immediately display it to the user.

Deleting a secondary Tile requires working with the ShellTile class again. It exposes a collection called ActiveTiles, which contains all the Tiles that belong to the application, including the main one. It’s sufficient to get a reference to the Tile we want to delete (using the deep link as an identifier) and call the Delete() method on it.

The previous sample deletes the Tile identified by the deep link /MainPage.xaml?id=1. Unlike when the Tile is created, the application won’t be closed.

Tip: Remember to always check that a Tile exists before removing it. Like every other Tile, in fact, users can also delete one on the main page by tapping and holding Tile and then tapping the Unpin icon.

Tiles can also be updated. Updates can be performed not only by the main application but also in the background by a background agent.

The approach is similar to the one we’ve seen for the delete operation. First we have to retrieve a reference to the Tile we want to update, and then we call the Update() method, passing the Tile object as a parameter. The following sample shows how to update a Tile that uses the flip template:

The Update() method can also be used to update the application’s main Tile. It’s always stored as the first element of the ActiveTiles collection, so it’s enough to call the Update() method on it as in the following sample:

The previous code will always work, even if the main Tile is not pinned to the Start screen. If the user decides to pin it, the Tile will already be updated with the latest notification.

Tip: You can invite users to pin the main Tile on the Start screen, but you can’t force it by code.

Interacting With the Lock Screen

Windows Phone 8 has introduced a new way for applications to interact with users, thanks to the lock screen support. There are two ways to interact with it:

  • Display notifications in the same way the Messaging and Mail apps display the number of unread messages.
  • Change the lock screen image; specifically, the application can become a lock screen provider and occasionally update the image using a background agent.

Let’s see in detail how to support both scenarios.

Notifications

In the Settings page, users can choose up to five applications that are able to display counter notifications, and only one application that is able to display text notifications.

To support both scenarios in our application, we need to manually add a new declaration in the manifest file (remember to use the View code option in the context menu since it’s not supported by the visual editor):

The first extension is used to support counter notifications, while the second one is used for text notifications. You can declare just one of them or both, according to your requirements.

If you want to support counter notifications, there’s another modification to apply to the manifest file: inside the Tokens section, you’ll find the tags that define the main Tile’s basic properties. One of them is called DeviceLockImageURI, which you need to set with the path of the image that will be used as an icon for the notifications.

The image should have the following properties:

  • The supported resolution is 38 × 38.
  • It has to be in PNG format.
  • It can contain only transparent or white pixels. No other colors are supported.

Once your application is set, you don’t have to do anything special to display lock screen notifications. In fact, they are based on Tile notifications, so you’ll be able to update both the Tile and the lock screen with just one notification.

  • If your application supports counter notifications, you need to send a Tile notification with the number stored in the Count property.
  • If your application supports text notifications, you need to send a Tile notification with the text stored in the WideBackContent property for the flip template or the WideContent1 property for an iconic template. The cycle template doesn’t support text notifications.
Lock Screen Notification with Counter and Text

Lock Screen Image

The starting point for supporting lock screen images is, again, the manifest file. The following sample is the declaration that should be added in the Extensions section:

Starting now, your application will be listed as a wallpaper provider in the Settings page. If the user chooses your application as a provider, you’ll be able to update the lock screen image, both from the foreground app and using a background agent.

The APIs allow you to check whether the application has already been set as a provider, or you can ask the user. If the application is set as a provider, you will be able to effectively change the wallpaper; otherwise you’ll get an exception.

Two classes are part of the Windows.Phone.System.UserProfile namespace: LockScreenManager can be used to detect the current provider status, and LockScreen can effectively perform operations on the lock screen.

The first step is to check if the current application is set as a provider by using the IsProvidedByCurrentApplication property of the LockScreenManager class. Otherwise, we ask for the user’s permission by calling the RequestAccessAsync() method. In return, we receive the user’s choice, which can be positive (LockScreenRequestResult.Granted) or negative (LockScreenRequestResult.Denied).

In both cases, only if the application has been set as provider can we effectively change the lock screen image using the SetImageUri() method, which requires the picture’s path as a parameter. The picture can be either part of the project (as in the previous sample where we use the ms-appx:/// prefix) or stored in the local storage (in this case, we have to use the ms-appdata:///Local/ prefix). Remote images are not directly supported; they must be downloaded before using them as a lock screen background.

The previous code can also be used for the background agent. The difference is that you’ll be able to check whether the application is set as a provider and, eventually, change the image. You won’t be able to ask to the user for permission to use your app as a provider since background agents can’t interact with the UI.

Conclusion

In this tutorial, we have seen that live apps are one of the core concepts in Windows Phone development and, to properly create a quality experience, many factors are involved, like notifications, agents, and Tiles.

The following list details what we’ve learned:

  • Push notifications are the best way to notify users of something even if the application is in the background. An app can either send toast notifications or update Tiles. We’ve seen how to create the required architecture for reach, both on the client side and the server side.
  • Push notifications offer the best approach for optimizing battery life and performance, but they support limited scenarios and require a server application to send them. For this reason, Windows Phone has introduced background agents, which we can periodically execute to send notifications or carry out general purpose operations, even when the application is not in the foreground.
  • Windows Phone offers a special background agent type called audio background agent that is used in audio playback scenarios. Applications are able to play audio even when they are not running, like the native Music + Videos Hub.
  • Alarms and reminders are a simple way to show reminders to users when the application is not running.
  • Live Tiles are one of the distinctive features of the platform. We’ve learned how to customize them by choosing between different templates and sizes.
  • We’ve seen another new feature introduced in Windows Phone 8, lock screen support: applications are now able to interact with the lock screen by displaying notifications and changing the wallpaper.

This tutorial represents a chapter from Windows Phone 8 Succinctly, a free eBook from the team at Syncfusion.

Tags:

Comments

Related Articles