Windows Push Notification Server Side Helper Library

This post is a preview of the Recipe for the Push Notification Server Side Helper Library. The library provides an easy way for sending all three kinds of push notification messages currently supported by Microsoft Push Notification Services (MPNS): TileToast, and Raw. Our main goal here is to extract any complexity for sending push notification (PN) messages from your website (or web service) to a Windows Phone. This library helps developers to send push messages using only a few lines of code.

We are not going to cover what push notifications are, or how they work. If you are not familiar with push notifications please be sure to read the previous posts: Understanding Microsoft Push Notifications for Windows Phones part 1 andpart 2, as well as Using Push Notification from Your Windows Phone Application, or refer to the Push Notificationsdocumentation on MSDN.

In a push notification scenario, the server side piece is as important as the Windows Phone client application. For a complete end-to-end push-enabled scenario to work, you need your server side to be able to receive incoming phone messages, as well as send push requests to Microsoft Push Notification Services as illustrated in the following diagram

As we said before, the Push Notification Server Side Helper Library helps you send push notification requests from your cloud application (web service) to MPNS, and manage (understand) the return values received from MPNS in response.

This post provides some background and an example of what you will find in greater detail in the Recipe. To start with, the recipe includes four projects, from which the library is the WindowsPhone.Recipes.Push.Messages assembly. The projects are:

  • WindowsPhone.Recipes.Push.Messages – The Push Notification Server Side Helper Library
  • WindowsPhone.Recipes.Push.Client – A Windows Phone client application the helps illustrate the push scenarios
  • WindowsPhone.Recipes.Push.Server – A WPF application that acts as a local server side application mimicking your real web service (we use a local WCF client as a local web service to simplify the deployment and testing of the helper library; however rest assured that the entire scenario works end-to-end)
  • Libraries –A few supporting libraries we are using in the Recipe

Since we are using WCF service to open a channel for incoming communications, you need to run the entire Visual Studio solution in “Admin mode” or else you will hit an exception when you try to run the WPF “server” application. But before we jump ahead, let’s understand how to use the helper library

PushNotificationMessage Base Class and Sub-Classes

In order to send a PN message to your Windows Phone application, you need to post that message to MPNS. Therefore, it makes sense to abstract the sending functionality and create a PushNotificationMessage base class. This base class handles the majority of the logic and heavy lifting for sending the message to MPNS.

The main public functions that the PushNotificationMessage base class exposes are two send methods:

  • Send, for sending the PN message synchronously – blocking the current thread
  • SendAsync, for sending the PN message asynchronously using the .NET thread pool.

Both methods have a callback for returning the MPNS response codes, and can throw an exception if something goes wrong. A separate sub-class represents each of the different PN message types, as illustrated in the following class diagram.

The three supported PN message sub-classes are:

  • RawPushNotificationMessage – Represents sending raw bytes to the Windows Phone application while it is running
  • TilePushNotificationMessage –Represents sending tile updates to the Windows Phone when your application tile is pinned to the phone’s Start screen
  • ToastPushNotificationMessage –Represents sending toast “alert” messages to the Windows Phone

The difference between the three types of messages is the way each one encapsulates the push message format and exposes it with regular .NET properties. Using any of these classes to send a message is relatively easy as shown in the following code samples".

var tile = new TilePushNotificationMessage
{
   BackgroundImageUri = tileImageUri, // Remote or phone-local tile image uri.
   Count = tileCount, // Counter between 1 to 99 should be displayed on the tile.
   Title = “Tile Title” // Title to be displayed on the tile.
};
// Send the message synchronously.
Var sendResult = tile.Send(phoneChannelUri);
 
// Send the message asynchronously.
tile.SendAsync(
phoneChannelUri,
   result => {/* Check the send result */},
   exception => {/* Log the error */});

When sending asynchronously, you need to provide delegates as callback handlers for the return values from MPNS and to log any exceptions.

Similarly, you can send toast and raw notifications, by simply instantiating new instances of ToastPushNotificationMessageand RawPushNotificationMessage, respectively.

Push Notification Server-Side Common Patterns

To illustrate the use of the Push Notification Server Side Helper Library, we’ve create a WPF application that acts like a web service, mimicking a third-party server. To enable this, the WPF application has a WCF service that lets the Windows Phone application register and communicate with MPNS. The WPF has tabs, each of which represents a specific Push Pattern that we wish to illustrate.

Push Patterns are a generalization of a common use of PN in an end-to-end solution that includes specific Windows Phone and server-side logic. The current application has five patterns:

  • One-time Push – Simple one-time send of any or all three push notification message types
  • Push Counter Resets upon Logon – Each time you send a push message, a counter value increments and displays on the tile (assuming the application’s tile is pinned to the Start screen), resetting the next time the user runs the application
  • Ask to Pin Application Tile –The phone application “asks” the user to pin the application’s tile to the phone Start screen up on sending request from the WPF application
  • Create Custom Server-side Image – Tile notification can update the application’s tile on the Start screen, and this scenario illustrate that you can create a complete new tile as image
  • Scheduled Tile Updates –Schedule tile updates (note this requires a testing period of 60 min)

Please note: The server-side patterns are provided as a samples and only to demonstrate the specific pattern usage; they are NOT best practices for server-side or web programming. The goal is to explain the patterns and server-side requirements. To keep the examples simple, we DO NOT use server-side authentication, a database, or any complex setups that would be included in actual scenarios.

