MessageBox, Navigation and Application Life Cycle

One of our applications failed certification today because of an issue I should have known about. Even though the scenario in which an exception occurs is fairly easy, solving the problem properly involves a little work and a little thinking. Other blog entries have been written about this particular problem, although suggested solutions did not seem to work for me. Let me first show the original code:

MessageBox and Navigation
  1. private void TurnCard_Click(object sender, System.Windows.RoutedEventArgs e)
  2. {
  3.     MessageBoxResult mr = MessageBoxResult.Cancel;
  4.  
  5.     if (nrTimesClicked > 2)
  6.     {
  7.         mr = MessageBox.Show("Continuing now might confuse you. Try again tomorrow?",
  8.             "Continuing tomorrow?", MessageBoxButton.OKCancel);
  9.     }
  10.  
  11.     if (mr == MessageBoxResult.OK)
  12.     {
  13.         NavigationService.GoBack();
  14.     }
  15.     else
  16.     {
  17.         Random r = new Random();
  18.         int card = r.Next(cardPages.Length);
  19.         NavigationService.Navigate(new Uri(cardPages[card], UriKind.Relative));
  20.         nrTimesClicked++;
  21.     }
  22. }

Running this code and clicking the Start button on the phone while the MessageBox is visible results in the following exception when running with the debugger attached (it results in an application termination when running stand-alone):

image

The NavigationFailed event is raised. This is caused by the fact that the MessageBox returns when clicking the phone’s Start button with a return value of MessageBoxResult.Cancel. Since in the above code fragment, the Cancel button is used to navigate to some page, even though the application is supposed to go to the background in order to display the start screen on the phone, navigation fails. The interesting part is that the application does not have a clue that the user pressed the Start button on the phone. So some thinking is required to fix this issue.

Single stepping through the problematic method TurnCard_Click showed another behavior:

image

This at least made clear that indeed the call to the NavigationService caused the problem. To solve the problem, what can be done is protecting calls to the NavigationService by catching this particular exception:

Protecting the Navigate method
  1. private void TurnCard_Click(object sender, System.Windows.RoutedEventArgs e)
  2. {
  3.     MessageBoxResult mr = MessageBoxResult.Cancel;
  4.  
  5.     if (nrTimesClicked > 2)
  6.     {
  7.         mr = MessageBox.Show("Continuing now might confuse you. Try again tomorrow?",
  8.             "Continuing tomorrow?", MessageBoxButton.OKCancel);
  9.     }
  10.  
  11.     if (mr == MessageBoxResult.OK)
  12.     {
  13.         NavigationService.GoBack();
  14.     }
  15.     else
  16.     {
  17.         Random r = new Random();
  18.         int card = r.Next(cardPages.Length);
  19.         try
  20.         {
  21.             NavigationService.Navigate(new Uri(cardPages[card], UriKind.Relative));
  22.         }
  23.         catch (InvalidOperationException)
  24.         {
  25.             ;
  26.         }
  27.         nrTimesClicked++;
  28.     }
  29. }

This does solve the problem, although I don’t like it that an exception is thrown in a situation that the operating system should somehow prevent us against (maybe by returning some other value when the MessageBox returns without the user clicking on one of its buttons). If you want to have a little more flexibility, and don’t mind coding a bit more, there is another possible solution. Instead of using a MessageBox, you can make use of the Guide.BeginShowMessageBox method that is defined in the XNA Framework. This method is a bit more complex, but also much more flexible then its Silverlight counterpart. BeginShowMessageBox is asynchronous, which means that you need to take care with calling code that is supposed to run on the UI Thread.

Using BeginShowMessageBox
  1. private void TurnCard_Click(object sender, System.Windows.RoutedEventArgs e)
  2. {
  3.     if (nrTimesClicked > 2)
  4.     {
  5.         ShowContinueMessage();
  6.     }
  7.     else
  8.     {
  9.         Random r = new Random();
  10.         int card = r.Next(cardPages.Length);
  11.         nrTimesClicked++;
  12.         NavigationService.Navigate(new Uri(cardPages[card], UriKind.Relative));
  13.     }
  14. }
  15.  
  16. private void ShowContinueMessage()
  17. {
  18.     List<string> mbOptions = new List<string>();
  19.     mbOptions.Add("OK");
  20.     mbOptions.Add("Cancel");
  21.     string msg = "Continuing now might confuse you. Try again tomorrow?";
  22.     string title = "Continuing tomorrow?";
  23.     Guide.BeginShowMessageBox(title, msg, mbOptions, 0, MessageBoxIcon.Alert, EnteredAnswer, null);
  24.     messageBoxVisible = true;
  25. }
  26.  
  27. private void EnteredAnswer(IAsyncResult ar)
  28. {
  29.     int? result = Guide.EndShowMessageBox(ar);
  30.  
  31.     if (result != null)
  32.     {
  33.         messageBoxVisible = false;
  34.     }
  35.  
  36.     if (result != null && result == 0)
  37.     {
  38.         this.Dispatcher.BeginInvoke(delegate
  39.         {
  40.             NavigationService.GoBack();
  41.         });
  42.     }
  43.     else if (result != null)
  44.     {
  45.         Random r = new Random();
  46.         int card = r.Next(cardPages.Length);
  47.         this.Dispatcher.BeginInvoke(delegate
  48.         {
  49.             NavigationService.Navigate(new Uri(cardPages[card], UriKind.Relative));
  50.         });
  51.     }
  52. }

The interesting code can be found in the EnteredAnswer method, where we retrieve the key the user entered in the message box. Since EndShowMessageBox returns a nullable integer, it has this nice way of using null in those cases where the user did not click any key (in other words, for instance when the message box is removed as a result of the application going to the background). So now we have a way of detecting if we can navigate (result has a value other then null). The sample code also sets a boolean variable messageBoxVisible, which is used in combination with PhoneApplicationPage.State to display the message box again when the user returns to the application. Hopefully this time the application will pass certification.

EvenTiles from Start to Finish–Part 14

In the previous episode of this series about how to develop a Windows Phone application from scratch we found out that special care must be taken when data must be passed between an application and its PeriodicTask. You learned how data can be protected against mutual access by using a Mutex object. You also learned that you cannot pass data directly from one to another, because the application and its PeriodicTask execute inside different processes.

In this episode of EvenTiles you will learn how you can make use of IsolatedStorage to pass data from the application to the PeriodicTask. Since we already created a separate project in the EvenTiles solution that is taking care of passing data, we can simply modify functionality in that project (EvenTilesComm) to use a file to pass data between the application and its PeriodicTask. Data protection against mutual access is already in place, so we can concentrate on file access. Hopefully the design decision in part 13 to make use of private methods that are called each time we access a public property inside the TileData class starts to make sense now.

