Tags

, , , , , , ,

OK folks, this is my third Windows Phone 8 tutorial blog post in this month and with this I am going to blog about how we can use Scheduled task Agent to build a Background Agent, which will automatically update, the tile of the app and virtually creating a Digital Clock in tile.
WP_UIs

Note, there are limitations in developing a Background Agent which satisfy Windows Phone store certification requirements. Please read http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202942(v=vs.105).aspx to know more about Constraints for all Scheduled Task Types.

Step 1

Create a Windows Phone project solution in Visual Studio

Step 2

In the solution you have created, add a new “Windows Phone Scheduled Task Agent” Project

img add new proj

sch

Now your solution explorer window should be like this

slnexplortr

Step 3

Put a reference to the newly created Scheduled Task Agent project to the main project

Refman

Step 4

Now open ScheduledAgent.cs file in ScheduledTaskAgent1 project. There you can see a method, protected override void OnInvoke(ScheduledTask task) this is where we need to put the code which runs the background agent. There add the following code.

        protected override void OnInvoke(ScheduledTask task)
        {
            //TODO: Add code to perform your task in background
            //UpdateAppTile(GetLastUpdatedTimeMessage()); 
            StandardTileData data = new StandardTileData
            {
                Title = DateTime.Now.ToString("yyyy MMM d - ddd HH:mm"),
                BackgroundImage = new Uri("/Background.png", UriKind.RelativeOrAbsolute),
                BackContent = DateTime.Now.ToString("hh : mm")
            };

            ShellTile.ActiveTiles.First().Update(data);

            // If debugging is enabled, launch the agent again in one minute.
#if DEBUG_AGENT
    ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));
#endif
            NotifyComplete();
        }

Since we are using, background tasks, which are permitted to run every 30 mins, we use #if DEBUG_AGENT to test the app and we need to add #define DEBUG_AGENT at the beginning of the class.

So the ScheduledAgent.cs class looks like,

#define DEBUG_AGENT

using System.Diagnostics;
using System.Windows;
using Microsoft.Phone.Scheduler;
using Microsoft.Phone.Shell;
using System;
using System.Linq;

namespace ScheduledTaskAgent1
{
    public class ScheduledAgent : ScheduledTaskAgent
    {
        /// <remarks>
        /// ScheduledAgent constructor, initializes the UnhandledException handler
        /// </remarks>
        static ScheduledAgent()
        {
            // Subscribe to the managed exception handler
            Deployment.Current.Dispatcher.BeginInvoke(delegate
            {
                Application.Current.UnhandledException += UnhandledException;
            });
        }

        /// Code to execute on Unhandled Exceptions
        private static void UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (Debugger.IsAttached)
            {
                // An unhandled exception has occurred; break into the debugger
                Debugger.Break();
            }
        }

        /// <summary>
        /// Agent that runs a scheduled task
        /// </summary>
        /// <param name="task">
        /// The invoked task
        /// </param>
        /// <remarks>
        /// This method is called when a periodic or resource intensive task is invoked
        /// </remarks>
        protected override void OnInvoke(ScheduledTask task)
        {
            StandardTileData data = new StandardTileData
            {
                Title = DateTime.Now.ToString("yyyy MMM d - ddd HH:mm"),
                BackgroundImage = new Uri("/Background.png", UriKind.RelativeOrAbsolute),
                BackContent = DateTime.Now.ToString("hh : mm")
            };

            ShellTile.ActiveTiles.First().Update(data);

            // If debugging is enabled, launch the agent again in one minute.
#if DEBUG_AGENT
    ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));
#endif
            NotifyComplete();
        }
    }
}

Step 5

Now lets back to our main project’s main page controller class. Which we code like,

#define DEBUG_AGENT

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using BackgroundAgentTileTest.Resources;
using Microsoft.Phone.Scheduler;

namespace BackgroundAgentTileTest
{
    public partial class MainPage : PhoneApplicationPage
    {
        PeriodicTask periodicTask;
        string periodicTaskName = "MyCustomPeriodicAgent"; //we just give a name
        bool agentsAreEnabled = true;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            agentsAreEnabled = true;

            // Obtain a reference to the period task, if one exists
            periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;

            if (periodicTask != null)
            {
                RemoveAgent(periodicTaskName);
            }

            periodicTask = new PeriodicTask(periodicTaskName);

            // The description is required for periodic agents. This is the string that the user
            // will see in the background services Settings page on the device.
            periodicTask.Description = "This demonstrates a periodic task.";

            // Place the call to Add in a try block in case the user has disabled agents.
            try
            {
                ScheduledActionService.Add(periodicTask);

                // If debugging is enabled, use LaunchForTest to launch the agent in one minute.
#if(DEBUG_AGENT)
                ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(1));
#endif
            }
            catch (InvalidOperationException exception)
            {
                if (exception.Message.Contains("BNS Error: The action is disabled"))
                {
                    MessageBox.Show("Background agents for this application have been disabled by the user.");
                    agentsAreEnabled = false;

                }

                if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
                {
                    // No user action required. The system prompts the user when the hard limit of periodic tasks has been reached.

                }

            }
            catch (SchedulerServiceException)
            {
                // No user action required.  
            }
        }

        private void RemoveAgent(string periodicTaskName)
        {
            try
            {
                ScheduledActionService.Remove(periodicTaskName);
            }
            catch (Exception)
            {
            }
        }
    }
}

Just go through the code, I have commented the code well. You can easily understand what is happening actually. Rather then explaining it again, going through the code makes you more good in programming.

Step 6, the final one.

Finally we have to add the support for WideTiles in WMAppManifest.xml file. and we are done.

Advertisements