As an example, let’s examine the Ask to Pin Application Tile scenario as it explained in the Recipe.

Ask To Pin Application

If a given application sends a tile PN message and that application’s tile is not pinned to the phone Start screen, the PN message will not be delivered to the phone, and the third-party server side will be notified that the application tile is not pinned. Since in Windows Phone, only end users can pin an application’s tile to the phone Start Screen, applications need a way to “ask” the user to pin the application’s tile. This pattern illustrates how an application can do that by sending a specific message to the phone. The pattern implementation includes both server-side and Windows Phone client-side code.

Implementation

  1. The server side maintains a list of the last tile message data sent per registered user.
  2. Upon client registration the server side application knows that the Windows Phone client application is running.
  3. The server side sends a tile message with the most updated tile data.
  4. Based on the response to this message from MPNS, the application knows if the Windows Phone application’s tile is pinned to the Start screen or not:
  1. If the device is connected, the subscription is active, and the notification is received, we know that the application’s tile is pinned to the Start screen.
  2. If not, the server side sends a custom raw PN message to the Windows Phone client application asking it to display the “Ask to Pin” message to the user.
  • Log message-send error or message-send success

Demonstration

  1. Run only the WindowsPhone.Recipes.Push.Server project and make sure that the “Ask to Pin” tab is selected.
  2. Run the WindowsPhone.Recipes.Push.Client (Windows Phone application), and make sure that the application’s tile is not pinned to the Start Menu.
  3. Accept existing push messages and log on with any user name.
  4. A message box should pop up asking to pin the application. Click OK.
  5. On the server UI, click Send to update the tile.
  6. A message box should pop up asking to pin the application. Click OK.
  7.  
  8. Close the application, pin it to the Start Page, and run the application again. The previous ”Ask to Pin” message should be gone.
  9. On the server UI, click Send to update the tile. The previous ”Ask to Pin” message should be gone and the tile number should be updated.

Note –This pattern can be adjusted to make the Windows Phone client application display the “Ask to Pin” message upon logon.

Code [Implemented as part of the AskToPinPushPatternViewModel.cs file in the WPF application]

The pattern starts when a client first registers to the server. In order to check if the application is pinned or not, theOnSubscribed method below sends a tile notification message to the relevant subscriber (based on the Windows Phone client application URI and username). The data used with the message is new for first time subscriptions or from previously stored data for re-subscriptions. Using stored data prevents updating the tile for no reason.

protected override void OnSubscribed(SubscriptionEventArgs args)
{
    // Asynchronously try to send Tile message to the relevant subscriber
    // with data already sent before so the tile won't change.
    var tileMsg = GetOrCreateMessage(args.Subscription.UserName, false);
 
    tileMsg.SendAsync(
        args.Subscription.ChannelUri,
        result =>
        {
            Log(result);
            OnMessageSent(args.Subscription.UserName, result);
        },
        Log);
}

The PN message is sent asynchronously, and the OnMessageSent callback is called when the tile PN message is sent. At that point, the server side can check if the application is pinned to the Start screen by checking the response returned by MPNS. If the tile is pinned, do nothing. However, if the application’s tile is not pinned, the Windows Phone client application will “ask” the user to pin the application’s tile by sending a raw message with custom data, in our case the “Ask to Pin” message. This raw message is received by the phone client and displays a message to the user.

/// <summary>
/// Once tile update sent, check if handled by the phone.
/// In case that the application is not pinned, ask to pin.
/// </summary>
private void OnMessageSent(string userName, MessageSendResult result)
{
    if (!CheckIfPinned(result))
    {
        AskUserToPin(result.ChannelUri);
    }
}

The same logic repeats in cases where the server wants to send a tile update to one or more clients. This time the message is newly created.

/// <summary>
/// Send a tile notification to all relevant subscribers.
/// </summary>
protected override void OnSend()
{            
    // Asynchronously try to send this message to all relevant subscribers.
    foreach (var subscriber in PushService.Subscribers)
    {
        // Create a tile message to send an update.
        var tileMsg = GetOrCreateMessage(subscriber.UserName);
 
        tileMsg.SendAsync(
            subscriber.ChannelUri,
            result =>
            {
                Log(result);
                OnMessageSent(subscriber.UserName, result);
            },
            Log);
    }
}

The CheckIfPinned method below checks if the application is pinned to the Start screen by observing the three previously described flags.

private bool CheckIfPinned(MessageSendResult result)
{
    // We known if the application is pinned by checking the following send result flags:
    return result.DeviceConnectionStatus == DeviceConnectionStatus.Connected &&
           result.SubscriptionStatus == SubscriptionStatus.Active &&
           result.NotificationStatus == NotificationStatus.Received;
}

The AskUserToPin method below sends a raw message with the custom “Ask to Pin” data, which is intercepted by the phone.

/// <summary>
/// Just in case that the application is running, send a raw message, asking
/// the user to pin the application. This raw message has to be handled in client side.
/// </summary>
private void AskUserToPin(Uri uri)
{
    new RawPushNotificationMessage
    {
        RawData = Encoding.ASCII.GetBytes(RawMessage)
 
    }.SendAsync(uri);
}

Conclusion

The Push Notification Server Side Helper Library is a simple library that lets you focus on your web service logic rather than on the technicality of sending push messages.

The actual Recipe contains detailed documentation and full code implementation. The above example is just one of 5 scenarios, each with full details.

Download the Recipe and its documentation

你可能感兴趣的:(notification)