What we want to achieve is the following:

  • From inside the application we can store a string containing content for the backside of a Secondary Tile in a file at any time
  • Our PeriodicTask executes approximately once per 30 minutes and it either displays the string passed by the application on the backside of the Secondary Tile or it displays a default string that is defined inside the PeriodicTask
  • The content of the backside of the Secondary Tile needs to toggle each time the PeriodicTask executes
  • If the EvenTiles user modifies the string to be displayed inside the Settings page, it will immediately be displayed on the Secondary Tile (if it exists)

In order to pass data between the application and the PeriodicTask we will extend the private retrieve / store methods inside the TileData class by adding a call to a couple of other private methods. Those new private methods will use a file in IsolatedStorage to read / write data from, meaning we can effectively pass data between the application and its PeriodicTask.

Properties to access Tile Data
  1. private static string RetrieveSecondaryBackContent()
  2. {
  3.     mtx.WaitOne();
  4.  
  5.     try
  6.     {
  7.         RetrieveTileContent();
  8.         return secondaryBackContent;
  9.     }
  10.     finally
  11.     {
  12.         mtx.ReleaseMutex();
  13.     }
  14. }
  15.  
  16. private static void StoreSecondaryBackContent(string content)
  17. {
  18.     mtx.WaitOne();
  19.  
  20.     try
  21.     {
  22.         secondaryBackContent = content;
  23.         PersistTileContent();
  24.     }
  25.     finally
  26.     {
  27.         mtx.ReleaseMutex();
  28.     }
  29. }

A new string to be displayed on the back side of a Secondary Tile will be stored by the application each time users modify their own tile text in the Settings Page of the EvenTiles application (something that will also be done initially when the application starts). The PeriodicTask simply retrieves that data (since now the data is persisted in a file this will work properly) and displays it on the back side of the Secondary Tile. Each time data needs to be stored a new file is created in IsolatedStorage or an existing file is overwritten. Each time data needs to be retrieved, we check if a file containing that data exists. There are small ways to optimize data access in the TileData class, because right now we simply read / write all file content when retrieving / storing single property values. However, this approach simplifies the code and the overhead with only two different variables is very small.

Using IsolatedStorage
  1. private const string contentFileName = "EvenTileContent.txt";
  2.  
  3. private static void PersistTileContent()
  4. {
  5.     using (var store = IsolatedStorageFile.GetUserStoreForApplication())
  6.     {
  7.         using (var contentStream = new StreamWriter(store.CreateFile(contentFileName)))
  8.         {
  9.             contentStream.WriteLine(showDefaultSecondaryBackContent.ToString());
  10.             contentStream.WriteLine(secondaryBackContent);
  11.         }
  12.     }
  13. }
  14.  
  15. private static void RetrieveTileContent()
  16. {
  17.     using (var store = IsolatedStorageFile.GetUserStoreForApplication())
  18.     {
  19.         if (store.FileExists(contentFileName))
  20.         {
  21.             using (var contentStream = new StreamReader(store.OpenFile(contentFileName, FileMode.Open)))
  22.             {
  23.                 showDefaultSecondaryBackContent = Convert.ToBoolean(contentStream.ReadLine());
  24.                 secondaryBackContent = contentStream.ReadToEnd();
  25.             }
  26.         }
  27.     }
  28. }

With the way we organized the functionality inside the TileData class in the previous episode of this development series, these are the only new methods necessary in order to pass data. When the user installs a Secondary Tile for the EvenTiles application and modifies its back string content through the Settings page, this is the result (changing the back content of the Secondary Tile every 30 minutes):

image

The following video shows EvenTiles in action with proper transfer of data between the application and its PeriodicTask.

Data transfer between an Application and a PeriodicTask through IsolatedStorage

To be able to experiment with this working implementation of EvenTiles, especially to understand how the application interacts with the PeriodicTask through a file in IsolatedStorage, the sample code is available for dowload here.

Right now we have the basic functionality of EvenTiles more or less ready, although the About Page still needs to get some content. That is something we will work on in the next part of EvenTiles. After that we will cover much more in the upcoming episodes of EvenTiles including but not limited to

  • using ads in the application
  • retrieving location information inside the application
  • taking pictures
  • modifying pictures
  • using alarms and notifications
  • using Visual Studio’s integrated Performance Analysis to find performance bottlenecks inside the application
  • submitting the application for certification

EvenTiles will continue soon so stay tuned for the next episode.

EvenTilesIf you want to see EvenTiles already in action on your Windows Phone, you can also install the latest version from Marketplace. Remember that this application is not meant to be extremely useful, although it contains similar functionality that “serious” applications have. Just go ahead and get your free copy of EvenTiles from Marketplace at this location: http://www.windowsphone.com/en-US/search?q=EvenTiles (or search on your phone for EvenTiles in the Marketplace application).

EvenTiles from Start to Finish–Part 13

In the previous episode of this series about how to develop a Windows Phone application from scratch we fixed some issues to properly start and renew a PeriodicTask. Now we are ready to find out how an application can communicate with its PeriodicTask.

In today’s EvenTiles episode, you will learn why you cannot simply use a variable to communicate between the application and the PeriodicTask. In my opinion that is important, because understanding why some things are not working makes you a better Windows Phone developer and decreases the chance of having hard to trace bugs inside your own applications. In order to separate the functionality to transfer data between the application and its PeriodicTask, we are going to create a new project inside the EvenTiles solution.

Dump1

The project will be of type Windows Phone Class Library and we will call it EvenTilesComm. In its initial version, this class library will contain one single class with the name TileData. It is used to store the text that the user can enter in the Settings Page of the EvenTiles application in order to allow the PeriodicTask to display this string on the back of the Secondary Tile once it is created. In order to vary the text on the back of the Secondary Tile, TileData will also contain a boolean variable indicating which string needs to be displayed on the Secondary Tile’s backside (either the string passed by the application or a default string that is defined inside the PeriodicTask).

screenTo be able to access TileData from within both the EvenTiles application and the PeriodicTask, it contains two static properties. A string property to store / retrieve the message that is defined through the Settings Page and a boolean property that defines which string needs to be displayed from within the PeriodicTask. The string property is always written by the application and read by the PeriodicTask. The boolean variable is both written by the application and the PeriodicTask but only read by the PeriodicTask. Because of the fact that the PeriodicTask and the application are running inside their own, separate process in different threads, and since they are running completely unsynchronized from each other, there is a possibility that they both want to access one of the properties of TileData at the same time. To prevent this potential dangerous situation (dangerous because it can leave the properties in an undefined state when one of the two different threads want to access them while the other is updating them), both properties are protected by a Mutex synchronization object.

NOTE: The following (initial) implementation of the TileData class will not work properly, but it is shown here to help you understand what it means that an application and its PeriodicTask belong to each other, but are completely separated from each other at the same time. You will have to wait a little while for a working solution, because that will be introduced in the next episode of EvenTiles.

