Background agent best practices for Windows Phone 8

[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]

This topic contains important considerations and best practices for developing background agents for Windows Phone.

This topic contains the following sections.

Debugging

The following should be considered when debugging background agents.

  • Use LaunchForTest(String, TimeSpan) to launch background agents when debugging. Periodic agents are not launched by the system when the debugger is attached. This method can be called from the foreground app or from the background agent.

  • For Windows Phone OS 7.1 apps, memory and execution time policies are not enforced while the debugger is attached. It is important that you test your agent while not debugging to verify that your agent does not exceed the memory cap or run longer than the allotted time period for the agent type. For Windows Phone 8 apps, memory and execution time policies are enforced while debugging.

  • Use ApplicationMemoryUsageLimit to query the memory limit for both foreground apps and background agents.

Detecting when background agents have been disabled

In Windows Phone OS 7.1, users have the ability to disable background agents for each installed app in the phone’s Settings app. If agents have been disabled for your app, attempts to register an agent using the Add(ScheduledAction) method of the ScheduledActionService will throw an InvalidOperationException, so place calls to Add in a try block. If an exception is thrown and the message associated with the exception is “BNS Error: The action is disabled”, then agents have been disabled for your app. The following code illustrates the proper way to handle this case.

bool agentsAreEnabled = true;
PeriodicTask periodicTask = new PeriodicTask("MyPeriodicTask");
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);
}
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.
}

}

An InvalidOperationException will also be thrown when the number of periodic background agents has reached the limit for the device. The number of agents allowed varies depending on the hardware capabilities of the device, but it is a small number and therefore it is common for this limit to be reached. For this reason, it is very important that you catch this exception whenever you attempt to add a periodic task. A SchedulerServiceException can also be thrown when adding a task, for example, if the device has just booted and the Scheduled Action Service hasn’t started yet. You should catch this exception whenever you add a scheduled task.

Tip

When an app’s periodic background agent runs, it consumes a small amount of the device’s battery power. Users can disable background agents for one or more apps in the Settings app in order to extend battery life. However, to make it easier for users to balance functionality and battery life, you may want to add functionality to your foreground app that allows the user to opt-in to enabling background agents.

Communication between foreground app and background agent

Passing information between the foreground app and background agents can be challenging because it is not possible to predict if the agent and the app will run simultaneously. The following are recommended patterns for this.

  1. For Periodic and Resource-intensive Agents: Use LINQ 2 SQL or a file in isolated storage that is guarded with a Mutex. For one-direction communication where the foreground app writes and the agent only reads, we recommend using an isolated storage file with a Mutex. We recommend that you do not use IsolatedStorageSettings to communicate between processes because it is possible for the data to become corrupt.

  2. For Audio Agents: Store custom data in the Tag property of the AudioTrack class. For notifications from the audio agent to the foreground app, read the Tag property in the PlayStateChanged event handler. To pass data from the foreground app to the audio agent, read the Tag property of the current track in the implementation of the OnPlayStateChanged(BackgroundAudioPlayer, AudioTrack, PlayState) method.

App structure

Windows Phone SDK 7.1 includes a project template for background agents called Windows Phone Scheduled Task Agent. When implementing a background agent, you should add a project to your solution using this template. In the project for your foreground app, add a reference to the output of the background agent project by selecting Project->Add Reference… and then selecting your background agent project. You should not create a class that implements ScheduledTaskAgent within the project for your existing app. Background agents will not be run if they are in the same assembly as the foreground app.

If you rename the background agent class or namespace, you will need to manually update the app manifest file for your foreground app. For information about the structure of this file, see the TASKS Element section of App manifest file for Windows Phone 8.

Dynamically generating images

Due to the memory constraints for background agents, if your app dynamically generates images to use as background images, it is recommended that you target the WVGA resolution and allow the phone to automatically scale images to fit higher resolution screens. Attempting to generate higher resolution images is likely to cause your agent to exceed the memory cap.