Introduction
In this post, I'm going to cover a method of background execution in the WinRT APIs that will allow you to setup a background task that will use a Microsoft Band connected to a Windows device and allow it to run indefinitely using a DeviceUseTrigger. This is a more advanced version of a background execution example I covered on my blog for the Microsoft Band.
Important information before we start
Before I go into the explanation of how this method works, if you've not developed with the Microsoft Band SDK previously, you might want to take a look at some of my previous blog posts. The content in this post will assume that you have a basic understanding of background execution in WinRT and how to get connected with the Microsoft Band in your application. Here are a few posts to look at to get up to speed:
Explanation of the implementation
Most users developing applications that take advantage of the Microsoft Band's sensors are looking to have them run in the background, especially when you're creating a new fitness application for the likes of running or home exercise.
The problem with my basic background execution method is that it only runs for as long as it can before the OS cancels the execution which means that the user would have gaps in their data pulled from the Band and as the Microsoft Band doesn't have any type of storage on the device itself, this data will be lost. Luckily, I took at look at background execution much deeper in WinRT and came up with a method that could keep the connection to the Band open for a longer period of time and this will be covered below.
When creating background tasks in Windows apps, there are a number of ways that the OS can trigger it to run. In my basic background execution method, I used the TimeTrigger which allowed the background task to run every 15 minutes. However, this solution doesn't work for the methods I've talked about above such as a running app where you'll want the connection for as long as the run iteself.
Having a look through MSDN, I came across a sample for Windows app background execution using Bluetooth devices and noticed the DeviceUseTrigger which is intended to be used to access sensors and peripherals using background tasks when the app is completely suspended. This is where the implementation for this background task comes in.
Developing the background task
Setting up the DeviceUseTrigger is done in a similar way to that of the TimeTrigger except for a slight change. When you use the DeviceUseTrigger, you have to request use of the device you're trying to connect to by passing through the ID of the Bluetooth peripheral you're wanting to connect to that is registered with your Windows device. This is done as follows:
public static async Task<bool> RegisterBandDataTask(string taskName)
{
try
{
var access = await BackgroundExecutionManager.RequestAccessAsync();
if ((access == BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity) || (access == BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity))
{
var taskBuilder = new BackgroundTaskBuilder { Name = "BandTask", TaskEntryPoint = taskName };
var deviceUseTrigger = new DeviceUseTrigger();
taskBuilder.SetTrigger(deviceUseTrigger);
taskBuilder.Register();
var device = (await DeviceInformation.FindAllAsync(RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(new Guid("A502CA9A-2BA5-413C-A4E0-13804E47B38F"))))).FirstOrDefault(x => x.Name == bandInfo.Name);
var triggerResult = await deviceUseTrigger.RequestAsync(device.Id);
switch (triggerResult)
{
case DeviceTriggerResult.DeniedByUser:
throw new InvalidOperationException("Cannot start the background task. Access denied by user.");
case DeviceTriggerResult.DeniedBySystem:
throw new InvalidOperationException("Cannot start the background task. Access denied by system.");
case DeviceTriggerResult.LowBattery:
throw new InvalidOperationException("Cannot start the background task. Low battery.");
}
return true;
}
}
catch (Exception)
{
}
return false;
}
</bool>
Now, I understand that this may look like a lot to go through but working with background tasks isn't the easiest of tasks. I'll break it down so that it's easier to understand what's going on in the snippet.
When you work with background tasks, you need to request access to the background execution services. That is what is happening with the first few lines and if we've been granted the access, we can begin setting up the background task with the DeviceUseTrigger and get it registered.
Unlike the TimeTrigger, we aren't done with the set up however. At this point in the code, we need to get the ID of the Microsoft Band and get the DeviceUseTrigger we've created to request access to it. The RfcommServiceId you're noticing in the code is for accessing any type of Microsoft Band device connected. The GUID can be found in the package manifest file for your application when you add the Microsoft Band SDK to your app.
If you're granted access at this point, your background task that you've built up will start running in the background immediately and will keep running until your app cancels it or the OS needs the CPU usage for other tasks. at which point it will be cancelled forcefully. You'll need to handle this in your background task code so that you can unregister the background task from the device so you can set it up again later or immediately to keep it running forever.
Play with the sample
If you'd like to take a look at a sample of how this works, you can head over to my GitHub repo and download it. If you have any questions or find issues, feel free to log them in GitHub or get in touch with me!