Threadsafe Data Access
  1. public class TileData
  2. {
  3.     private static Mutex mtx = new Mutex(false, "MtxSync");
  4.  
  5.     private static string secondaryBackContent;
  6.     private static bool showDefaultSecondaryBackContent;
  7.  
  8.  
  9.     public static string SecondaryBackContent
  10.     {
  11.         get
  12.         {
  13.             return RetrieveSecondaryBackContent();
  14.         }
  15.         set
  16.         {
  17.             StoreSecondaryBackContent(value);
  18.         }
  19.     }
  20.  
  21.     public static bool ShowDefaultSecondaryBackContent
  22.     {
  23.         get
  24.         {
  25.             return RetrieveShowDefaultSecondaryBackContent();
  26.         }
  27.         set
  28.         {
  29.             StoreShowDefaultSecondaryBackContent(value);
  30.         }
  31.     }
  32.  
  33.     private static string RetrieveSecondaryBackContent()
  34.     {
  35.         mtx.WaitOne();
  36.  
  37.         try
  38.         {
  39.             return secondaryBackContent;
  40.         }
  41.         finally
  42.         {
  43.             mtx.ReleaseMutex();
  44.         }
  45.     }
  46.  
  47.     private static void StoreSecondaryBackContent(string content)
  48.     {
  49.         mtx.WaitOne();
  50.  
  51.         try
  52.         {
  53.             secondaryBackContent = content;
  54.         }
  55.         finally
  56.         {
  57.             mtx.ReleaseMutex();
  58.         }
  59.     }
  60.  
  61.     private static bool RetrieveShowDefaultSecondaryBackContent()
  62.     {
  63.         mtx.WaitOne();
  64.  
  65.         try
  66.         {
  67.             return showDefaultSecondaryBackContent;
  68.         }
  69.         finally
  70.         {
  71.             mtx.ReleaseMutex();
  72.         }
  73.     }
  74.  
  75.     private static void StoreShowDefaultSecondaryBackContent(bool showDefaultContent)
  76.     {
  77.         mtx.WaitOne();
  78.  
  79.         try
  80.         {
  81.             showDefaultSecondaryBackContent = showDefaultContent;
  82.         }
  83.         finally
  84.         {
  85.             mtx.ReleaseMutex();
  86.         }
  87.     }
  88. }

If you look at the source code of the TileData class, you can see that we are using a two properties through which we are calling a few private methods to actually store or retrieve data. You will also see that we define a single Mutex inside the TileData class. This Mutex has a name, meaning it can be used to synchronize threads over multiple processes. This is important, since EvenTiles and its PeriodicTask will execute in separate processes. If we take a look at one of the individual retrieval methods, you will see how the single Mutex that is defined in TileData is used.

Retrieving data
  1. private static string RetrieveSecondaryBackContent()
  2. {
  3.     mtx.WaitOne();
  4.  
  5.     try
  6.     {
  7.         return secondaryBackContent;
  8.     }
  9.     finally
  10.     {
  11.         mtx.ReleaseMutex();
  12.     }
  13. }

In this method, we access the variable secondaryBackContent only when the method WaitOne on our Mutex returns. When WaitOne returns, our method has exclusive access to the variable secondaryBackContent until we call the method ReleaseMutex on our Mutex. At that moment, another thread that is waiting for the same Mutex will be granted access. Every method that uses of a Mutex to get access to protected data must under all circumstances call ReleaseMutex when it is done. That is the reason why we are adding a try / finally block. The code in the finally block will execute, even when exceptions are thrown. In this way, we prevent our application from a potential deadlock situations (where multiple threads are waiting on each other to free up a synchronization object that is never being freed).

The way data is protected for EvenTiles works properly, which can be verified by debugging the application and deliberately skipping a call to ReleaseMutex from within the EvenTiles application (which is fully explained in the accompanying video as well). Doing so will result in the PeriodicTask waiting forever for the Mutex, because it will never be released by the application. This at least proves that both EvenTiles and its PeriodicTask are making use of the same Mutex that they both need to own before being able to access variables.

There is still a potential problem, because we are calling the WaitOne method without parameters, which means that we will wait indefinitely until the Mutex becomes available. In our simple example this is sufficient, but in a real application you most likely want to wait for a specific time and take action upon timeouts.

However, there is a way bigger problem with the current implementation of our newly created TileData class. We already saw that the Mutex is properly shared between EvenTiles and its PeriodicTask, but what about the public properties. The following screen dump shows you what is wrong with the TileData class right now. Even though the variable secondaryBackContent is set by the EvenTiles application, it seems that it is not initialized when the PeriodicTask retrieves the variable (both through the appropriate properties).

image image

Since our EvenTiles application and its PeriodicTask are running in separate processes, they are completely separated from each other, meaning that they get their own copies of variables they both want to access, even though these variables are defined in a separate project. This is a good thing (even though we have to solve the problem), because otherwise all variables used by every process on the phone would need a unique name. The following video shows EvenTiles in action in combination with its PeriodicTask. It shows how the Mutex works and how passing data fails.

Protecting variables against simultaneous access by multiple threads

To be able to experiment with this wrong implementation of EvenTiles, especially to understand how the application interacts with the PeriodicTask, the sample code is available for dowload here.

Instead of using ‘simple’ variables to pass data between EvenTiles and its PeriodicTask, we will have to make use of IsolatedStorage and have them share data through a file. That will be the topic of the next episode of EvenTiles.

EvenTiles from Start to Finish–Part 12

In the previous episode of this series about how to develop a Windows Phone application from scratch we talked about debugging a PeriodicTask. Before digging deeper into exchanging data between an application and its PeriodicTask, we need to talk a little more about scheduling the PeriodicTask and about expiration of a PeriodicTask.

Going back to part 10 of the EvenTiles series, the PeriodicTask was created inside the MainPage.xaml.cs file in a method called StartPeriodicAgent. This private method takes care of stopping a currently active agent before creating a new one. It also handles an exception that might be thrown when an attempt is made to start a new PeriodicTask while the user has disabled background processing for the EvenTiles application, which they can do from inside the Phone Settings.

However, after submitting EvenTiles to Marketplace, I noticed an exceptionally high crash count in the application (as you can see from my AppHub dashboard). Since I want to share all details about developing this application, but also about the application’s life cycle, it is only fair to share the number of crashes to date, a number I am not proud off.

image

For starters, the first version of EvenTiles called LaunchForTest in release mode which results in a thrown exception as shows up in the call stack of various crash incidents. Also, the application does not count on other applications making use of background agents on a particular device. To preserve memory, but mainly battery power on the device, the number of background agents that can run at the same time is limited. It varies depending on the hardware capabilities of the device and might differ between devices, but it is a small number and therefore the limit can easily be reached. When this limit is reached, a SchedulerServiceException will be thrown whenever you attempt to add a periodic task. Of course you much handle this exception to prevent your application against crashing, since you are adding your periodic task from inside your application.

So, to create a periodic task, the following code should be used (which is an extension to the code that we used in part 10 of the series):

