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:
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:
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:
- <Tasks>
- <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
- <ExtendedTask Name="BackgroundTask">
- <BackgroundServiceAgent Specifier="ScheduledTaskAgent"
- Name="EvenTilesScheduledTaskAgent"
- Source="EvenTilesScheduledTaskAgent"
- Type="EvenTilesScheduledTaskAgent.ScheduledAgent" />
- </ExtendedTask>
- </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:
- private void StartPeriodicAgent()
- {
- RemovePeriodicAgent();
- evenTilesPeriodicTask = new PeriodicTask(evenTilesPeriodicTaskName);
- evenTilesPeriodicTask.Description = "EvenTilesPeriodicTask";
- try
- {
- ScheduledActionService.Add(evenTilesPeriodicTask);
- }
- catch (InvalidOperationException ex)
- {
- if (ex.Message.Contains("BNS Error: The action is disabled"))
- {
- MessageBox.Show("Background agents for this application are disabled.");
- }
- }
- }
- private void RemovePeriodicAgent()
- {
- var runningPeriodicTask = ScheduledActionService.Find(evenTilesPeriodicTaskName) as PeriodicTask;
- if (runningPeriodicTask != null)
- {
- ScheduledActionService.Remove(evenTilesPeriodicTaskName);
- }
- }
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:
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.
- private void btnInstall_Click(object sender, RoutedEventArgs e)
- {
- if (secondaryTileInstalled)
- {
- var secondaryTile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileId=Secondary"));
- if (secondaryTile != null)
- {
- RemovePeriodicAgent();
- secondaryTile.Delete();
- btnInstall.Content = txtInstallTile;
- secondaryTileInstalled = false;
- }
- }
- else
- {
- StartPeriodicAgent();
- StandardTileData NewTileData = new StandardTileData
- {
- BackgroundImage = new Uri("Background.png", UriKind.Relative),
- Title = "EvenTiles",
- Count = 0,
- BackBackgroundImage = new Uri("BackBackTile.png", UriKind.Relative),
- BackTitle = "EvenTiles",
- BackContent = App.ActualSecBackContent
- };
- ShellTile.Create(new Uri("/MainPage.xaml?TileId=Secondary", UriKind.Relative), NewTileData);
- }
- }
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:
- protected override void OnInvoke(ScheduledTask task)
- {
- //TODO: Add code to perform your task in background
- NotifyComplete();
- }
I strongly encourage you to take a look at the following video, that shows all the functionality we have so far in action:
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.
One thought on “EvenTiles from Start to Finish–Part 10”
Comments are closed.