Background Agents and Scheduled Tasks allow your application to execute to code in the background even when the application is not running in the foreground. This is quite useful in various type of scenarios where you want to update the Live Tile frequently, show a toast notification on getting some data from web service, perform some data synchronization, etc. In this tutorial, we will take a look at how to use Background Agent to update the app tile in Windows Phone 8 application.
The Windows Phone API includes the ScheduledTaskAgent
class which can be used to create Background agents which run on periodic schedules. Two types of tasks can be created which are:
PeriodicTask
: This is useful for scenarios which require a small time to execute. This is run once every 30 minutes and is useful for performing tasks like raising notifications, updating tile, etc. ResourceIntensiveTask
: This is useful when performing operations which require a long amount of time. This task executes for 10 minutes, however there are a lot of criteria related to processor activity which must be fulfilled before the task is executed. You can use this while performing lengthy operations like synchronizing data or uploading pictures.
A Windows Phone application can have only one background agent but it can register both PeriodicTask
as well as ResourceIntensiveTask
. If an application registers both types of tasks, they are both executed at different intervals. The tasks can use a limited amount of memory which is around 11 MB at a given time. If memory usage increase, the task is immediately terminated. If the agents terminated two consecutive times due to unhandled exceptions, they are automatically removed from schedule.
Both the tasks have limited lifetime and are set to expire two weeks from the time they are first registered so it is a good practice to reregister the same before the expiration period. In some of the cases like the agent updating the app tile, lock screen notification, the background agent gets automatically renewed.
There are some unsupported API calls which you simply cannot make from the agent which include accessing the device camera, clipboard, browser, etc. Based on memory usage of device or if the device is running in battery saver mode, there are chances that the agent will not run.
Let's now create a simple application to demonstrate Background agent. Our app will display some random quotes. It will also include a Scheduled Task Agent which will display the quote on the application wide tile at regular intervals.
Open Visual Studio –> New Project –> Windows Phone Blank App and name the application “WPBackgroundAgentApp
”.
Right click on the solution and Add another Project of type “Class Library (Portable)” and name it "Quotes.DataAccess
" as shown below:
On clicking Ok, you will be provided with a dialog box, select settings as shown below:
It is a good idea to have a separate class for Data Access as the same can be then referenced from the Scheduled Agent as well as our Windows Phone app. Add a class called “QuotesRepository.cs” to the DataAccess
project. The code of the class will look like:
public class QuotesRepository
{
public List<string> QuotesList = new List<string>
{
"Attitude is a little thing that makes a big difference",
"We are all in the gutter but some of us are looking at the stars",
"Be not afraid of going slowly, but be afraid of standing still",
"Don't let what you can't do stop you from doing what you can do",
"The man who makes no mistakes does not usually make anything"
};
public string GetRandomQuote()
{
int randomNumber = (new Random()).Next(QuotesList.Count - 1);
return QuotesList[randomNumber];
}
}
We are adding a function GetRandomQuote()
which will return a random quote from the list of quotes. Typically, your Data Access will contain code to access database or some storage mechanism for getting the data. For simplicity and demonstration purposes, we are using a simple list as our data storage.
Adding Scheduled Task Agent To Project
Add a new project to the solution. In the New Project Dialog, select “Windows Phone Scheduled Task Agent” and name it “QuotesTaskAgent1
”.
When the project gets loaded, you will notice that it contains a single class called ScheduledAgent
which derives from ScheduledTaskAgent
. It contains a method OnInvoke()
which gets called when the Schedules Task in invoked. You should place the code which you want to execute in this method.
Add a reference to your Quotes.DataAccess
project in the current project. Add the following using directives in the ScheduledAgent.cs file.
using Quotes.DataAccess;
using Microsoft.Phone.Shell;
using System.Linq;
using System;
Our OnInvoke()
will contain the following code:
protected override void OnInvoke(ScheduledTask task)
{
if (task is PeriodicTask)
{
QuotesRepository repository = new QuotesRepository();
string quotes = repository.GetRandomQuote();
FlipTileData flipTileData = new FlipTileData()
{
BackContent = quotes,
WideBackContent = quotes
};
ShellTile appTile = ShellTile.ActiveTiles.First();
if (appTile != null)
{
appTile.Update(flipTileData);
}
}
#if DEBUG
ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));
#endif
NotifyComplete();
}
We first check whether the task is PeriodicTask
or not. This is not necessary when you are using a single agent but when you are using both the PeriodicTask
and ResourceIntensiveTask
, you can branch your code here. The code then calls the GetRandomQuote()
method in the repository to get a random quote. It then creates a FlipTileData
object to update the App Tile.
The LaunchForTest()
method is used during app development to launch the method on frequent schedule, then it will run on original device. This will only run on apps deployed using the development tools and not on production app. You should remove the calls to this method on your production app. The NotifyComplete()
is called at the end to let the operating system know that our agent has finished executing code.
Integrating the Agent with App
In our Windows Phone App project, add a reference to the Background Agent. In the Add Reference dialog, select the Projects
tab. Select the agent project, QuotesTaskAgent1
, and click Ok.
We also need to update the Manifest file to register our agent. Right click the WMAppManifest.xml file and then click View Code. In the Tasks
element, add the ExtendedTask
element so that it appears as shown below:
<Tasks>
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
<ExtendedTask Name="RandomQuoteTask">
<BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="RandomQuoteTask"
Source="QuotesTaskAgent1" Type="QuotesTaskAgent1.ScheduledAgent" />
</ExtendedTask>
</Tasks>
The specifier should be of type ScheduledTaskAgent
which the Name
and Source
should use the name that you provided while creating the Agent
.
Now, we will add code in our foreground app to register the agent. Open “MainPage.xaml.cs” file and add a private
method called RegisterAgent()
containing the following code:
public MainPage()
{
InitializeComponent();
RegisterAgent();
}
private void RegisterAgent()
{
string taskName = "RandomQuoteTask";
try
{
if (ScheduledActionService.Find(taskName) != null)
{
ScheduledActionService.Remove(taskName);
}
PeriodicTask periodicTask = new PeriodicTask(taskName);
periodicTask.Description = "Random Quote Update On Tile";
ScheduledActionService.Add(periodicTask);
#if DEBUG
ScheduledActionService.LaunchForTest(taskName, TimeSpan.FromSeconds(30));
#endif
}
catch (InvalidOperationException exception)
{
MessageBox.Show(exception.Message);
}
catch (SchedulerServiceException schedulerException)
{
MessageBox.Show(schedulerException.Message);
}
}
You also need to add the reference to the “Quotes.DataAccess
” project in your Windows Phone project and also add the following using directives at the top.
using Microsoft.Phone.Scheduler;
using Quotes.DataAccess;
In the above method, we create a PeriodicTask
object by giving a name and description and register the same with the operating system by calling the Add
method of the ScheduledActionService
. We also check whether the task is already registered. If it is already registered, we remove it first before reregistering it so as to extend the expiration period. We then call the RegisterAgent
method from the MainPage
constructor. There are chances that sometimes the device’s limit of agent has been reached and your Agent
will not be registered. In that case, you need to include some error handling code to alert the user of the same.
Now we need to modify the manifest file to add support for Wide Tiles. Open “WPAppManifest.xml” file and add check the “Support For Large Tiles” checkbox as shown below:
Testing In Emulator
Let's now test the app in the emulator. On running the app, you will be taken to app’s main page. Click on GetQuote
button which displays a random quote on the screen. You will need to pin the tile to the start screen. If the tile is pinned successfully, you will be taken to phone start screen. By default, the medium size tile is pinned to start screen. Tap and hold the tile to change sizes. The first size change will switch to the small tile size. The next size change will expand to the large, wide tile size. Wait for 30 seconds and you will see the Tile getting updated with a random quote.
In this example, we saw how to update the app tile using Background Agent. You can also perform different stuff like making some Http call to fetch data and then display the same using Toast notification.