Tag: Secondary Tiles

EvenTiles from Start to Finish–Part 9

In the previous episode of this series about how to develop a Windows Phone application from scratch we talked about restoring the entire page state after the application returns from the background. Today we finally are going to add a Secondary Tile to our application.

Each application has at least one tile, the Application Tile, which end users can pin to the start screen on their phone. In the very first episode of this series we defined the contents for the backside of the Application Tile in the manifest file of our application. Each application can also create one or more Secondary Tiles. Once a Secondary Tile is created programmatically, it will immediately be pinned to the start screen. Secondary Tiles can be removed again programmatically, but the end user can also remove Secondary Tiles from the start screen of their phone.

To add a Secondary Tile to the start screen, our application’s MainPage will host a button. When the user clicks the button, a new Secondary Tile is created. After creation, our application is moved to the background by the operating system in order to show the start screen with our newly created secondary tile, that is initialized in such a way that it contains both a front- and backside.

image

You can see the Secondary Tile being pinned on the start screen. You can also see that the Secondary Tile has two different sides, each with their own image and the backside containing an additional string, the string that the user can enter in the SettingsPage of the application. If the user returns to the application when the Secondary Tile is installed, they have the possibility to remove the Secondary Tile again from the start screen programmatically.

To find out if our Secondary Tile is currently visible on the start screen of the phone, we just check if it is defined in our application’s collection of tiles. This collection of ActiveTiles always contains at least the Application Tile and optionally all Secondary Tiles that were created in the application. When we are navigating to the MainPage of the application, we can find out if our Secondary Tile is available by executing the following code:

Secondary Tile Active?
  1. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     base.OnNavigatedTo(e);
  4.  
  5.     secondaryTileInstalled = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileId=Secondary")) != null;
  6.     btnInstall.Content = secondaryTileInstalled ? txtRemoveTile : txtInstallTile;
  7. }

In this code snippet, we use a lambda expression on the static collection of ActiveTiles to find the first tile that contains the following string in its Uri: TileId=Secondary. The Application Tile does not contain this additional information, so if we find a tile with this string being part of its Uri, we can safely assume that this is our Secondary Tile. In that case, we set a boolean variable to true. Depending on the presence or absence of a Secondary Tile we also modify the Content property of the button. Of course we also need to create / delete the Secondary Tile, which is something that we will do inside the Click event handler of the button we created on the MainPage:

Creating / Deleting Sec. Tiles
  1. private void btnInstall_Click(object sender, RoutedEventArgs e)
  2. {
  3.     if (secondaryTileInstalled)
  4.     {
  5.         var secondaryTile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileId=Secondary"));
  6.         if (secondaryTile != null)
  7.         {
  8.             secondaryTile.Delete();
  9.             btnInstall.Content = txtInstallTile;
  10.             secondaryTileInstalled = false;
  11.         }
  12.     }
  13.     else
  14.     {
  15.         StandardTileData newTileData = new StandardTileData
  16.         {
  17.             BackgroundImage = new Uri("Background.png", UriKind.Relative),
  18.             Title = "EvenTiles",
  19.             Count = 0,
  20.             BackBackgroundImage = new Uri("Backbackground.png", UriKind.Relative),
  21.             BackTitle = "EvenTiles",
  22.             BackContent = App.ActualSecBackContent
  23.         };
  24.         ShellTile.Create(new Uri("/MainPage.xaml?TileId=Secondary", UriKind.Relative), newTileData);
  25.     }
  26. }

In the above code snippet the first thing we do is verify if a Secondary Tile is installed. If so, we simply call the Delete method on it to remove it from the start screen on the phone. As visual feedback to the user, we immediately change the content property of the button to show a string to add another Secondary Tile. If we don’t have a Secondary Tile, what we are going to do is create and initialize a new instance of StandardTileData. Through its properties, this object will hold the complete characteristics of our new Secondary Tile. To create the Secondary Tile, we simply call the static Create method of the ShellTile class, passing a navigation string, indicating to which page we should go in our application when the user clicks the Secondary Tile. In this way, you can use Secondary Tiles to link to any page inside your application. You can also pass your own parameters to the navigation URI, which can help you take different actions if a page is invoked from a Secondary Tile. Together with the navigation URI, you also pass the StandardTileData to create the Secondary Tile. Immediately after calling the ShellTile.Create method, our application is moved to the background by the operating system and the start screen with our newly created Secondary Tile becomes visible. If you click on the phone’s back button, our application returns to the foreground (from either a tombstoning or dormant state). On the other hand, if the user clicks on the Secondary Tile, a new instance of our application is started and the instance of our application that was still available in the background is removed. This behavior implies that we don’t have to modify the text of the button in case of creating a live tile, because OnNavigatedTo will always execute before our MainPage becomes visible again.

