EvenTiles from Start to Finish - Part 10
Join the DZone community and get the full member experience.
Join For Freein 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:
periodictask in manifest:
<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:
create and remove periodictask:
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.
starting/stopping agent:
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:
an 'empty' periodictask:
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.
source:
http://mstruys.com/2011/12/21/eventiles-from-start-to-finishpart-10/
Opinions expressed by DZone contributors are their own.
Comments