Correctly adding the agent
  1. private void StartPeriodicAgent()
  2. {
  3.     RemovePeriodicAgent();
  4.  
  5.     var evenTilesPeriodicTask = new PeriodicTask(evenTilesPeriodicTaskName);
  6.     evenTilesPeriodicTask.Description = "EvenTilesPeriodicTask";
  7.  
  8.     try
  9.     {
  10.         ScheduledActionService.Add(evenTilesPeriodicTask);
  11. #if DEBUG_TASK
  12.         ScheduledActionService.LaunchForTest(evenTilesPeriodicTaskName, TimeSpan.FromSeconds(30));
  13. #endif
  14.         App.PeriodicTaskScheduled = true;
  15.     }
  16.     catch (InvalidOperationException ex)
  17.     {
  18.         if (ex.Message.Contains("BNS Error: The action is disabled"))
  19.         {
  20.             MessageBox.Show("Background agents for this application are disabled.");
  21.         }
  22.     }
  23.     catch (SchedulerServiceException)
  24.     {
  25.         MessageBox.Show("Can't schedule your background agent. There might be too many background agents enabled. You can disable background agents through the phone's settings application.");
  26.     }
  27. }

If you take a look at how a periodic task is created you will also see that a App.PeriodicTaskScheduled is set to true. This static property is maintained in the App.xaml.cs file, its value is stored / retrieved from the IsolatedStorageSettings (see part 5 of EvenTiles for more information).

The reason to add this boolean property is to find out if the application did schedule a PeriodicTask. If a PeriodicTask was added for the application, you must realize that the PeriodicTask will age and eventually it will expire unless it is rescheduled by the application. A PeriodicTask will expire if it has not been rescheduled for 14 days from the time it was scheduled. Since the application is responsible for adding a PeriodicTask, it means that the PeriodicTask will only continue to run if the application is activated at least once every two weeks and if the application makes sure to reschedule the PeriodicTask. The approach that EvenTiles takes right now is to check if at some time a PeriodicTask was scheduled. If so, it will be rescheduled as soon as the EvenTiles’ MainPage is created.

NOTE: We could have used another way to determine if a PeriodicTask was scheduled, for instance by verifying if a SecondaryTile is currently available on the StartScreen.

Making use of IsolatedStorageSettings, we will add logic to the app.xaml.cs file to properly store and retrieve the App.PeriodicTaskScheduled property when the application is started, activated, deactivated and terminated.

To begin, a new property and a new const string to identify the value in the IsoloatedStorageSettings are created in app.xaml.cs as follows:

  1. public const string keyPTScheduled = "K_PTS";
  2.  
  3. public static bool PeriodicTaskScheduled { get; set; }

In the constructor, the PeriodicTaskScheduled property is explicitly initialized to false. Finally, the value of PeriodicTaskScheduled is stored / retrieved in the various application life cycle events:

Store/Retrieve property value
  1. // Code to execute when the application is launching (eg, from Start)
  2. // This code will not execute when the application is reactivated
  3. private void Application_Launching(object sender, LaunchingEventArgs e)
  4. {
  5.     if (appSettings.Contains(keyPTScheduled))
  6.     {
  7.         PeriodicTaskScheduled = (bool)appSettings[keyPTScheduled];
  8.     }
  9.  
  10.     if (!appSettings.Contains(keyActSecBackContent))
  11.     {
  12.         appSettings[keyActSecBackContent] = DefaultSecBackContent;
  13.     }
  14.     ActualSecBackContent = (string)appSettings[keyActSecBackContent];
  15. }
  16.  
  17. // Code to execute when the application is activated (brought to foreground)
  18. // This code will not execute when the application is first launched
  19. private void Application_Activated(object sender, ActivatedEventArgs e)
  20. {
  21.     if (!e.IsApplicationInstancePreserved)
  22.     {
  23.         PeriodicTaskScheduled = (bool)appSettings[keyPTScheduled];
  24.         ActualSecBackContent = (string)appSettings[keyActSecBackContent];
  25.     }
  26. }
  27.  
  28. // Code to execute when the application is deactivated (sent to background)
  29. // This code will not execute when the application is closing
  30. private void Application_Deactivated(object sender, DeactivatedEventArgs e)
  31. {
  32.     appSettings[keyPTScheduled] = PeriodicTaskScheduled;
  33.     appSettings[keyActSecBackContent] = ActualSecBackContent;
  34. }
  35.  
  36. // Code to execute when the application is closing (eg, user hit Back)
  37. // This code will not execute when the application is deactivated
  38. private void Application_Closing(object sender, ClosingEventArgs e)
  39. {
  40.     appSettings[keyPTScheduled] = PeriodicTaskScheduled;
  41.     appSettings[keyActSecBackContent] = ActualSecBackContent;
  42. }

Finally, we will use this property inside the MainPage.xaml.cs file when the page is constructed to determine if we need to reschedule a PeriodicTask:

Rescheduling PeriodicTask?
  1. public MainPage()
  2. {
  3.     InitializeComponent();
  4.     if (App.PeriodicTaskScheduled)
  5.     {
  6.         StartPeriodicAgent();
  7.     }
  8. }

Each time the PeriodicTask is scheduled, the App.PeriodicTaskProperty is set to true and a Secondary Tile is created. If the Secondary Tile is removed, the App.PeriodicTaskProperty is set to false as well.

The following video shows you how to modify the existing EvenTiles project to improve the way the PeriodicTask is scheduled as well as the functionality needed to reschedule the PeriodicTask:

Rescheduling a PeriodicTask

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 12 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.

EvenTilesIf you want to see EvenTiles already in action on your Windows Phone, you can also install the latest version from Marketplace. Remember that this application is not meant to be extremely useful, although it contains similar functionality that “serious” applications have. Just go ahead and get your free copy of EvenTiles from Marketplace at this location: http://www.windowsphone.com/en-US/search?q=EvenTiles (or search on your phone for EvenTiles in the Marketplace application).

When EvenTiles continues with part 13, you will learn how to exchange data between an application and its background agent.

EvenTiles from Start to Finish–Part 11

In the previous episode of this series about how to develop a Windows Phone application from scratch we started talking about using a PeriodicTask to perform background processing for our application. You learned how to create a Windows Phone Scheduled Task Agent, a separate project that became part of the EvenTiles solution to host a PeriodicTask. You also learned how the PeriodicTask relates to the EvenTiles to enable background processing for the application. In this episode of EvenTiles we will take a look at how to debug the PeriodicTask.

When you have added a PeriodicTask to your application you may have noticed that the behavior of Visual Studio’s debugger did change. Instead of detaching the debugger if you terminate the application, the debugger remains attached. This allows you to debug the PeriodicTask when the application is no longer executing. This is of course important because typically the PeriodicTask executes without our application being active. Under normal circumstances, a PeriodicTask will run once every 30 minutes for a few seconds. This schedule can not be changed for released applications and is determined by the operating system. Of course debugging a PeriodicTask would be unproductive in this way. Therefore there is a possibility to run your PeriodicTask more frequent under test.