The following video shows step-by-step how to create and delete Secondary Tiles programmatically. It also shows our Secondary Tile in action. Of course, this sample application is very simple, but hopefully you can see the potential, not only for having Live Tiles available for an application, but also to make use of Secondary Tiles to allow the user to immediately navigate to a particular page of your application.

Creating and Deleting Secondary Tiles Programmatically

If you want to take a look at the source code that we have available for EvenTiles so far, you can download the entire solution belonging to this episode:

Download EvenTiles Episode 9 Source Code

After downloading and unzipping the sample code, you can open the EvenTiles solution in Visual Studio 2010 Express for Windows Phone. You must have the Windows Phone SDK 7.1 installed on your development system to do so. If you have a developer unlocked phone you can deploy the application to your phone, if you don’t have a developer unlocked phone you can still experiment with this application inside the emulator.

In the next episode of EvenTiles we will introduce a more advanced topic when we are beginning to talk about making use of a background agent to allow our application to execute some code, even when it is not in the foreground.

Every Live Tile deserves a Windows Phone Application

Over the last week I have been writing about Live Tiles in Windows Phone Mango, how you can create Secondary Live Tiles and how you can display information on the back of Live Tiles and periodically change that information. There is more to write about Live Tiles, but I think it is time to change the topic slightly.

In part 4 of the Live Tile mini series, I introduced an application that adds a Secondary Tile to the Start Screen of your phone. That application is now almost finished in its first version. This free application has a Secondary Tile, it contains an AdControl, deals with location awareness and periodically updates the Secondary Tile. It also can access Marketplace, both to submit a review for the application and to display other applications that are published by me. All in all it is a complete application, yet its functionality is very simple. It is simple enough to explain it almost entirely. That is exactly what I am planning to do over the upcoming weeks.

Initially, the application makes use of code behind. In a later version it will be changed, making use of MVVM and Unit Testing. The application will also act as a sample to show profiling, debugging background agents and many more topics. I will combine blog entries and videos to show how to create this application, how to test it and hopefully how to publish it to Marketplace. As soon as the application is available for download, I will let you know in this blog entry. Here is a sneak preview of EvenTiles.

dump1This application is very simple, yet it contains lots of functionality that you can use inside a Windows Phone application. When the application is started, it checks if a Secondary Tile exists. Actually, it can even be started by clicking on its Secondary Tile when available. If no Secondary Tile is pinned to the start screen, the user has the option to create a Secondary Tile and automatically pin it to the Start Screen. When the Secondary Tile is already pinned on the Start Screen, the user has the possibility to remove it from the Start Screen. You can also see that the application has advertisements. In order to allow for localized advertisements, the application reads the current location of the device once (if the user allows doing that). The application has a Settings Page that can be reached through the ApplicationBar as well as an About Page. To preserve data, the application makes of of Isolated Storage. To transfer data between the application and its background agent, a file in IsolatedStorage is used that is protected by a Mutex. So even though the application itself is very simple, it contains many pieces of functionality that you can use in very complex applications as well. As such, this application is hopefully a starting point that allows you to develop fantastic Windows Phone Applications. Stay tuned for the first part of EvenTiles from Start to Finish – Part 1, which shows you how to create the initial solution and how to create a Secondary Live tile.

Every Windows Phone application deserves Live Tiles (part 4)

My previous post about Live Tiles showed you how you can use a PeriodicTask to update your Application’s Live Tile periodically from inside the phone. Now we are going to move a little beyond Application Tiles and move towards Secondary Tiles.

image_thumb2Matthijs Hoekstra, Microsoft’s Dutch Windows Phone Champ, inspired me to create the following sample application. The application creates a single Secondary Tile and that is about it. This application is great to make the number of tiles on the phone’s start screen even (which simply looks better). At the same time, the application has limited functionality, making it easier to concentrate on functionality that is needed to create and update the Secondary Tile.

Each application can create multiple Secondary Tiles. These Secondary Tiles are created programmatically, and will be pinned on the user’s start screen after they are created. They do have the same properties and update possibilities as Application Tiles. However, an application always has an Application Tile, regardless from it being pinned on the start screen or not. Secondary Tiles are completely optional. End users of course have the possibility to unpin the Secondary Tile again from the start screen, so you should not automatically assume that a Secondary Tile you created inside your application will live on the phone’s Start Screen forever. One important difference between the Application Tile and a Secondary Tile is the possibility for a Secondary Tile to specify a navigation URI. With this URI it is possible to immediately navigate to a particular page inside an application and / or to pass additional data to a particular page. Because users can unpin Secondary Tiles, it is not wise to only allow navigating to a particular page through a Secondary Tile, even though this would be technically possible.

