Sending notifications from inside your application, both from code of from a push notification channel, is being a must when developing with Windows 8.1. Sending a notification is at all a simple task, but it involves boring and repetitive things that always need to be done. Recently I’ve published a new library made to oversimplify this task and made it straightforward in both the scenarios, from the server side with a push notification or from the running app both in foreground and in background.
Notifications: the usual way
All in all, sending a notification to a tile, a toast or a badge is a simple task. At the very end you have only to build a fragment of xml and then send it to the runtime using the right manager. The very hard task to me, is that you need to create the xml, from scratch or using a template, and this implies you always remember the structure and the fields you have to fill to make this notification valid.
This means you always have to browse documentation (here is the tile template catalog http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx) to detect the right format of the output xml on the basis of the combination of images, title and content you need and then use the XmlDocument to fill out the template.
As an example if you would like to get a tile notification for a tile, you need to write something like the code below. First of all, after going in the template catalog you have to get the template using the GetTemplateContent method:
1: XmlDocument tileXml =
2: TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150ImageAndText01);
Then, with the structure of the xml in mind you have to fill the fields. This template has two fields, an image and a text line. So you scan the template for the text node and fill it this way:
1: XmlNodeList tileTextNode =
2: tileXml.GetElementsByTagName("text");
3:
4: if (tileTextNode != null && tileTextNode.Length > 0)
5: tileTextAttributes[0].InnerText = "This is a notification build by hand!";
Then the same thing is done with the image that has instead two attributes to fill. So again find the node and set the attributes:
1: XmlNodeList tileImageNode =
2: tileXml.GetElementsByTagName("image");
3:
4: if (tileImageNode != null && tileImageNode.Length > 0)
5: {
6: ((XmlElement)tileImageNode[0]).SetAttribute("src", "ms-appx:///images/mytileimage.png");
7: ((XmlElement)tileImageNode[0]).SetAttribute("alt", "The tile image text");
8: }
With tile notifications usually you need to send an update for each size your app implements. Usually, when you choose to use a tile notification you provide at least two sizes so the code above needs to be duplicated and merged to create a single notification that contains both the sizes. With the XmlDocument this task imply you have to extract part of the notification and import it into the other one. The resulting XML should be like this:
1: <tile>
2: <visual version="2">
3: <binding template="TileWide310x150ImageAndText01" fallback="TileWideImageandText01">
4: <image id="1" src="ms-appx:///images/mytileimage.png" alt="The tile image text" />
5: <text id="1">This is a notification build by hand!</text>
6: </binding>
7: <binding template="TileSquare150x150Text04" fallback="TileSquareText04">
8: <text id="1">This is a notification build by hand!</text>
9: </binding>
10: </visual>
11: </tile>
Each <binding> node represents a single tile size. To build this you do something like this:
1: XmlDocument squareTileXml =
2: TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text04);
3:
4: XmlNodeList squareTileTextNode =
5: squareTileXml.GetElementsByTagName("text");
6:
7: if (squareTileTextNode != null && squareTileTextNode.Length > 0)
8: squareTileTextNode[0].AppendChild(squareTileXml.CreateTextNode("This is a notification build by hand!"));
9:
Finally the templates should be merged together:
1: IXmlNode node =
2: tileXml.ImportNode(
3: squareTileXml.GetElementsByTagName("binding").Item(0), true);
4:
5: tileXml.GetElementsByTagName("visual").Item(0).AppendChild(node);
This code, taken from the MSDN documentation is probably nothing of too hard, but it requires time and the deep knowledge of the xml manipulation tecniques. After having build a number of these I’ve finally decided to create a simple library to make this work easy as opening a simple messagebox.
Introducing the XPG.Toolkit.Notifications library
Saying “simple library” may sounds that it have been build in a few hours. Unfortunately, since there are almost 75 templates only for tiles and the great part of them have two version of the xml (one for version 1 and the other for version 2), building a compehensive library that also includes toasts and badged took me a number of days of work. But now, with the XPG Notification Library, sending an update like the one I’ve shown in the previous section is easy like drinking a glass of water:
1: INotificationManager manager = new NotificationManager();
2:
3: manager.PublishTile(
4: new Tile
5: {
6: Visual = new TileVisual
7: {
8: Bindings = new TileBinding[] {
9: new TileWide310x150ImageAndText01
10: {
11: Text1 = "This is a notification build easy",
12: ImageSource1 = new Uri("ms-appx:///images/mytileimage.png"),
13: ImageText1 = "The tile image text"
14: },
15: new TileSquare150x150Text04{
16: Text1 = "This is a notification build easy"
17: },
18: }
19: }
20: });
As you can see you have only to build a couple of object instances, corresponding to the tile sizes you have to update and then add both to the notification structure. At the end, using a NotificationManager you post the notification to the right update manager. This is for sure way too better because Visual Studio helps you with intellisense in discovering the properties you have to fill and you also use strictly typed properties (in this case the image Uri) to avoid unwanted errors that make the notification fail silently with XML.
The concept behind the library is definitely simple. It is a big collection of xml serializable classes that matches all the available templates. All the templates actually supports both the old version 1 and the new version 2 shapes. You can forget the difference between the two versions and directly use the old or new version using its original name:
1: // initialize and old (version 1) tile template
2: TileSquareText01 oldTile = new TileSquareText01();
3:
4: // initialize the new (version 2) tile template
5: TileSquare150x150Text01 newTile = new TileSquare150x150Text01();
6:
7: // everywhere possible the old template is base class for the new one
8: // so it is possible the following assignment
9: oldTile = newTile;
All the templates are able to directly serialize to a string using a simple assignment. This is because the base class implements an operator overloading for the assignment to a string variable. Here is and example:
1: var tile = new TileWide310x150ImageAndText01
2: {
3: Text1 = "This is a notification build easy",
4: ImageSource1 = new Uri("ms-appx:///images/mytileimage.png"),
5: ImageText1 = "The tile image text"
6: };
7:
8: Debug.WriteLine(tile);
The code above outputs the following XML to the debug console:
1: <binding fallback="TileWideImageAndText01" template="TileWide310x150ImageAndText01">
2: <image id="1" src="ms-appx:///images/mytileimage.png" alt="The tile image text" />
3: <text id="1">This is a notification build easy</text>
4: </binding>
Obviously you can also assign the output to a string variable or to a XDocument instance
1: var tile = new TileWide310x150ImageAndText01
2: {
3: Text1 = "This is a notification build easy",
4: ImageSource1 = new Uri("ms-appx:///images/mytileimage.png"),
5: ImageText1 = "The tile image text"
6: };
7:
8: XDocument xDocument = tile;
9: string xmlString = tile;
Getting the xml from a notification may be useful if you need to send a push notification. This is possible because the library is built as a PCL (portable class library) so you can generate notifications also in a server code that pushed it to the Windows Notification Service (WNS). The serializations actually works at every level of the hierarchy, allowing to serialize the whole structure with a number of notifications into it.
Not only for tiles. Toasts, badges and…
As I said initially you can send also other types of notifications. The library includes all the templates for toast and badge notification. Using the same notification manager you will find the PublishToast and PublishBadge methods:
1: manager.PublishToast(
2: new Toast
3: {
4: Visual = new ToastVisual
5: {
6: Binding = new ToastText04
7: {
8: Text1 = "This is a toast notification",
9: Text2 = "Created with XPG Toolkit",
10: Text3 = "by A. Boschin"
11: }
12: }
13: });
This code sends a tile notification using the ToastText04 template. As for tiles it exposes properties with the same name of the online catalog so it is easy to understand the content to provide. Equally you can send an badge notification this way:
1: manager.PublishBadge(new Badge
2: {
3: Value = BadgeValue.Attention,
4: Version = 1
5: });
The BadgeValue property is an enumerator but you can also supply and integer to show a number on the badge, using a value from 0 to 99. Here is the sample:
1: manager.PublishBadge(new Badge
2: {
3: Value = (BadgeValue)42,
4: Version = 1
5: });
Windows 8.1 also support scheduled alarm notifications that have a given delivery time and a snooze interval. The methods in the NotificationManager allow to specify these values for every Toast and Tile notifications:
1: manager.PublishToast(new Toast
2: {
3: Duration = "long",
4: Launch = "12345",
5: Audio = new ToastAudio
6: {
7: Loop = true,
8: Source = "ms-winsoundevent:Notification.Looping.Alarm2"
9: },
10: Visual = new ToastVisual
11: {
12: Binding = new ToastText01
13: {
14: Text1 = "Alarm!"
15: }
16: },
17: Scenario = new AlarmScenario
18: {
19: CanDismiss = true,
20: CanSnooze = true
21: }
22: }, DateTimeOffset.Now.AddMinutes(1), TimeSpan.FromSeconds(60), 3);
The previous code sends a scheduled toast notification that is raised one minute after, and it snooze three times every 60 seconds.
Supporting Mocking
As a final note, you have to notice that the library has been build with mocking in mind. The NotificationManager is based on a INotificationManager interface and it may support a dependency injection container. This lets you to add at runtime the NotificationManager instance and change it during tests with a mock that track the calls to the manager’s methods.
The library is enforced by 136 unit tests that ensures the correct output to the notification system. So you can rely for sure on it. In the future I’m planning to add some other methods to the NotificationManager the sends easily standard notifications with very few lines of code, removing the needs of creating the wrapping package of the notification.
If you are interested, the library is available on Nuget with the MS-PL license, and it can be downloaded easily directly from Visual Studio using the Nuget package manager. Feel free to use the library in your commercial products, free of charge. Other details here: http://www.xamlplayground.org/page/XPG-Toolkit-Notification-library.aspx