If you take a look at the ScheduledActionService class, you will see that it contains a static method called LaunchForTest. This method allows you to schedule a Periodic Task to run at the time you specify. Since you will only use this method for testing Periodic Tasks, draining the battery by frequently executing code in the background is not really an issue. However, you will must not forget to remove the call to LaunchForTest in your production code. You can for instance do this by making use of conditional compilation. What I like to do is to define a separate symbol (to be used in combination with DEBUG) to control execution of LaunchForTest. Usually in Debug mode you want to test your Periodic Task frequently, but by defining a separate symbol, you can also easily disable calling LaunchForTest, even in Debug mode. The following code fragment defines the DEBUG_TASK constant:

Conditionally defined constant
  1. #if DEBUG
  2. #define DEBUG_TASK
  3. #endif

Since this constant is not defined in Release mode, you don’t have to worry about accidentally adding a call to LaunchForTest in your released application. If you want to test your Periodic Agent with a normal schedule in Debug mode, you can simply change the name of the constant, for instance into NDEBUG_TASK. To make sure that the Periodic Agent will be called more frequent then usual, you can make use of the following code (inside the #if and #endif directives):

Calling Periodic Agent faster
  1. private void StartPeriodicAgent()
  2. {
  3.     RemovePeriodicAgent();
  4.  
  5.     evenTilesPeriodicTask = new PeriodicTask(evenTilesPeriodicTaskName);
  6.     evenTilesPeriodicTask.Description = "EvenTilesPeriodicTask";
  7.  
  8.     try
  9.     {
  10.         ScheduledActionService.Add(evenTilesPeriodicTask);
  11. #if DEBUG_TASK
  12.         ScheduledActionService.LaunchForTest(evenTilesPeriodicTaskName, TimeSpan.FromSeconds(30));
  13. #endif
  14.     }
  15.     catch (InvalidOperationException ex)
  16.     {
  17.         if (ex.Message.Contains("BNS Error: The action is disabled"))
  18.         {
  19.             MessageBox.Show("Background agents for this application are disabled.");
  20.         }
  21.     }
  22. }

As a result, the Periodic Task will now be executed approximately 30 seconds after this statement is executed. After that, the Periodic Task will execute on its normal 30 minute schedule, unless you add the call to LaunchForTest in the DoInvoke method of the Periodic Task as well:

Relaunching Periodic Agent
  1. protected override void OnInvoke(ScheduledTask task)
  2. {
  3.     //TODO: Add code to perform your task in background
  4.  
  5. #if DEBUG_TASK
  6.     ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(30));
  7. #endif
  8.  
  9.     NotifyComplete();
  10. }

The following video shows you how to use the LaunchForTest method inside the EvenTiles application and how to make use of the Visual Studio debugger to test the Periodic Agent:

Debugging a Windows Phone Application’s PeriodicTask using LaunchForTest.

Of course the functionality of the Periodic Agent is still to be determined. In part 12 of EvenTiles we will work on adding functionality for the Periodic Agent.

EvenTiles from Start to Finish–Part 10

In the previous episode of this series about how to develop a Windows Phone application from scratch we talked about creating a Secondary Tile programmatically inside our application and showing different content on both the front and the back of the Secondary Tile.

This time we will introduce the concept of Background Agents for Windows Phone. A Background Agent is a piece of application code that can execute, even when the application is not running. Background Agents can be used to periodically perform some actions. Depending on the type of action and the type of scheduling, Background Agents can be of type PeriodicTask (which runs regularly for short amounts of time) or of type ResourceIntensiveTask (which runs for a longer amount of time, but not on a regular interval). Each application can have at most one PeriodicTask and one ResourceIntensiveTask. There are restrictions in using both PeriodicTask and ResourceIntensiveTask. One of the more important things to keep in mind is that a PeriodicTask will run approximately every 30 minutes for at most a couple of seconds, and it will continue running roughly twice an hour for 14 days in a row (assuming the PeriodicTask does not crash). If the application has not renewed the PeriodicTask within those 14 days, the PeriodicTask will be removed from the schedule. Thinking about it, that makes sense. If a user is not using your application for such a long time, it is probably not necessary to continue executing code for that application in the background.

For EvenTiles we will make use of a PeriodicTask, to allow updating of our Secondary Tile on a regular interval. Since updating the Secondary Tile is a relatively simple action, this is a perfect candidate for a PeriodicTask. In this way we can bring our Secondary Tile to life (after all, things will change to it on the start screen of the user’s phone), regardless of the execution state of our application. This technique can for instance be used to update weather information, or number of newly available emails to simply keep the user informed. In our sample application, we will use a PeriodicTask to simply display different strings on the back of the Secondary Tile. The reason to chose something so simple is to be able to concentrate on the bare functionality of the PeriodicTask, its relation to the application and ways to exchange data between the application and its Periodic Task.

To make use of a PeriodicTask, we need to add a new project to our solution. Visual Studio already contains a template for a Windows Phone Scheduled Task Agent, as shown in the next figure:

image

In the newly created PeriodicTask you will find a method called OnInvoke. That is the method into which you will add the functionality you like to have executed in the background. It is important to call the NotifyComplete method as last statement inside your OnInvoke method. Each time your code executes, it will execute in a separate thread. Since the PeriodicTask runs independent from the application (once the application has started the PeriodicTask), it can not update the User Interface of the application it belongs to.

To be able to start the PeriodicTask from inside your application, the first thing you will do is add a reference to the PeriodicTask in your application’s project:

image

When you have added the reference to the PeriodicTask, you have effectively made a connection between it and the application. This is visible inside the WPAppManifest.xml file:

PeriodicTask in Manifest
  1. <Tasks>
  2.   <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
  3.   <ExtendedTask Name="BackgroundTask">
  4.     <BackgroundServiceAgent Specifier="ScheduledTaskAgent"
  5.                             Name="EvenTilesScheduledTaskAgent"
  6.                             Source="EvenTilesScheduledTaskAgent"
  7.                             Type="EvenTilesScheduledTaskAgent.ScheduledAgent" />
  8.   </ExtendedTask>
  9. </Tasks>

The next thing that needs to be done is starting the PeriodicTask from inside the application. Of course it is good practice to keep the user in control, so we are going to create the PeriodicTask as a result of a user action. In episode 9 of EvenTiles we added a button to the MainPage to create a Secondary Tile. Since we want this Secondary Tile to change its backside text regularly (even without the application being active), it makes sense to create the PeriodicTask as part of the same Click event handler. The code to create and to remove the PeriodicTask looks like this:

