Creating custom backgrounds for Windows Phone Push Tiles

As Windows Phone 7 is still around and will be around for sometime I thought it proper to talk about one of the most useful techniques that developers employ to customize their live tiles.

First let’s start with what Microsoft gives you for the front of the tile:

BasicTileFront

Personally I hate this look, especially the way the notifications are displayed.  After all the work that is put into creating an app experience, being forced to go with this look just seems wrong.  Thankfully, you are not forced to use this and, in fact, most developers seem to avoid it, aside from Facebook, but their app has more things wrong with it than just the notifications.

So how can we adjust this?  The answer lies in the background URI that you are allowed to specify as part of the push XML, turns out it doesnt have to point to a real image.  Here is a sample from the Codemash app:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<wp:Notification xmlns:wp=\"WPNotification\">
   <wp:Tile>
      <wp:BackgroundImage>
         http://localhost/handlers/WP7Background.ashx?count=1
      </wp:BackgroundImage>
   </wp:Tile>
</wp:Notification>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Notice that I am specifying an ASHX handler.  Really it can be anything so long as what is return is perceived as an image.  Here is the code for the handler:

public void ProcessRequest(HttpContext context)
{
   string basePath = context.Server.MapPath("Images/wp7");
   int count = context.Request.QueryString["count"].AsInt();
   if (count > 0)
   {
      string filename = GetFilename(count);
      string filePath = Path.Combine(basePath, filename);
      if (!File.Exists(filePath))
      {
         CreateNotificationTile(basePath, count);
      }

     context.Response.ContentType = "image/png";
     context.Response.WriteFile(Path.Combine(basePath, GetFilename(count)));
     context.Response.Flush();
   }
} private void CreateNotificationTile(string basePath, int count) { const string template_name = "phone7_template.png"; using (var srcTemplate = new Bitmap(Path.Combine(basePath, template_name))) { using (var graphics = Graphics.FromImage(srcTemplate)) { var font = new Font("Arial", 35f, GraphicsUnit.Point); var brush = new SolidBrush(Color.White); graphics.DrawString(count.ToString(), font, brush, 105, 60); } srcTemplate.Save(Path.Combine(basePath, GetFilename(count))); } }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

What I am doing here is opening an existing image and drawing a number to it based on what I received for the count, I think save that image and return the file’s byte stream.  Along with the forced content type makes the receiver (the phone) think this is an image and display it.

For the sake of efficiency, the reason I save the created image is so I can simply return it later instead of creating the image each time.  The result is if I make a request to this handler with count = 1, I get the following image:

1

Remember, that there is a limit to how long a push notification will wait for its background to download is 1 minute and the returned tile cannot exceed a size of 80kb.  These are hard limits by Microsoft and they make sense.

What about the back content?

The back content can take the same approach, really anywhere that allows specification of a URI for the background can be manipulated using this approach.

Can I do this for things other than numbers?

Yes.  Take an app like Weatherflow which will actually send you an image representative of the weather in your area.  In fact, people will also send color information based on the current theme the phone is using so the tile background can be adjusted to match.  This is why this approach is so popular is the immense amount of creativity it makes available.

What about Windows Phone 8?

This approach remains useful in Phone 8 through the Cycle and Flip tile templates.  I am certain you could use the technique with the Iconic template, but I am not sure it would make sense.  But as I said, really anywhere there is a URI specified allows you to use this technique.  Its nothing especially new, we have been using it on the web for years.

Final Thoughts

I really love this technique and regularly use it in my Windows Phone apps.  I think Microsoft recognized the limitation the previous tile formats placed on developers and resolved it by offering the additional templates: Iconic, Flip, and Cycle.  These new templates certainly allow for more creativity, but specifying static images doesn’t always make sense, and in the cases where they don’t, it is nice to have this technique in your back pocket.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s