James Montemagno
James Montemagno

Live, Love, Bike, and Code.

Tags


Twitter


Windows 8 Live Tiles Done Right

James MontemagnoJames Montemagno

It is a bit surprising to that one of the best features of Windows 8 isn’t extremely well documented on how to implement it. Now there are plenty of tutorials on implementing live tiles, however what if you want to update them in the background, or maybe every so often. Do you need to require permissions? Do you need to register events? Who knows!?!?! Well there is probably a document somewhere, but I couldn’t find it. So what do you need to do?

In this tutorial I am going to go through how I think you should do it, which is to update live tiles when people launch your app and then also how to create a maintenance task to run every few hours. Also how to do proper wide & square live tiles

Step 0 (optional)

If you want to have live tiles then you must specify a Wide Logo. I will be doing this!

Step 1

Download the NotificationsExtensions from Microsoft. This will make make live tiles about 100% easier to implement. Instead of microsoft just including this into the API they have some crazy xml way of managing live tiles, and this awesome extension wraps it. After you have it downloaded simply add the project to your solution.

Step 2

Add a new Project in your solution. It should be a Windows Runtime Component and to make it easy let’s call it “BackgroundTasks”


Step 3

Rename Class1.cs to TileUpdater.cs. Open it up and have your TileUpdaterClass Implement IBackgroundTask.

Step 4

Now before we implement some code let’s do some really important things. First add BackgroundTasks project as Reference to your main class. If you skip this it wont work.

Also open up your Package.appxmanifest and go to Declarations and add a new “Background Tasks” Declaration. Then check “System event” and for the Entry Point you should set it to “BackgroundTasks.TileUpdater”

Step 5: App.xaml.cs stuff

Open up your App.xaml.cs and we will want to add a few variables in here:

private const string TASK_NAME = "SomethingUniqueTileUpdater";
private const string TASK_ENTRY_POINT = "BackgroundTasks.TileUpdater"; //don't change
private const int MAINTENANCE_INTERVAL =  3 * 60; // Check for updates that need to be updated every 3 hours

You can change the maintenance interval as well i have it to 3 hours. Now we can add a little helper method which checks to see if we have the task registered:

private bool IsTaskRegistered()
{
  foreach (var task in BackgroundTaskRegistration.AllTasks.Values)
  {
    if (task.Name == TASK_NAME)
    {
      return true;
    }
  }
  return false;
}

Now in your App() constructor add this code under this.Suspending += OnSuspending;

if (!IsTaskRegistered())
{
  BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder();
  MaintenanceTrigger trigger = new MaintenanceTrigger(MAINTENANCE_INTERVAL, false);
  taskBuilder.SetTrigger(trigger);
  taskBuilder.TaskEntryPoint = TASK_ENTRY_POINT;
  taskBuilder.Name = TASK_NAME;

  SystemCondition internetCondition = new SystemCondition(SystemConditionType.InternetAvailable);
  taskBuilder.AddCondition(internetCondition);

  taskBuilder.Register();
}

One stipulation here is that they must have internet. If for some reason you don’t need internet then remove that condition.


Step 6: Add normal live tile via In App

Alright now we can go ahead and create the live tiles. There are TONS for you to pick from. Microsoft has a great break down on their TileTemplateEnum msdn article. For each update you will want to pick out a Square and Wide Tile.

I am going to just do a simple tile inside of the on navigated to. What you will see here is I am using the TileContentFactory which is part of that NotificationsExtensions I told you to add earlier. All of the .CreateTile____() metods match the msdn article which is awesome.

protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            //some work upfront
            var updater = TileUpdateManager.CreateTileUpdaterForApplication();
            updater.EnableNotificationQueue(true); //doing this means you can stack 5 tiles.

            updater.Clear(); //clear out any old ones

            var tile = TileContentFactory.CreateTileSquareText04();
            var tileWide = TileContentFactory.CreateTileWideText01();

            tile.TextBodyWrap.Text = "This came from In App.";
            tileWide.TextHeading.Text = "In App Update";
            tileWide.TextBody1.Text = "www.MotzCod.es";
            tileWide.TextBody2.Text = DateTime.Now.ToString();

            tileWide.SquareContent = tile;
            updater.Update(tileWide.CreateNotification());
        }

Make sure you set “tileWide.SquareContent = tile” as the user can switch between wide and small at any time. If you don’t do this it will throw an exception.


Alright that is great, but let’s do some background updates. We can re-use all of that code from earlier but change it around a bit but we have to do something special in our TileUpdater.cs

So inside of Run method the first thing we will want to do is ass this piece of code:

var defferal = taskInstance.GetDeferral();

This is telling the system we are about do to some stuff. Now add in the code to update the tile, and then when you are all done add this code:

defferal.Complete();

This tells them we are all done. Here is what mine looks like now:

 public void Run(IBackgroundTaskInstance taskInstance)
        {
            var defferal = taskInstance.GetDeferral();
            //some work upfront
            var updater = TileUpdateManager.CreateTileUpdaterForApplication();
            updater.EnableNotificationQueue(true); //doing this means you can stack 5 tiles.

            updater.Clear(); //clear out any old ones

            var tile = TileContentFactory.CreateTileSquareText04();
            var tileWide = TileContentFactory.CreateTileWideText01();

            tile.TextBodyWrap.Text = "Background task";
            tileWide.TextHeading.Text = "Background task";
            tileWide.TextBody1.Text = "www.MotzCod.es";
            tileWide.TextBody2.Text = DateTime.Now.ToString();

            tileWide.SquareContent = tile;
            updater.Update(tileWide.CreateNotification());

            defferal.Complete();
        }

Now this is lovely, however you probably don’t want to wait around for 3 hours to let this thing run. (or 15 mins as it is the minimum). So you can actually force the debugger to invoke it. First add the “Debug Location” to your Visual Studio Tool bar:
Now add in a break point in your Run method, and then run your application in Debug. Once it is up and running you will want to trigger the event manually. See screenshot:

This will force the background task to trigger for your application. If for some reason your app closes and you lost your debug session that means you missed something… perphaps adding the reference from step 4?


Boom and now we have this:

I hope you enjoyed this and it helped in your development. I found live tiles to be really easy to implement as long as you don’t try to do a real background task as users would then need your permission to update the live tiles. The maintenance task allows you to get around this.


You can get the full source code here.

Live, Love, Bike, and Code

Comments