Create and Remove PeriodicTask
  1. private void StartPeriodicAgent()
  2. {
  3.     RemovePeriodicAgent();
  4.  
  5.     evenTilesPeriodicTask = new PeriodicTask(evenTilesPeriodicTaskName);
  6.     evenTilesPeriodicTask.Description = "EvenTilesPeriodicTask";
  7.  
  8.     try
  9.     {
  10.         ScheduledActionService.Add(evenTilesPeriodicTask);
  11.     }
  12.     catch (InvalidOperationException ex)
  13.     {
  14.         if (ex.Message.Contains("BNS Error: The action is disabled"))
  15.         {
  16.             MessageBox.Show("Background agents for this application are disabled.");
  17.         }
  18.     }
  19. }
  20.  
  21. private void RemovePeriodicAgent()
  22. {
  23.     var runningPeriodicTask = ScheduledActionService.Find(evenTilesPeriodicTaskName) as PeriodicTask;
  24.     if (runningPeriodicTask != null)
  25.     {
  26.         ScheduledActionService.Remove(evenTilesPeriodicTaskName);
  27.     }
  28. }

Note how we make use of ExceptionHandling to catch an InvalidOperationException. This exception will typically be thrown if the user has disabled background processing for our application, which they can do from inside the Phone Settings. The following picture shows how the user can enable / disable background processing for our application:

image

Calling the methods to create / remove our PeriodicTask from inside our Click event handler is of course a simple action, although you should note that we create the PeriodicTask before creating a Secondary Tile. The reason for that is to allow the PeriodicTask to display a MessageBox to the user in case of problems. By first creating the Secondary Tile we force our application to immediately go to the background, and with that, not being able to show the MessageBox to the user.

Starting/Stopping Agent
  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.             RemovePeriodicAgent();
  9.             secondaryTile.Delete();
  10.             btnInstall.Content = txtInstallTile;
  11.             secondaryTileInstalled = false;
  12.         }
  13.     }
  14.     else
  15.     {
  16.         StartPeriodicAgent();
  17.         StandardTileData NewTileData = new StandardTileData
  18.         {
  19.             BackgroundImage = new Uri("Background.png", UriKind.Relative),
  20.             Title = "EvenTiles",
  21.             Count = 0,
  22.             BackBackgroundImage = new Uri("BackBackTile.png", UriKind.Relative),
  23.             BackTitle = "EvenTiles",
  24.             BackContent = App.ActualSecBackContent
  25.         };
  26.         ShellTile.Create(new Uri("/MainPage.xaml?TileId=Secondary", UriKind.Relative), NewTileData);
  27.     }
  28. }

Since we did not add functionality to our PeriodicTask, it will wake up every 30 minutes to immediately terminate again, because the only thing we are doing inside the PeriodicTask’s OnInvoke method is calling the NotifyComplete method:

An ‘Empty’ PeriodicTask
  1. protected override void OnInvoke(ScheduledTask task)
  2. {
  3.     //TODO: Add code to perform your task in background
  4.     NotifyComplete();
  5. }

I strongly encourage you to take a look at the following video, that shows all the functionality we have so far in action:

PeriodicTask for Background Processing inside a Windows Phone Application

One thing is annoying in our solution so far. If we want to debug our PeriodicTask, we would have to wait 30 minutes each time until code in the PeriodicTask will be executed. How to overcome this problem will be topic of part 11 of our ongoing series around EvenTiles.

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.

EvenTiles from Start to Finish–Part 8

In the previous episode of this series about how to develop a Windows Phone application from scratch we talked about Fast Application Switching and Tombstoning. We saw how Visual Studio 2010 can help us testing Tombstoning scenarios. We also covered how to preserve application data when the application is interrupted by other applications and how to restore that data when returning to the foreground.

Right now we will extend our knowledge about Fast Application Switching and Tombstoning by trying to exactly restore a page after the application returns from the background. For that, we will take a look at the following scenario.

imageThe user is entering data in the textbox inside the SettingsPage. This means that a keyboard is visible and that the textbox has input focus and a blinking cursor at the location where data is entered. Sometime in the middle of entering text, the user hits the start button to activate another application, to return to our application only after a while. Even though we have stored all data the user entered (because we are saving the contents of the textbox when navigating away from the SettingsPage), the text box does not have focus when the user returns to the SettingsPage, nor a cursor positioned at the right location. In order to restore the exact same situation, we need to store additional data when navigating away from the SettingsPage. This leads to another challenge. To store the local page state when we are navigating away from the SettingsPage we can use the following code:

Saving the Page State
  1. protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     if (!e.IsNavigationInitiator)
  4.     {
  5.         TextBox tb = FocusManager.GetFocusedElement() as TextBox;
  6.  
  7.         if (tb != null)
  8.         {
  9.             this.State[keySelectionLength] = tb.SelectionLength;
  10.             this.State[keySelectionStart] = tb.SelectionStart;
  11.         }
  12.     }
  13.     App.ActualSecBackContent = tbBackContent.Text;
  14.     base.OnNavigatedFrom(e);
  15. }

Each time OnNavigatedFrom is called, there is a possibility that the application is moved to the background. If so, the property IsNavigationInitiator is false. If the application is moved to the background, we check if the textbox currently has focus. If so, we will store the location of the cursor by adding entries for both the SelectionStart (location where the cursor is) and SelectionLength. If on the other hand the textbox does not have focus, we don’t have to store page state information, just the Text property of the textbox.

Retrieving page state information back can be done in the OnNavigatedTo method as follows:

Restore the Page State
  1. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     tbBackContent.Text = App.ActualSecBackContent;
  4.     btnRestore.Visibility = tbBackContent.Text.Equals(App.DefaultSecBackContent) ?
  5.         System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;
  6.  
  7.     if (this.State.ContainsKey(keySelectionLength))
  8.     {
  9.         tbBackContent.SelectionLength = (int)this.State[keySelectionLength];
  10.         tbBackContent.SelectionStart = (int)this.State[keySelectionStart];
  11.         focusToTextBox = true;
  12.     }
  13.     base.OnNavigatedTo(e);
  14. }

However, it is not possible to get the focus back to the textbox control in the OnNavigatedTo method, because the different UI elements are not yet initialized when OnNavigatedTo is called. That is the reason to set a boolean variable to true and actually give the textbox focus when the Loaded event on the page is fired. If the application is returning from the background and focusToTextBox is set to true, the tbBackContent textbox will get focus:

Restore textbox input focus
  1. private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
  2. {
  3.     if (focusToTextBox)
  4.     {
  5.         tbBackContent.Focus();
  6.     }
  7. }

If an application would always be tombstoned, this would be sufficient to store / restore state information for the page and to restore the input focus if the textbox had focus when the application was put in the background. However, with Windows Phone Mango, applications can benefit from the Dormant state, where they stay in memory even though being in the background. There is not really a clear distinction from a developer’s point of view between Dormant and Tombstoned, except for the fact that in case of returning from being Tombstoned, the page constructor is executed, something that is not the case when the application returns from Dormant since the application was still in memory. As a consequence, returning from the Dormant state also means that the Loaded event on the page is not fired. So, even though returning to the foreground is faster if we were in the Dormant state, we need some additional logic to give the textbox focus in this case. In order to distinguish between Dormant and Tombstoned, it is possible to set a boolean variable in the constructor of a page to true and check that variable in the OnNavigatedTo method:

