Windows Phone 7 supports push notifications that let you do things like send alerts to a WP7 application, or update the tile (icon) for an application. The notifications are sent using the Microsoft Push Notification Service (MPNS), a free service that Microsoft provides. You’re reponsible for somehow creating the notification message and passing it to the MPNS, which then routes it to the WP7 device.
I’ve been reading how to accomplish this using .NET and wanted to give it a go using Ruby. Turns out it’s pretty simple.
There are three types of notifications that WP7 supports, toast, tile, and raw. Each has a specific function, so we need to understand what they do and when to use them. You can see an example of each at http://msdn.microsoft.com/en-us/library/ff402558(v=vs.92).aspx.
A toast notification results in an alert that pops up on the screen for 10 seconds, but doesn’t disrupt what the user is doing. If you tap the notification message, the associated application will launch. This type of notification is useful for alerts or other informational type messages that you want the user to see, but not neccessarily act on right now.
A tile notification changes the tile (icon) for the application, if the tile is pinned to the start screen. You can update the title, a numerical counter, or even change the image of the tile. There’s two sides to every tile with the latest mango update, and you can set both sides. This is a useful way to provide information without having the user open the application. For example, an e-mail application might update a number to indicate the number of new messages.
A raw notification is simply a push of data into the application. It’s up to the application as far as what it does with this data.
To send a notification, you need to know the URI to send the notification to. This needs to be created by an application running on the WP7 device. The ‘How It Works’ section of http://msdn.microsoft.com/en-us/library/ff402558(v=vs.92).aspx has more information on this, but basically the application talks to the Microsoft Push Notification Service, which gives it a unique URI, which it then hands off to your notification service.
I’m not going to concentrate too much on the Windows Phone 7 application in this post, as that’s not really the focus. For testing I used the Windows Phone 7 client appilcations in the SDK Notification samples available at http://msdn.microsoft.com/en-us/library/ff431744(v=VS.92).aspx#BKMK_PushAndTiles.
The notification message is sent to the MPNS via HTTP post. There are some specific headers that must be set, and the body format depends on the notification type being sent. The common items for all message types are the following HTTP headers:
The first two should be familiar to anyone who’s worked with HTTP, but what are these X-MessageID and X-NotificationClass things?
X-MessageID is an optional header that lets you specify a unique ID for this message, and you can then compare it to the value returned in the message response to match up response to header.
X-NotificationClass is where we specifiy how important this message is so that the MPNS can batch up message based on importance and send them to your phone in one lump. This saves on phone battery life as it just has to receive the one batch instead of X individual notifications.
But what value do we use here? Took me a bit to find it, but here’s the valid values:
If you’re sending a raw message, this is pretty much all you need; headers, body, URI to send to. It’s a little more complicated for toast and tiles.
Toast notification messages have the following message format:
<?xml version='1.0' encoding='utf-8'?> <wp:Notification xmlns:wp='WPNotification'> <wp:Toast> <wp:Text1></wp:Text1> <wp:Text2></wp:Text2> <wp:Param></wp:Param> </wp:Toast> </wp:Notification>
For more information on toast notifications, see http://msdn.microsoft.com/en-us/library/ff402558(v=vs.92).aspx.
Tile notification messages have the following message format:
<?xml version='1.0' encoding='utf-8'?> <wp:Notification xmlns:wp='WPNotification'> <wp:Tile> <wp:BackgroundImage></wp:BackgroundImage> <wp:Count></wp:Count> <wp:Title></wp:Title> <wp:BackBackgroundImage></wp:BackBackgroundImage> <wp:BackTitle></wp:BackTitle> <wp:BackContent></wp:BackContent> </wp:Tile> </wp:Notification>
For more information on tile notifications, see http://msdn.microsoft.com/en-us/library/ff402558(v=vs.92).aspx.
The following code demonstrates how to accomplish push notifications from Ruby:
require 'net/http' require 'uri' NONRAWTYPES=[:toast, :tile] BASEBATCH={:tile=>1, :toast=>2, :raw=>3} BATCHADDS={:delay450=>10, :delay900=>20} def send_notification(params) msg=build_message(params) delay=calculate_delay(params[:type],params[:delay]) uri=URI.parse(params[:uri]) http=Net::HTTP.new(uri.host, uri.port) headers={ 'Content-Type'=>'text/html', 'Content-Length'=>msg.length.to_s, 'X-NotificationClass'=>delay.to_s } if NONRAWTYPES.include?(params[:type]) headers['X-WindowsPhone-Target']= (params[:type]==:toast) ? 'toast' : 'token' end http.post(uri.path, msg, headers) end private def calculate_delay(type, delay) if type.nil? type = :raw end delay.nil? ? BASEBATCH[type] : BASEBATCH[type]+BATCHADDS[delay] end def build_message(params) if NONRAWTYPES.include?(params[:type]) msg_body="<?xml version='1.0' encoding='utf-8'?><wp:Notification xmlns:wp='WPNotification'><wp:#{params[:type].capitalize}>" case params[:type] when :toast msg_body << "<wp:Text1>#{params[:title]}</wp:Text1>" msg_body << "<wp:Text2>#{params[:message]}</wp:Text2>" msg_body << "<wp:Param>#{params[:param]}</wp:Param>" when :tile msg_body << "<wp:BackgroundImage>#{params[:image]}</wp:BackgroundImage>" msg_body << "<wp:Count>#{params[:count].to_s}</wp:Count>" msg_body << "<wp:Title>#{params[:title]}</wp:Title>" msg_body << "<wp:BackBackgroundImage>#{params[:back_image]}</wp:BackBackgroundImage>" msg_body << "<wp:BackTitle>#{params[:back_title]}</wp:BackTitle>" msg_body << "<wp:BackContent>#{params[:back_content]}</wp:BackContent>" end msg_body << "</wp:#{params[:type].capitalize}></wp:Notification>" else msg_body=params[:message] end return msg_body end
To use this, you can pass the following keys and values to send_notification:
I tested this using the notification samples from the Windows Phone 7 SDK. You can download these from http://msdn.microsoft.com/en-us/library/ff431744(v=VS.92).aspx#BKMK_PushAndTiles. These samples do require Visual Studio 2010 running on a Windows machine, but they function just fine from the emulator; no WP7 device required. Note that none of the samples upload their URI, but instead rely on displaying it and having you manually type it in.
The steps I followed to use this were: