Sumchans
Sumchans

Reputation: 3774

Windows Phone 8.1 Runtime - Background Task Time Trigger

I am trying to trigger a background task towards the end time of a calendar entry. For e.g if the calendar entry is 3pm - 5pm I want the background task to trigger at 5 pm and also I want to have another time trigger setup based on the upcoming calendar entry. At the end of the calendar entry time, I would fetch the details about the next calendar entry by querying the database and have the end time set as the next time trigger. I am not sure on how to set the time as it going to be different every time. So far this is what I am up to:

//Background Task updated for Live Tile
        Windows.Storage.ApplicationDataContainer pageData = Windows.Storage.ApplicationData.Current.LocalSettings;
        pageData.Values["Testing"] = DateTime.Now.ToString();
        bool taskRegistered = false;
        string UpdateTile = "UpdateTile";
        // check if task is already registered
        foreach (var task in BackgroundTaskRegistration.AllTasks)
        {
            if (task.Value.Name == UpdateTile)
            {
                await (new MessageDialog("Task already registered")).ShowAsync();
                taskRegistered = true;
                break;
            }
        }            
        // register a new task
        var builder = new BackgroundTaskBuilder();
        builder.TaskEntryPoint = "TileUpdaterTask.UpdateTile";
        builder.SetTrigger(new TimeTrigger(30, false));
        // Windows Phone app must call this to use trigger types (see MSDN)
        await BackgroundExecutionManager.RequestAccessAsync();
        BackgroundTaskRegistration theTask = builder.Register();

Here is the Windows Runtime Component class to update the live tile:

public sealed class UpdateTile : IBackgroundTask //XamlRenderingBackgroundTask
{
    Windows.Storage.ApplicationDataContainer pageData = Windows.Storage.ApplicationData.Current.LocalSettings;
    public void Run(IBackgroundTaskInstance taskInstance)
    {
        BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();
        ITileSquare150x150Text01 tileContent = TileContentFactory.CreateTileSquare150x150Text01();
        tileContent.TextHeading.Text = "Hello!";
        tileContent.TextBody1.Text = pageData.Values["Testing"].ToString();//"One";
        tileContent.TextBody2.Text = "Two";
        tileContent.TextBody3.Text = "Three";
        TileUpdateManager.CreateTileUpdaterForApplication().Update(tileContent.CreateNotification());
        _deferral.Complete();
    }
}

Please advise.

Upvotes: 0

Views: 825

Answers (1)

kernanb
kernanb

Reputation: 586

Starting from the beginning:

  1. Create a New Windows Phone RT App Solution
  2. Add a new Windows RT Component Project to the Solution
  3. Put the below code in the main class in the Background Task. This code is designed to 'do something' approximately every n minutes (multiples of 30 minutes) (a little different to what you asked for, but you should get the idea). It reads two values from Local Settings - time stamp, and gap time in minutes. These values are set in the main app.

Code:

using System;
using System.Globalization;
using Windows.ApplicationModel.Background;
using Windows.Storage;

namespace WindowsRuntimeComponent1
{
    public sealed class MyBackgroundClass : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Get a deferral, to prevent the task from closing prematurely if asynchronous code is still running.
            BackgroundTaskDeferral deferral = taskInstance.GetDeferral();

            // GET THIS INFO
            ApplicationDataContainer LocalSettings = ApplicationData.Current.LocalSettings;
            double elapsed = (DateTime.Now - Convert.ToDateTime(LocalSettings.Values["time stamp"], CultureInfo.InvariantCulture)).TotalMinutes;
            double remainingMinutes = (int) LocalSettings.Values["gap time minutes"] - elapsed;

            // SEE IF WE CAN DO IT NOW
            if (remainingMinutes > 15)
            {
                // do something, otherwise, wait for the next one
            }

            // FINISH UP
            deferral.Complete();
        }
    }
}
  1. In the main app go to the Package.appxmanifest file
  2. In the declarations tab add 'Background Task' of type 'Timer'
  3. The entrypoint should be 'WindowsRuntimeComponent1.MyBackgroundClass'
  4. In the Mainpage.xaml.cs for the main app, insert the below code into the constructor.

Code:

// UNREGISTER THE EXISTING TASK IF IT EXISTS
var myTask = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(iTask => iTask.Name == "DoSomethingBackground");
if (myTask != null) myTask.Unregister(true);

// REGISTER NEW TASK TO EXECUTE EVERY 30 MINUTES
BackgroundTaskBuilder myTaskBuilder = new BackgroundTaskBuilder() { Name = "DoSomethingBackground", TaskEntryPoint = "WindowsRuntimeComponent1.MyBackgroundClass" };
myTaskBuilder.SetTrigger(new TimeTrigger(30, false));
myTaskBuilder.Register();

// CREATE/RESET THESE VARIABLES
ApplicationData.Current.LocalSettings.Values["gap time minutes"] = 60;
ApplicationData.Current.LocalSettings.Values["time stamp"] = DateTime.Now.ToString(CultureInfo.InvariantCulture);
  1. Build the project for the Background task in debug mode and add the reference ...WindowsRuntimeComponent1\bin\Debug\WindowsRuntimeComponent1.winmd to the main app.
  2. Run the Main app in Debug . From Lifecycle Events in the top menu, select 'DoSomethingBackground' and run it. Put a breakpoint in the MyBackgroundClass.cs to see if it execute correctly.

You'll probably encounter the situation where when you try and run 'DoSomethingBackground' from Lifecycle Events the program just ends abruptly. If this happen, delete the bin and obj files for the main app, rebuild everything, and reattach the .winmd file. This should get it to work again. Also, it's good advice to use Debug.WriteLine() a lot in the Background Task, so when you execute it you can track in the output window what your code is up to. Finally, be careful using datetime formats, and I'd recommend you use CultureInfo.InvariantCulture when storing dates, due to differing global formats.

Upvotes: 3

Related Questions