Dormant vs Tombstoned
  1. private bool focusToTextBox;
  2. private bool pageConstructed;
  3.  
  4. public SettingsPage()
  5. {
  6.     InitializeComponent();
  7.     pageConstructed = true;
  8. }

The value of the pageConstructed variable determines if we are returning from a Dormant state to the foreground (false) or not. If we are not returning from a Dormant state, we need to determine in OnNavigatedTo if we returned from a Tombstoned state in order to optionally set the focus to the textbox. However, if we are returning from a Dormant situation, the OnNavigatedTo method itself must be used to set focus to the textbox if needed. The modified OnNavigatedTo method looks like this:

Complete Page Reconstruction
  1. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
  2. {
  3.     tbBackContent.Text = App.ActualSecBackContent;
  4.     btnRestore.Visibility = tbBackContent.Text.Equals(App.DefaultSecBackContent) ?
  5.         System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;
  6.  
  7.     if (this.State.ContainsKey(keySelectionLength))
  8.     {
  9.         tbBackContent.SelectionLength = (int)this.State[keySelectionLength];
  10.         tbBackContent.SelectionStart = (int)this.State[keySelectionStart];
  11.         if (!pageConstructed)
  12.         {
  13.             tbBackContent.Focus();
  14.         }
  15.         else
  16.         {
  17.             focusToTextBox = true;
  18.         }
  19.     }
  20.     base.OnNavigatedTo(e);
  21. }

The following video shows how to save and restore the page state for the SettingsPage of EvenTiles for the different application execution states:

Saving Page State and restoring Textbox Focus

Update after video creation: Even though it seems in the video that the application is working properly both when returning from Dormant and from Tombstoning states, this is not entirely the case. Even though the focus of the Textbox is restored properly when needed, the Textbox will also get focus each and every time we return from the background, with the exception of the first time. The reason for that is that the dictionary entries in the Page.State collection were not deleted after usages in the OnNavigatedTo method. The source code for EvenTiles contains a fix for this undocumented application feature.

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 8 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 finally get to the heart and soul of the application, when we are going to create a Secondary Tile.

EvenTiles from Start to Finish–Part 7

In the previous episode of this series about how to develop a Windows Phone application from scratch we used the Isolated Storage Explorer Tool to take a look at the contents of the ApplicationSettings, stored in IsolatedStorage on the device or emulator. This time we continue dealing with our application settings, because we are going to talk about Fast Application Switching and Tombstoning.

As you probably know, only one application can be running in the foreground on a Windows Phone. That application can use as much resources as it needs and should be as responsive as possible to give end users a great experience. Typically, users switch often between applications. They might not even think about different applications, because they are most likely very task oriented. To give end users the best experience, our applications share a responsibility with other applications and with the operating system.

If our application is currently running in the foreground, there are two important reasons for our application to stop running in the foreground:

  1. The user terminates our application by pressing the Back Key on the phone until the entire back stack of pages for our application is empty.
  2. Our application is interrupted because some sort of an event occurred.

The first situation is simple. When our application is terminating, it is our responsibility to store information that we want to persist until the next time our application is running. This is what we did for EvenTiles in part 5 of the series, using the Application_Launching and Application_Closing methods that are defined in the App.xaml.cs file.

NOTE: The description of Fast Application Switching and Tombstoning in this article is valid for Windows Phone Mango, not for previous versions of the operating system.

The following picture shows our application running over time. The user navigated to the SettingsPage on EvenTiles, modified the string value and decided to use the Start Key on the phone to start another application. After a while, the user returns to our application by pressing the Back Key until our SettingsPage is visible again.

image

For the user, this experience is great, because when they come back to our application, it shows up exactly as it was when they moved our application to the background. The operating system simply keeps our application in memory. There are some restrictions with regards to applications using certain resources like the camera. To keep our story lean and mean we will omit those. When the user starts many applications (thus putting more and more applications in the background), at some time the amount of available memory gets so low that another application can no longer be started. In this situation, the operating system decides to remove the oldest application in the background from memory, saving just minimal state information for that application. In this situation, the application that was just removed from memory is said to be Tombstoned. To restore our application from being tombstoned, we not only need to reload our application settings (as we did on the Application_Launching event), but most likely we also need to restore additional data. The Operating System ‘remembers’ the page in our application the user had visible when we were tombstoned. It is our responsibility to restore data that the user entered on that page (for instance the contents of a Textbox).

When our application is send to the background, several things happen. On the page that is currently visible, an OnNavigatedFrom event will occur. Also, the Application_Deactivated method in the App.xaml.cs file will be called. When an application is switched to the background, basically three things can happen to it:

  1. The application will become the foreground application again without having entered the tombstone state. In this situation the application can benefit from Fast Application Switching.
  2. The application got tombstoned, but it will become the foreground application after a while. In this situation the application must restore more state information.
  3. The user starts the application again by clicking its icon or tile on the start screen. In this situation, the previous instance of the application is removed and the user should see the application in its initial state.

dump3When you are debugging your application in Visual Studio, the default behavior when the application is moved to the background is for it to remain in memory. However, by modifying one of the project properties (as shown in the screen dump on the left), you can force the application to become tombstoned, regardless from the amount of free memory on the device (emulator). In this way, we as developers have the possibility to test our applications in either state they enter when being moved to the background. You should make sure that you test the tombstone scenario for your application. For instance, if EvenTiles with its current functionality is tested for tombstoning it will crash. This currently has to do with the way that data is initialized. In EvenTiles, we have a string property defined in App.xaml.cs that will later be used to write information to the back side of our Secondary Tile. The SettingsPage already makes use of this property. However, we are initializing this property, named ActualBackSecContent when the application is started in the Application_Launching method.

Activating and Terminating
  1. // Code to execute when the application is launching (eg, from Start)
  2. // This code will not execute when the application is reactivated
  3. private void Application_Launching(object sender, LaunchingEventArgs e)
  4. {
  5.     if (!appSettings.Contains(keyActSecBackContent))
  6.     {
  7.         appSettings[keyActSecBackContent] = DefaultSecBackContent;
  8.     }
  9.     ActualSecBackContent = (string)appSettings[keyActSecBackContent];
  10. }
  11.  
  12. // Code to execute when the application is activated (brought to foreground)
  13. // This code will not execute when the application is first launched
  14. private void Application_Activated(object sender, ActivatedEventArgs e)
  15. {
  16. }
  17.  
  18. // Code to execute when the application is deactivated (sent to background)
  19. // This code will not execute when the application is closing
  20. private void Application_Deactivated(object sender, DeactivatedEventArgs e)
  21. {
  22. }
  23.  
  24. // Code to execute when the application is closing (eg, user hit Back)
  25. // This code will not execute when the application is deactivated
  26. private void Application_Closing(object sender, ClosingEventArgs e)
  27. {
  28.     appSettings[keyActSecBackContent] = ActualSecBackContent;
  29. }

