W
Windows Apps Team
Interested in running your application in the background? A new developer option available in the Windows 10 Anniversary Update just made background activity a whole lot easier. Your feedback was clear on the multiple process model: while doing background work in a separate process was more resilient, it required significantly more code to implement. From this feedback we are able to provide a new option, a simplified method for enabling background activity without creating a background task. Now developers have the choice of running code in the background as either a separate process or directly inside the foreground application. We’ll cover the basics for all the tools which utilize the single process model:
Let’s take a look at how the single process model is designed to make your life easier.
But first, the fundamentals
The single process model enhances the application lifecycle with improved notifications for when your app is in the foreground or in the background. Two new events are available from the Application object for these transitions: EnteredBackground and LeavingBackground. These events fit into the application lifecycle based on the visibility state of your application.
Entering the background
EnteredBackground lets your app know when it has moved out of foreground visibility completely. Previously the Suspending callback was the best place to save state after a user finished a session with your app. Now an application could continue running into the background and then move back to the foreground due to trigger activity without ever reaching the Suspended state. The best place to save data after a user session is in EnteredBackground. Memory limits also change as an app moves into the background. It is best to check the Memory Manager and drop memory if needed to ensure your app does not get terminated.
Leaving the background
Running in the background is the default state an application is activated or resumed into. Depending on the type of activation, your app may then move to running in the foreground or it may stay in the background. The LeavingBackground event is fired just before application UI is visible to your user. Previously the best location to load UI was in the Activated or Resuming event handlers. Now LeavingBackground is the best place to do your final checks that the UI is up and ready for presentation. It is important to check that visual assets are ready by this time, as this is the last opportunity to do work before your application is visible to the user.
Using EnteredBackground and LeavingBackground will allow your application to move smoothly between the foreground and background as a single process application.
Getting into the implementation
Now that we learned the fundamentals, let’s talk about actually doing the work.
Single process background activity is registered just like multiple process background activity. All background triggers start with registration using the Background Task Builder. The builder makes is easy to register a background task by setting all required values in one place.
var builder = new BackgroundTaskBuilder();
builder.Name = "My Background Trigger";
builder.SetTrigger(new TimeTrigger(15, true));
// use builder.TaskEntryPoint if you want to not use the default OnBackgroundActivated
// we’ll register it and now will start work based on the trigger, here we used a Time Trigger
BackgroundTaskRegistration task = builder.Register();
Register your background triggers with BackgroundTaskBuilder, but do not set the TaskEntryPoint. This will enable the default entry point, a new protected method on the Application object called OnBackgroundActivated. Once a trigger is registered, it can now fire based on the type of trigger set in the SetTrigger method. In the example above a TimeTrigger is used, which will fire fifteen minutes from the time it was registered. Taking action when that trigger fires can be accomplished by filling in the OnBackgroundActivated method. OnBackgroundActivated can be treated just like an IBackgroundTask’s Run method. The method has a parameter of BackgroundActivatedEventArgs, which contains everything that the Run method delivers.
// Since we didn’t use TaskEntryPoint, this is the default constructor used
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
DoBackgroundWork(args.TaskInstance);
}
The simplest way to convert your multiple process background activity into single process is to bring your IBackgroundTask Run method code inside your application and initiate it from OnBackgroundActivated. The code above assumes your app only has one background task. If your app has multiple background tasks the Background Activation Sample shows how you can use BackgroundActivatedEventArgs.TaskInstance.Task.Name to identify which task is being initiated. If you are currently communicating between background and foreground processes, you can remove that state management and communication code. Now background actions like database writes can be synced easily with your foreground application, because your application is actually performing the background activity.
App Services
While triggers are used to activate your application in the background from system activities, an App Service Connection enables another application to wake up your app in the background and start a direct line of communication. App Services do not run forever and are limited to the work that is requested by the foreground host application. This could be used to request information from an app or to hand off data for processing or ingestion by the App Service. App Services can now also be run in the same process as the foreground application making communication between apps much easier while removing the need to separate the service code to a separate project. With the introduction of App Services to the single process model two running foreground applications can have a direct line of communication via an App Service Connection. Turning a multiple process model App Service into single process model requires two changes. The first is a change in the manifest.
<uap:Extension Category="windows.appService">
<uap:AppService Name="SingleProcessAppService" />
</uap:Extension>
Simply remove the EntryPoint attribute, like we did with BackgroundTaskBuilder. Now the same OnBackgroundActivated callback will be used as the callback method. The second change is to move the service logic from a separate IBackgroundTask project into methods that can be called from OnBackgroundActivated, just like we did with the Background Trigger conversion. Now your application can directly run your App Service!
private AppServiceConnection appServiceconnection;
private BackgroundTaskDeferral appServiceDeferral;
protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
IBackgroundTaskInstance taskInstance = args.TaskInstance;
AppServiceTriggerDetails appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;
appServiceDeferral = taskInstance.GetDeferral();
taskInstance.Canceled += OnAppServicesCanceled;
appServiceConnection = appService.AppServiceConnection;
appServiceConnection.RequestReceived += OnAppServiceRequestReceived;
appServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed;
}
private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
AppServiceDeferral messageDeferral = args.GetDeferral();
ValueSet message = args.Request.Message;
string text = message["Request"] as string;
if ("Value" == text)
{
ValueSet returnMessage = new ValueSet();
returnMessage.Add("Response", "True");
await args.Request.SendResponseAsync(returnMessage);
}
messageDeferral.Complete();
}
private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
appServiceDeferral.Complete();
}
private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
appServiceDeferral.Complete();
}
In the code snippet above the OnBackgroundActivated method has been implemented to handle activation for an AppService. All of the events required for communication through an AppServiceConnection are registered, and the task deferral object is stored so that it can be marked as complete when the communication between the applications is done. In the example above an app receives a request and reads the ValueSet provided to see if the “Key” and “Value” strings are present. If they are present then the app service returns a pair of “Response” and “True” string values back to the app on the other side of the AppServiceConnection. You can learn more about connecting and communicating with other apps from Create and Consume an App Service.
Background Media Playback
Background media has a single process option which removes the need for inter-process communication and state management, saving hundreds of lines of code. Now playback can continue from the foreground to the background seamlessly with one simple addition: add the new background media playback capability to your manifest along with the new uap schema namespace, and that’s it.
<Package
xmlns="<a href="http://schemas.microsoft.com/appx/manifest/foundation/windows10">http://schemas.microsoft.com/appx/manifest/foundation/windows10</a>"
xmlns:mp="<a href="http://schemas.microsoft.com/appx/2014/phone/manifest">http://schemas.microsoft.com/appx/2014/phone/manifest</a>"
xmlns:uap="<a href="http://schemas.microsoft.com/appx/manifest/uap/windows10">http://schemas.microsoft.com/appx/manifest/uap/windows10</a>"
xmlns:uap3="<a href="http://schemas.microsoft.com/appx/manifest/uap/windows10/3">http://schemas.microsoft.com/appx/manifest/uap/windows10/3</a>"
IgnorableNamespaces="uap uap3 mp">
...
<Capabilities>
<uap3:Capability Name="backgroundMediaPlayback"/>
</Capabilities>
All of the media playback APIs are available to you as you move from the foreground into the background, there is no more need to communicate to a BackgroundMediaPlayer in a separate process! With this form of sponsored background execution the system will see that your application is playing media and will automatically extend its lifetime as it moves into the background. To learn more, take a look at the Background Media Playback Sample.
Doing more work with Extended Execution
Extended Execution is a method to continue work being done in the foreground while an app moves into the background. If you have important work to complete, extended execution allows for a more time to complete that actions before the app moves into the suspended state. Rather than initiating background activity by registering a trigger for later activation, applications that are in the foreground and need to continue doing work in the background can use Extended Execution. An Extended Execution session acts as a lock that is requested for background activity.
When requesting extended execution there are five required steps:
ExtendedExecutionSession Session = new ExtendedExecutionSession();
Session.Reason = ExtendedExecutionReason.Unspecified;
Session.Description = BackgroundActivityDescription;
Session.Revoked += SessionRevoked;
ExtendedExecutionResult result = await Session.RequestExtensionAsync();
Your request could be denied, at which point you should decide whether you need to notify the user or perform a shorter action. Hold onto the session as long as your activity needs to occur; if it goes out of scope or is marked as disposed then your session will end. If you do not dispose it yourself your session will run until it has been revoked by the system and the Revoked event will fire. It is important to clean up and halt work quickly, or your application could be terminated.
An Extended Execution Session can be used for Saving Data, Location Tracking, or generic Unspecified scenarios. Each of these scenarios is expressed as an ExtendedExecutionReason, which is required for initiating the session. Each reason has a different amount of time to complete before the session is revoked. Location Tracking session can run as long as location tracking is required even when a device is entering a low power mode, while a Saving Data session runs for a limited time period before it is revoked. Unspecified Extended Execution has a battery-aware timeout. It can run as long as the user is interacting with the device while it is charging and plugged into power. If the device is running off of battery power it can run for a limited time, unless the user sets the “Always allowed in background” option for your app in the Battery Use Settings. This is a new setting available in the Windows 10 Anniversary Update for devices that have batteries to give users more choice around what apps can use energy in the background. More information on this behavior is available in the Extended Execution Sample.
Unsupported Scenarios
Background activity can still be terminated even when inside an app if it runs past execution time limits, so for some purposes the resiliency of separating work into a background task will still be useful. Keeping background work as a task separate from the foreground application may be the best option for work that does not require communication to the foreground application. There are a set of scenarios that are currently not supported with the single process model. DeviceUseTrigger, DeviceServicingTrigger and IoTStartupTask cannot be used with the single process model at this time. Activating a VoIP background task within your application is also not possible. These triggers and tasks are still supported using the multiple process model.
We are always listening to feedback and what the community is interested in us working on. Please tell us via the Windows Platform UserVoice forum so we know what APIs are needed.
Wrapping Up
The Single Process Model is a new option available to developers targeting the Windows 10 Anniversary Update. Background activity isn’t needed for every app; the application lifecycle is often all you need to provide a rich experience for users. For those applications that do require background activity a single process app requires significantly less code to implement, and no more communication between multiple processes. The Background Task Sample shows that background activity can still be run in a separate process, but now background Triggers and App Services can be run alongside Extended Execution and audio playback directly inside your application.
Additional Resources:
Continue reading...
- Background Triggers
- App Services
- Background media playback using Activity Sponsored Execution.
- Extended Execution
Let’s take a look at how the single process model is designed to make your life easier.
But first, the fundamentals
The single process model enhances the application lifecycle with improved notifications for when your app is in the foreground or in the background. Two new events are available from the Application object for these transitions: EnteredBackground and LeavingBackground. These events fit into the application lifecycle based on the visibility state of your application.
Entering the background
EnteredBackground lets your app know when it has moved out of foreground visibility completely. Previously the Suspending callback was the best place to save state after a user finished a session with your app. Now an application could continue running into the background and then move back to the foreground due to trigger activity without ever reaching the Suspended state. The best place to save data after a user session is in EnteredBackground. Memory limits also change as an app moves into the background. It is best to check the Memory Manager and drop memory if needed to ensure your app does not get terminated.
Leaving the background
Running in the background is the default state an application is activated or resumed into. Depending on the type of activation, your app may then move to running in the foreground or it may stay in the background. The LeavingBackground event is fired just before application UI is visible to your user. Previously the best location to load UI was in the Activated or Resuming event handlers. Now LeavingBackground is the best place to do your final checks that the UI is up and ready for presentation. It is important to check that visual assets are ready by this time, as this is the last opportunity to do work before your application is visible to the user.
Using EnteredBackground and LeavingBackground will allow your application to move smoothly between the foreground and background as a single process application.
Getting into the implementation
Now that we learned the fundamentals, let’s talk about actually doing the work.
- Background triggers allow you to do work in your app
- App services allows for other apps to use your app to do work.
- Background media playback lets your app continue to play audio without being in the foreground and without a background audio task.
Single process background activity is registered just like multiple process background activity. All background triggers start with registration using the Background Task Builder. The builder makes is easy to register a background task by setting all required values in one place.
var builder = new BackgroundTaskBuilder();
builder.Name = "My Background Trigger";
builder.SetTrigger(new TimeTrigger(15, true));
// use builder.TaskEntryPoint if you want to not use the default OnBackgroundActivated
// we’ll register it and now will start work based on the trigger, here we used a Time Trigger
BackgroundTaskRegistration task = builder.Register();
Register your background triggers with BackgroundTaskBuilder, but do not set the TaskEntryPoint. This will enable the default entry point, a new protected method on the Application object called OnBackgroundActivated. Once a trigger is registered, it can now fire based on the type of trigger set in the SetTrigger method. In the example above a TimeTrigger is used, which will fire fifteen minutes from the time it was registered. Taking action when that trigger fires can be accomplished by filling in the OnBackgroundActivated method. OnBackgroundActivated can be treated just like an IBackgroundTask’s Run method. The method has a parameter of BackgroundActivatedEventArgs, which contains everything that the Run method delivers.
// Since we didn’t use TaskEntryPoint, this is the default constructor used
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
DoBackgroundWork(args.TaskInstance);
}
The simplest way to convert your multiple process background activity into single process is to bring your IBackgroundTask Run method code inside your application and initiate it from OnBackgroundActivated. The code above assumes your app only has one background task. If your app has multiple background tasks the Background Activation Sample shows how you can use BackgroundActivatedEventArgs.TaskInstance.Task.Name to identify which task is being initiated. If you are currently communicating between background and foreground processes, you can remove that state management and communication code. Now background actions like database writes can be synced easily with your foreground application, because your application is actually performing the background activity.
App Services
While triggers are used to activate your application in the background from system activities, an App Service Connection enables another application to wake up your app in the background and start a direct line of communication. App Services do not run forever and are limited to the work that is requested by the foreground host application. This could be used to request information from an app or to hand off data for processing or ingestion by the App Service. App Services can now also be run in the same process as the foreground application making communication between apps much easier while removing the need to separate the service code to a separate project. With the introduction of App Services to the single process model two running foreground applications can have a direct line of communication via an App Service Connection. Turning a multiple process model App Service into single process model requires two changes. The first is a change in the manifest.
<uap:Extension Category="windows.appService">
<uap:AppService Name="SingleProcessAppService" />
</uap:Extension>
Simply remove the EntryPoint attribute, like we did with BackgroundTaskBuilder. Now the same OnBackgroundActivated callback will be used as the callback method. The second change is to move the service logic from a separate IBackgroundTask project into methods that can be called from OnBackgroundActivated, just like we did with the Background Trigger conversion. Now your application can directly run your App Service!
private AppServiceConnection appServiceconnection;
private BackgroundTaskDeferral appServiceDeferral;
protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
IBackgroundTaskInstance taskInstance = args.TaskInstance;
AppServiceTriggerDetails appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;
appServiceDeferral = taskInstance.GetDeferral();
taskInstance.Canceled += OnAppServicesCanceled;
appServiceConnection = appService.AppServiceConnection;
appServiceConnection.RequestReceived += OnAppServiceRequestReceived;
appServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed;
}
private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
AppServiceDeferral messageDeferral = args.GetDeferral();
ValueSet message = args.Request.Message;
string text = message["Request"] as string;
if ("Value" == text)
{
ValueSet returnMessage = new ValueSet();
returnMessage.Add("Response", "True");
await args.Request.SendResponseAsync(returnMessage);
}
messageDeferral.Complete();
}
private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
appServiceDeferral.Complete();
}
private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
appServiceDeferral.Complete();
}
In the code snippet above the OnBackgroundActivated method has been implemented to handle activation for an AppService. All of the events required for communication through an AppServiceConnection are registered, and the task deferral object is stored so that it can be marked as complete when the communication between the applications is done. In the example above an app receives a request and reads the ValueSet provided to see if the “Key” and “Value” strings are present. If they are present then the app service returns a pair of “Response” and “True” string values back to the app on the other side of the AppServiceConnection. You can learn more about connecting and communicating with other apps from Create and Consume an App Service.
Background Media Playback
Background media has a single process option which removes the need for inter-process communication and state management, saving hundreds of lines of code. Now playback can continue from the foreground to the background seamlessly with one simple addition: add the new background media playback capability to your manifest along with the new uap schema namespace, and that’s it.
<Package
xmlns="<a href="http://schemas.microsoft.com/appx/manifest/foundation/windows10">http://schemas.microsoft.com/appx/manifest/foundation/windows10</a>"
xmlns:mp="<a href="http://schemas.microsoft.com/appx/2014/phone/manifest">http://schemas.microsoft.com/appx/2014/phone/manifest</a>"
xmlns:uap="<a href="http://schemas.microsoft.com/appx/manifest/uap/windows10">http://schemas.microsoft.com/appx/manifest/uap/windows10</a>"
xmlns:uap3="<a href="http://schemas.microsoft.com/appx/manifest/uap/windows10/3">http://schemas.microsoft.com/appx/manifest/uap/windows10/3</a>"
IgnorableNamespaces="uap uap3 mp">
...
<Capabilities>
<uap3:Capability Name="backgroundMediaPlayback"/>
</Capabilities>
All of the media playback APIs are available to you as you move from the foreground into the background, there is no more need to communicate to a BackgroundMediaPlayer in a separate process! With this form of sponsored background execution the system will see that your application is playing media and will automatically extend its lifetime as it moves into the background. To learn more, take a look at the Background Media Playback Sample.
Doing more work with Extended Execution
Extended Execution is a method to continue work being done in the foreground while an app moves into the background. If you have important work to complete, extended execution allows for a more time to complete that actions before the app moves into the suspended state. Rather than initiating background activity by registering a trigger for later activation, applications that are in the foreground and need to continue doing work in the background can use Extended Execution. An Extended Execution session acts as a lock that is requested for background activity.
When requesting extended execution there are five required steps:
- Create a new Extended Execution Session
- Set the Reason for the session
- Fill out the Description for what is occurring in the session
- Provide a revocation callback in case the session needs to be revoked early
- Make the request for the execution extension
ExtendedExecutionSession Session = new ExtendedExecutionSession();
Session.Reason = ExtendedExecutionReason.Unspecified;
Session.Description = BackgroundActivityDescription;
Session.Revoked += SessionRevoked;
ExtendedExecutionResult result = await Session.RequestExtensionAsync();
Your request could be denied, at which point you should decide whether you need to notify the user or perform a shorter action. Hold onto the session as long as your activity needs to occur; if it goes out of scope or is marked as disposed then your session will end. If you do not dispose it yourself your session will run until it has been revoked by the system and the Revoked event will fire. It is important to clean up and halt work quickly, or your application could be terminated.
An Extended Execution Session can be used for Saving Data, Location Tracking, or generic Unspecified scenarios. Each of these scenarios is expressed as an ExtendedExecutionReason, which is required for initiating the session. Each reason has a different amount of time to complete before the session is revoked. Location Tracking session can run as long as location tracking is required even when a device is entering a low power mode, while a Saving Data session runs for a limited time period before it is revoked. Unspecified Extended Execution has a battery-aware timeout. It can run as long as the user is interacting with the device while it is charging and plugged into power. If the device is running off of battery power it can run for a limited time, unless the user sets the “Always allowed in background” option for your app in the Battery Use Settings. This is a new setting available in the Windows 10 Anniversary Update for devices that have batteries to give users more choice around what apps can use energy in the background. More information on this behavior is available in the Extended Execution Sample.
Unsupported Scenarios
Background activity can still be terminated even when inside an app if it runs past execution time limits, so for some purposes the resiliency of separating work into a background task will still be useful. Keeping background work as a task separate from the foreground application may be the best option for work that does not require communication to the foreground application. There are a set of scenarios that are currently not supported with the single process model. DeviceUseTrigger, DeviceServicingTrigger and IoTStartupTask cannot be used with the single process model at this time. Activating a VoIP background task within your application is also not possible. These triggers and tasks are still supported using the multiple process model.
We are always listening to feedback and what the community is interested in us working on. Please tell us via the Windows Platform UserVoice forum so we know what APIs are needed.
Wrapping Up
The Single Process Model is a new option available to developers targeting the Windows 10 Anniversary Update. Background activity isn’t needed for every app; the application lifecycle is often all you need to provide a rich experience for users. For those applications that do require background activity a single process app requires significantly less code to implement, and no more communication between multiple processes. The Background Task Sample shows that background activity can still be run in a separate process, but now background Triggers and App Services can be run alongside Extended Execution and audio playback directly inside your application.
Additional Resources:
- App Lifecycle Blog Post
- App Lifecycle and Background Task How-To’s
- Extended Execution MSDN Magazine article
- Create and Consume an AppService
- Extended Execution Sample
- Background Task Sample
- Background Activation Sample
- Background Media Playback Sample
- Windows Platform UserVoice
Continue reading...