Let’s take a look how to create a Secondary Tile inside an application. The sample code that you will see is all part of the sample application that simply creates a Secondary Tile. The application also has a few options to change the appearance of the tile, which will be described in future blog entries around Live Tiles. In the sample application, a Secondary Tile is created when the user clicks a button. Technically, this could also be done automatically, for instance in the constructor of the MainPage. This code snippet is responsible for creating a Secondary Tile:

Creating a Secondary Tile
  1. private void btnInstall_Click(object sender, RoutedEventArgs e)
  2. {
  3.     ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileId=Secondary"));
  4.  
  5.     if (TileToFind == null)
  6.     {
  7.         StandardTileData NewTileData = new StandardTileData
  8.         {
  9.             BackgroundImage = new Uri("Tile.png", UriKind.Relative),
  10.             Title = "Even Tiles",
  11.             Count = 0,
  12.             BackBackgroundImage = new Uri("Tile.png", UriKind.Relative),
  13.             BackTitle = "Even Tiles",
  14.             BackContent = "Show even # of tiles on Start Screen",
  15.         };
  16.  
  17.         ShellTile.Create(new Uri("/MainPage.xaml?TileId=Secondary", UriKind.Relative), NewTileData);
  18.         btnInstall.Content = removeText;
  19.     }
  20.     else
  21.     {
  22.         TileToFind.Delete();
  23.         btnInstall.Content = addText;
  24.     }
  25. }

In the above code snippet we first check if the Secondary Tile currently exists. If not, a new Secondary Tile will be created containing both foreground and background information. The Secondary Tile also contains a Uri, containing the address of the MainPage, but it also passes additional data so we can determine if the MainPage was started from the Secondary Tile or not. If, on the other hand a Secondary Tile does exist, it will be deleted and the user has the possibility to create another Secondary Tile. As you can see, the ShellTile class is used to create or access the Secondary Tile. Identical to Application Tiles, the StandardTileData class is used to modify properties on the tile.

In the OnNavigatedTo method the reason for navigating to the MainPage is determined by checking if the Secondary Tile caused this. If so, the user has the possibility to delete the Secondary Tile. If the application was started traditionally, we are checking for an existing Secondary Tile and set Button Content accordingly. This is shown in the next code snippet:

Secondary Tile Navigation?
  1. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     base.OnNavigatedTo(e);
  4.  
  5.     btnInstall.Content = addText;
  6.  
  7.     if (NavigationContext.QueryString.ContainsKey("TileId"))
  8.     {
  9.         btnInstall.Content = removeText;
  10.     }
  11.     else
  12.     {
  13.         ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileId=Secondary"));
  14.         if (TileToFind != null)
  15.         {
  16.             btnInstall.Content = removeText;
  17.         }
  18.     }
  19. }

The initial version of the sample application looks like this:

image_thumb13

image_thumb12

 

 

 

 

 

In the next part of this series we will take a look at additional possibilities you have to update your Live Tiles.

Every Windows Phone application deserves a Live Tile (part 3)

My previous post about Live Tiles showed you how to update the back side of the Application Tile inside an application. The big drawback of this approach is that your tile will only be updated as a result of your application being executed. Depending on the information you want to display on your tile, you might want to take another approach to update your application’s tiles.

This time we will make use of a Background Agent to periodically update the Application Tile without the need for the application to actually run. We again work on the same sample application, Clicker, and extend its functionality by adding a PeriodicTask. A PeriodicTask is supposed to be lightweight and will run at fixed intervals. A PeriodicTask will not run forever, but it expires after at most 14 days. From within the running application, the PeriodicTask can be renewed before the expiration date. In this way, applications that are not used will not continue to use precious device resources through a PeriodicTask forever.

Back to our tile though. The scenario we want to implement is the following. The backside of the tile already displays the high score. It would be nice to alternate between showing the game’s high score and showing the amount of time the game has not been played. To implement this functionality, a PeriodicTask is ideal.