Even though our application is removed from memory when it is tombstoned, if the user navigates through the back stack using the back key on the phone, eventually they will return back to a page of our application. In order to make this happen in case our application was tombstoned, it has to be reloaded again to memory to become active. In this situation, minimal state information was stored by the imageoperating system (for instance which page was the last page the user saw when our application got tombstoned). On returning from tombstoning we will return to that page, but since the application needs to be started completely, classes have to be newly created and code in constructors of those classes will therefor be executed. To distinguish between starting a fresh copy of the application or returning from the background, Application_Launching (fresh restart) or Application_Activated (tombstoning or fast application switching) is called in our App.xaml.cs file. If our application was still in memory, there is no problem, after all, the property ActualSecBackContent still holds its value. If we are returning from a tombstoning situation we do have a problem, since Application_Activated will be called instead of Application_Launching. That is why the exception that is shown in the screen dump above was thrown.

You might think that this problem could easily be solved by initializing the ActualSecBackContent property in the constructor of our App class, but that would mean that we don’t benefit from fast application switching (the situation where our application remains in memory, even though it is in the background). A better solution is to make use of the Application_Activated event as follows:

Switching between BG and FG
  1. // Code to execute when the application is activated (brought to foreground)
  2. // This code will not execute when the application is first launched
  3. private void Application_Activated(object sender, ActivatedEventArgs e)
  4. {
  5.     if (!e.IsApplicationInstancePreserved)
  6.     {
  7.         // The application was not preserved in memory, so we were tombstoned
  8.         // Only in this case we need to re-initialize ActualSecBackContent
  9.         ActualSecBackContent = (string)appSettings[keyActSecBackContent];
  10.     }
  11. }
  12.  
  13. // Code to execute when the application is deactivated (sent to background)
  14. // This code will not execute when the application is closing
  15. private void Application_Deactivated(object sender, DeactivatedEventArgs e)
  16. {
  17.     appSettings[keyActSecBackContent] = ActualSecBackContent;
  18. }

If the application is becoming the foreground application, we check if we were still available in memory. If so (e.IsApplicationInstancePreserved == true) we don’t do anything, otherwise we just initialize the ActualSecBackContent property. There is nothing else to do, because we know that a value with that particular Settings key already is available, since the application was launched at some time before Application_Activated was called. If an application is moved to the background you want to make sure to save everything in such a way that you assume that your application will never return to the background. After all, the application can stay in memory, it might be tombstoned but there is also a possibility that the user starts a brand new instance of the application from the start menu. In the latter case, the existing instance of the application in the background will be removed by the operating system.

NOTE: If you are upgrading an existing application for Mango, at the very least (after converting your project in Visual Studio) you need to only retrieve stored data in the Application_Activated method when e.IsApplicationInstancePreserved is false. In that way your application will immediately benefit from fast application switching.

The following video shows the actions we took to prevent the EvenTiles application from crashing after being reactivated from a tombstoned state:

Fast Application Switching and Tombstoning (1)

With the changes that were described so far added to our application, it no longer crashes if we are returning from a tombstone state. There are however more things that need to be considered when the application is brought back from background to foreground. In the next Episode of EvenTiles we will take a look at restoring Focus on an input control when returning from the background.

If you want to see EvenTiles already in action on your Windows Phone, you can install the latest release from Marketplace. Remember that this application is not meant to be extremely useful, although it contains similar functionality that “serious” applications have. All functionality that you can find in the released version of EvenTiles will be covered in the upcoming episodes of this blog series, together with all source code. Just go ahead and get your free copy of EvenTiles from Marketplace at this location: http://www.windowsphone.com/en-US/search?q=EvenTiles (or search on your phone for EvenTiles in the Marketplace application).

EvenTiles from Start to Finish–Part 6

In the previous episode of this series about how to develop a Windows Phone application from scratch we used IsolatedStorage to persist some data. Since IsolatedStorage is a file store on a Windows Phone device, for exclusive use by a single application, it can be a challenge to look at its contents. Luckily, the Windows Phone 7.1 SDK has a tool available to explore IsolatedStorage contents. In this episode of EvenTiles we will explore this Isolated Storage Explorer Tool.

The Isolated Storage Explorer Tool is a command line tool, which is installed together with the Windows Phone 7.1 SDK in the following folder:

C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.1\Tools (64 bit OS)
or
C:\Program Files\Microsoft SDKs\Windows Phone\v7.1\Tools (32 bit OS)

The tool itself has a lot of parameters, to get contents from IsolatedStorage, to write contents to IsolatedStorage, to specify an application and to specify a device. In a command prompt some limited help information is available:

image

In order to retrieve our ApplicationSettings from IsolatedStorage for EvenTiles, the first thing we need to know is the ProductID for our application. This ide can be found in the WMAppManifest.xml file.

WMAppManifest.xml
  1. <Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.1">
  2.   <App xmlns="" ProductID="{883385e6-52e5-4835-83db-8a17499b5767}" Title="EvenTiles"

The next thing we need to do is make sure that the Emulator is started (or a physical device is connected). Either should have the application installed, but it is not necessary to have the application running. After passing the following command,

image

the folder C:\iso will contain a snapshot of our application’s IsolatedStorage.

image

When we drag and drop the _ApplicationSettings file to Visual Studio 2010, you can see that its contents are XML data, representing a Dictionary with one single entry defined in it, matching our Secondary Tile’s back side string.

image

You might not like using a command line tool to explorer IsolatedStorage. In that case, there is good news for you. If you browse to http://wptools.codeplex.com/, you will find the Windows Phone Power Tools for download. This handy collection of tools embeds the different SDK tools including the Isolated Storage Explorer Tool inside a Windows application. With that application you can explore your application’s IsolatedStorage as well. Using the power tool, it is also easy to write new or modified files to your application’s IsolatedStorage. The latter makes a lot of sense if you want to test new versions of applications against old contents in IsolatedStorage, for instance to migrate old files to new versions.

image

The following video shows the Isolated Storage Explorer Tool and the Windows Phone Power Tools in action.

Using the Isolated Storage Explorer Tool and the Windows Phone Power Tools

So this time we did not add functionality to our EvenTiles application, but it is important to learn about useful tools to help us develop our applications as well. In the next episode we will talk about Tombstoning and Fast Application switching and what we need to do in our application to support these two important execution states on Windows Phone devices.

imageIf you want to see EvenTiles already in action on your Windows Phone, you can install the latest release from Marketplace. Remember that this application is not meant to be extremely useful, although it contains similar functionality that “serious” applications have. All functionality that you can find in the released version of EvenTiles will be covered in the upcoming episodes of this blog series, together with all source code. Just go ahead and get your free copy of EvenTiles from Marketplace at this location: http://www.windowsphone.com/en-US/search?q=EvenTiles (or search on your phone for EvenTiles in the Marketplace application).