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.

One thought on “EvenTiles from Start to Finish–Part 12

Comments are closed.