Scheduling Background Agents in Windows Phone 7.1 Mango


Scheduled Tasks & Background Agents allows apps to run in background in Windows Phone while the app is not running in foreground. There are two types of Scheduled Tasks referenced called Periodic Tasks & ResourceIntensive Tasks which helps to implement background agent scaling.

  • Periodic Tasks: Periodic agents run for a small amount of time on a regular recurring interval. Typical scenarios for this type of task include uploading the device’s location and performing small amounts of data synchronization.
  • Resource-Intensive Tasks: This tasks works for long period of time when the phone meets a set of requirements relating to processor activity, power source, and network connection. A typical scenario for this type of task is synchronizing large amounts of data to the phone while it is not being actively used by the user.
  • The Background  Agent LifeCycle for Windows Phone:  The app can have at least of one type of Scheduled tasks either Periodic Tasks or Scheduled Tasks or even both. So the schedule on which the agent runs depends on which type of task it is registered as.

There are some constraints features on both of Periodic Tasks & Resource-Intensive Tasks . For details Click here.

  • Implement Background Tasks for Windows Phone 7.1 Mango : In order to implement it you need to a Windows Phone application project in VS 2010 SP1 from Silverlight for Windows Phone template.

  • Add a new Schedule Task agent Project to add resources for Schedule agent tasks in Windows Phone app.

  • In order to access the Schedule Task apps in Foreground app , we need to add reference of ScheduleTaskAgent1 Project in ScheduledTask project by clicking on add reference-> Project dialog.

  • Now, add the following code in ScheduleAgent.cs file in the ScheduleTaskAgent1 project.

#define

DEBUG_AGENT

using  System.Windows;

using Microsoft.Phone.Scheduler;

using  Microsoft.Phone.Scheduler;

using  Microsoft.Phone.Shell;

using  System;

namespace ScheduledTaskAgent1

{

public class ScheduledAgent : ScheduledTaskAgent

{

private static volatile bool _classInitialized;

///<remarks>

/// ScheduledAgent constructor, initializes the UnhandledException handler

///</remarks>

public ScheduledAgent()

{

if (!_classInitialized)

{

_classInitialized = true;

// Subscribe to the managed exception handler

Deployment.Current.Dispatcher.BeginInvoke(delegate

{

Application.Current.UnhandledException += ScheduledAgent_UnhandledException;

});

}

}

/// Code to execute on Unhandled Exceptions

private void ScheduledAgent_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)

{

if (System.Diagnostics.Debugger.IsAttached)

{

// An unhandled exception has occurred; break into the debugger

System.Diagnostics.

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 overridevoid OnInvoke(ScheduledTask task)

{

//TODO: Add code to perform your task in background

string toastMessage = “Hello WP7″;

if (task isPeriodicTask)

{

toastMessage = “Periodic task running.”;

}

else

{

toastMessage = “Resource-intensive task running.”;

}

// The toast will not be shown if the foreground application is running.

ShellToast toast = newShellToast();

toast.Title = “Background Agent Sample”;

toast.Content = toastMessage;

toast.Show();

#if

DEBUG_AGENT

ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));

#endif

// Call NotifyComplete to let the system know is done working .

NotifyComplete();

}

}

}

  • So, Next to build the Forgeound App Project , so move to MainPage.xaml in ScheduleTask Project of Windows Phone.

MainPage.Xaml:  Modify the code inside the Grid name called ContentPanel.

<Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″>

<StackPanel>

<StackPanel Orientation=”Vertical” Name=”PeriodicStackPanel” Margin=”0,0,0,40″>

<TextBlock Text=”Periodic Agent” Style=”{StaticResource PhoneTextTitle2Style}” />

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”name:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding Name}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”is enabled” VerticalAlignment=”Center” Style=”{StaticResource PhoneTextAccentStyle}” />

<CheckBox Name=”PeriodicCheckBox” IsChecked=”{Binding IsEnabled}” Checked=”PeriodicCheckBox_Checked” Unchecked=”PeriodicCheckBox_Unchecked” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”is scheduled:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding IsScheduled}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”last scheduled time:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding LastScheduledTime}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”expiration time:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding ExpirationTime}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”last exit reason:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding LastExitReason}” />

</StackPanel>

</StackPanel>

<StackPanel Orientation=”Vertical” Name=”ResourceIntensiveStackPanel” Margin=”0,0,0,40″>

<TextBlock Text=”Resource-intensive Agent” Style=”{StaticResource PhoneTextTitle2Style}” />

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”name:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding Name}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”is enabled” VerticalAlignment=”Center” Style=”{StaticResource PhoneTextAccentStyle}” />