In order to make use of a PeriodicTask, a new project of type Windows Phone Scheduled Task Agent must be added to the solution containing the Clicker application. This newly created project already contains an OnInvoke method that is called each time the PeriodicTask executes. Inside the OnInvoke method, the back side of the live tile is updated. The PeriodicTask will execute approximately once every 30 minutes. It is important to determine how data can be exchanged between the application and the PeriodicTask. The PeriodicTask has access to the application’s IsolatedStorage. In Clicker, a file is used to save the high score, which in turn is read by the PeriodicTask. Since the OnInvoke method will execute on a thread and will be terminated after being executed, data needed for the PeriodicTask must also be persisted in IsolatedStorage. To store and retrieve high scores, a static class is available inside the Clicker application. This class will be used in the application to store high scores. The same class will also be used in the PeriodicTask to retrieve high scores. Together with the high score, also a boolean variable is stored, indicating if the high score or an informational message should be stored on the back of the Application Tile.

Retrieving HighScore info
  1. public static string GetLiveTileBack()
  2. {
  3.     string highScore = string.Empty;
  4.     bool showHighScore;
  5.  
  6.     using (var store = IsolatedStorageFile.GetUserStoreForApplication())
  7.     {
  8.         mtx.WaitOne();
  9.         if (store.FileExists(highScoreFileName))
  10.         {
  11.             string storedHighScore;
  12.  
  13.             using (var highScoreStream = new StreamReader(store.OpenFile(highScoreFileName, FileMode.Open)))
  14.             {
  15.                 showHighScore = Convert.ToBoolean(highScoreStream.ReadLine());
  16.                 storedHighScore = highScoreStream.ReadToEnd();
  17.             }
  18.  
  19.             if (showHighScore)
  20.             {
  21.                 highScore = storedHighScore;
  22.             }
  23.  
  24.             using (var highScoreStream = new StreamWriter(store.CreateFile(highScoreFileName)))
  25.             {
  26.                 showHighScore = !showHighScore;
  27.                 highScoreStream.WriteLine(showHighScore.ToString());
  28.                 highScoreStream.WriteLine(storedHighScore.ToString());
  29.             }
  30.         }
  31.         mtx.ReleaseMutex();
  32.     }
  33.  
  34.     return highScore;
  35. }

The following code shows how the PeriodicTask is created / renewed and scheduled to update the Live Tile of the application.

Creating the PeriodicTask
  1. public static void PeriodicTileUpdater()
  2. {
  3.     PeriodicTask periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;
  4.  
  5.     if (periodicTask != null)
  6.     {
  7.         RemoveAgent(periodicTaskName);
  8.     }
  9.  
  10.     periodicTask = new PeriodicTask(periodicTaskName)
  11.     {
  12.         Description = "Periodic Task to Update the ApplicationTile"
  13.     };
  14.  
  15.     // Place the call to Add in a try block in case the user has disabled agents.
  16.     try
  17.     {
  18.         ScheduledActionService.Add(periodicTask);
  19.  
  20.         // If debugging is enabled, use LaunchForTest to launch the agent in one minute.
  21. #if DEBUG_TASK
  22.         ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(30));
  23. #endif
  24.     }
  25.     catch (InvalidOperationException)
  26.     {
  27.     }
  28. }

To make debugging easier, the PeriodicTask will execute every 30 seconds in debug mode, instead of every 30 minutes. The other important piece of functionality is in the PeriodicTask itself. The OnInvoke method is started every 30 minutes (every 30 seconds in debug mode). It retrieves the information to be displayed on the back of the Application Tile.

Heart of the PeriodicTask
  1. protected override void OnInvoke(ScheduledTask task)
  2. {
  3.     if (task.Name.Contains(clickerTaskName))
  4.     {
  5.         // Application Tile is always the first Tile, even if it is not pinned to Start.
  6.         ShellTile TileToFind = ShellTile.ActiveTiles.First();
  7.                
  8.         if (TileToFind != null)
  9.         {
  10.             string backContent = LiveTile.GetLiveTileBack();
  11.  
  12.             if (backContent == string.Empty)
  13.             {
  14.                 backContent = "Isn't it time to play again";
  15.             }
  16.  
  17.             StandardTileData NewTileData = new StandardTileData
  18.             {
  19.                 BackContent = backContent
  20.             };
  21.  
  22.             TileToFind.Update(NewTileData);
  23.         }
  24.  
  25. #if DEBUG_TASK
  26.         ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(30));
  27. #endif
  28.     }
  29.  
  30.     NotifyComplete();
  31. }

At the end of the OnInvoke method you will see a call to NotifyComplete. This call is important because it releases resources of the PeriodicTask. Omitting to do this means the PeriodicTask will not be rescheduled to run again after the specified interval in debug mode or after the fixed interval in release mode.

image