Monday, 8 September 2014

Background TimerTask 00

Let's create a timed background task:

Create a regular winRT store app project, I'm going to name mine pc.BackgroundTimer

Once that's done add a winMD (windows run-time component) project to the same solution, I named id pc.BackgroundTimerTask

with that done create a reference from your winRT application to your winMD component. 

with that complete, rename the class1.cs file in your winMD component to something more relevant, I went with TimerTask because I'm super creative... 

Once your class1.cs is renamed open it up and implement the IBackgroundTask interface. That should give your the run method, this method will be what does the work in your background task.

using Windows.ApplicationModel.Background;
using Windows.UI.Notifications;

namespace pc.BackgroundTimerTask
{
    public sealed class TimerTask :IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
        
        }
    }
}

lets add some logic in here, I go with a toast notification 

using Windows.ApplicationModel.Background;
using Windows.UI.Notifications;

namespace pc.BackgroundTimerTask
{
    public sealed class TimerTask :IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            var d = taskInstance.GetDeferral();

            var ToastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);

            //extract all the text elements
            var toastTextElements = ToastXml.GetElementsByTagName("text");

            //set the one text element we have to a value
            toastTextElements[0].AppendChild(ToastXml.CreateTextNode("Woot Woot!!!"));

            //create the toast
            var Toast = new ToastNotification(ToastXml);

            //show the toast in the top right corner
            ToastNotificationManager.CreateToastNotifier().Show(Toast);

            d.Complete();
        }
    }
}


I like to go with a toast notification to make displaying to the user simpler, but you could do a multitude of things here.

so with that done make note of the namespace.className so in my case it's "pc.BackgroundTimerTask.TimerTask", copy that into your clipboard. Now open your the app manifest of your winRT application and go to the Declarations Tab, here you'll have to add a background task, specify that it's a timer, and add the Entry point, which is the "namespace.ClassName" of your task that i told you to note earlier.


with that done, go to the Application tab

here you're going to have to set your toast Capable to yes, why? Because our background task makes toasts. Also set the lock screen notification to badge, why? i'm not really sure, but it's going to force you to make visual assets for your badge as well it will require your app to be pinned to the lock screen for your timer job to fire in windows 8.1 apparently this restriction has been removed for windows 10.

Now go to the visual assets page and follow the errors

You should see the above, just add icons with the corresponding sizes, you only have to add one, Usually the largest, but i generally add all three.

With all that done you can build your solution, it still does nothing, but at least it builds. So lets lets register our background task

using System.Linq;
using Windows.ApplicationModel.Background;
using Windows.UI.Xaml.Controls;

namespace pc.BackgroundTimer
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            //check to make sure that your background task isn't already registred
            if (BackgroundTaskRegistration
                    .AllTasks
                    .FirstOrDefault(t => t.Value.Name == "TimerTask").Value == null)
            {
                var builder = new BackgroundTaskBuilder();
                builder.Name = "TimerTask";
                builder.TaskEntryPoint = "pc.BackgroundTimerTask.TimerTask";
                //waits 15 minutes to schedual the background task, once scheduled it
                //will fire within 15 minutes, indefinitely 
                builder.SetTrigger(new TimeTrigger(15, false));

                var taskRegistration = builder.Register();
            }
        }
    }
}

To keep from registering our task every time we start our app we first check to make sure it's not already registered, the we set it to be scheduled after 15 minutes, once it's scheduled it will fire within 15 minutes. The freshness timer that is the 15 minutes before being scheduled is a variable with the lowest value accepted being 15 minuets anything below that and you'll get an error, the second 15 that is the fired within is a constant, so whether you set your freshness timer to the minimum 15 minutes or 30 minutes (not sure if there's an upper limit) it will still fire within 15 minutes of being scheduled.

now waiting 15 minutes to 30 minutes to test your app seems silly, luckily to trouble shoot it you can force the background task to fire early. Use the  debug toolbar to force the Background task to fire.


and there you go you have a timer task firing.