<CheckBox Name=”ResourceIntensiveCheckBox” IsChecked=”{Binding IsEnabled}” Checked=”ResourceIntensiveCheckBox_Checked” Unchecked=”ResourceIntensiveCheckBox_Unchecked” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”is scheduled:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding IsScheduled}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”last scheduled time:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding LastScheduledTime}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”expiration time:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding ExpirationTime}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”last exit reason:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding LastExitReason}” />

</StackPanel>

</StackPanel>

</StackPanel>

</Grid>

</Grid>

  • Add the following code in MainPage.xaml.cs:

MainPage.xaml.cs:

#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.Documents;

using  System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using  System.Windows.Shapes;

using  Microsoft.Phone.Controls;

using  Microsoft.Phone.Scheduler;

namespace ScheduledTask

{

public partial class MainPage : PhoneApplicationPage

{

PeriodicTask periodicTask;

ResourceIntensiveTask resourceIntensiveTask;

string periodicTaskName = “PeriodicAgent”;

string resourceIntensiveTaskName = “ResourceIntensiveAgent”;

public bool agentsAreEnabled = true;

// Constructor

public MainPage()

{

InitializeComponent();

}

private void StartPeriodicAgent()

{

agentsAreEnabled = true;

periodicTask = ScheduledActionService.Find(periodicTaskName) asPeriodicTask;

if (periodicTask != null)

{

RemoveAgent(periodicTaskName);

}

periodicTask = newPeriodicTask(periodicTaskName);

periodicTask = newPeriodicTask(periodicTaskName);

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);

PeriodicStackPanel.DataContext = periodicTask;

// If debugging is enabled , use LaunchForTest to launch the agent in one minutes

#if

(DEBUG_AGENT)

ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(60));

#endif

}

catch (InvalidOperationException exception)

{

if (exception.Message.Contains(“BNS Error: The action is disabled”))

{

MessageBox.Show(“Bakcground agents for this application have been disabled by the user.”);

agentsAreEnabled = false;

PeriodicCheckBox.IsChecked = false;

}

if (exception.Message.Contains(“BNS Error: The maximum number of ScheduledActions of this type have already been added.”))

{

// No user action required.

}

PeriodicCheckBox.IsChecked = false;

}

catch (SchedulerServiceException)

{

PeriodicCheckBox.IsChecked =false;

}

}

private void StartResourceIntensiveAgent()

{

agentsAreEnabled = true;

resourceIntensiveTask =  ScheduledActionService.Find(resourceIntensiveTaskName) asResourceIntensiveTask;

if (resourceIntensiveTask != null)

{

RemoveAgent(resourceIntensiveTaskName);

}

resourceIntensiveTask = newResourceIntensiveTask(resourceIntensiveTaskName);

try

{

ScheduledActionService.Add(resourceIntensiveTask);

ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;

#if

(DEBUG_AGENT)

ScheduledActionService.LaunchForTest(resourceIntensiveTaskName, TimeSpan.FromSeconds(60));

#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;

}

ResourceIntensiveCheckBox.IsChecked = false;

}

catch (SchedulerServiceException)

{

ResourceIntensiveCheckBox.IsChecked = false;

}

}

bool ignoreCheckBoxEvents = false;

private void PeriodicCheckBox_Checked(object sender, RoutedEventArgs e)

{

if (ignoreCheckBoxEvents)

return;

StartPeriodicAgent();

}

private void PeriodicCheckBox_Unchecked(object sender, RoutedEventArgs e)

{

if (ignoreCheckBoxEvents)

     return;

RemoveAgent(periodicTaskName);

}

private void ResourceIntensiveCheckBox_Checked(object sender, RoutedEventArgs e)

{

if (ignoreCheckBoxEvents)

return;

RemoveAgent(resourceIntensiveTaskName);

}

private void ResourceIntensiveCheckBox_Unchecked(object sender, RoutedEventArgs e)

{

if (ignoreCheckBoxEvents)

return;

RemoveAgent(resourceIntensiveTaskName);

}

private void RemoveAgent(string name)

{

    try

{

ScheduledActionService.Remove(name);

}

catch (Exception)

{

}

}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)

{

ignoreCheckBoxEvents = true;

periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;

     if (periodicTask != null)

{

PeriodicStackPanel.DataContext = periodicTask;

}

resourceIntensiveTask = ScheduledActionService.Find(resourceIntensiveTaskName) as ResourceIntensiveTask;

   if (resourceIntensiveTask != null)

{

ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;

}

ignoreCheckBoxEvents = false;

}

  • Now the Debug the app in Windows Phone 7.1 Mango emulator & check the background app agent running as Schedule Tasks.

  •    The Background apps schedule time with Periodic Agent on Windows Phone.

  • Enable Background schedule to receive toast notification as foreground process from background activity apps. Check to see the Toast notification tile on Mango screen as foreground process.

Follow

Get every new post delivered to your Inbox.

Join 169 other followers

%d bloggers like this: