Porting a Windows Phone 8.0 Silverlight app to Windows Phone 8.1 Universal app - Background Tasks

After we handled Background Transfers in the previous post it took me some time to understand the differences between Background Tasks and the Background Agent.

The plain basics

We always started with a simple Class Library, we are a little bit more constrained now because we have to add a Windows Runtime Component. Then we add a reference to this newly created project from our app project.


In the past we’ve had to derive from ScheduledTaskAgent and override the OnInvoke method. When we were ready we did a NotifyComplete.

public class ScheduledBackgroundTask : ScheduledTaskAgent
    protected override void OnInvoke(ScheduledTask task)
        //Do lots of work

But things are different, but the look very similar. I have to implement IBackgroundTask and implement the Run method. I need to explicitly get a deferral and call the Complete method on the deferral when I’m ready. However don’t forget to make the class sealed.

public sealed class ScheduledBackgroundTask : IBackgroundTask
    public void Run(IBackgroundTaskInstance taskInstance)
        var deferral = taskInstance.GetDeferral();
        //Do lots of work


Registering of a task in Windows Phone 8.0 is very simple and straightforward there are PeriodicTasks and ResourceIntensiveTasks.

var periodicTask = new PeriodicTask(taskName)
    Description = taskDescription

var intensiveTask = new ResourceIntensiveTask(intensiveTaskName)
                    Description = taskDescription



The registration is much more flexible now in the Universal app platform. As a start the background task needs to be added to the appxmanifest declarations. Here we also choose Timer and System event as supported task types. Only the Entry point is required, which we fill with the fully qualified name of the background task class.


Besides registering a background task, there’s the need to actually define the Trigger. There are lots of different triggers, but I focused on the TimeTrigger and the MaintenanceTrigger. The TimeTrigger makes your background task to run as often as every 15 minutes. I thought the MaintenaceTrigger was a lot like the ResourceIntensiveTask we have in Windows Phone 8.0, but more on that at the end of this article.

First we have to Request execution of Background Tasks. For Windows Phone this means access is granted silently. In big Windows this is different. Your app can only run in the same sense like Windows Phone background tasks when they are added to the lockscreen. Otherwise they will also run in the background, but only when the app is in the foreground. We define the Task Entry Point which is the fully qualified name of the background task class, I’ve seen a lot of handwritten strings in there, which I hate. Then we create a BackgroundTaskBuilder with a name and the created TaskEntryPoint. We have to set the trigger, to port my ScheduledTask this has to be a TimeTrigger. To complete registration we call the Register method on the TaskBuilder.

await BackgroundExecutionManager.RequestAccessAsync();

var taskEntryPoint = typeof(ScheduledBackgroundTask).FullName;
BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder { Name = "Background Task", TaskEntryPoint = taskEntryPoint };

taskBuilder.SetTrigger(new TimeTrigger(15, false));

BackgroundTaskRegistration task = taskBuilder.Register();


Something I don’t need for porting my podcast app is the use of Conditions. This can be very interesting for your app so I suggest reading more about the Conditions.

App Update

While reading the documentation I found a small section I almost missed. It’s about what to do when the app launches after being updated. The app must explicitly call RemoveAccess on the background task when the version number changes. The below code is copied directly from MSDN because it just works.

async void CheckAppVersion()
    String appVersion = String.Format("{0}.{1}.{2}.{3}",

    if (Windows.Storage.ApplicationData.Current.LocalSettings.Values["AppVersion"] != appVersion)
        // Our app has been updated
        Windows.Storage.ApplicationData.Current.LocalSettings.Values["AppVersion"] = appVersion;

        // Call RemoveAccess

    BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync();

Note: This is only valid for the Windows Phone apps.

There is a very interesting Trigger that calls a specific background task when an app update is downloaded. This can be used for example to apply database schema-changes or cleanup of old stuff. A good explanation of how background tasks work after an app update is written in the MSDN documentation.

Too many background tasks registered?

In Windows Phone 8.0 we had to catch the InvalidOperationException when Registering the Background Task. This was to get to know when for example too many background tasks are registered. In that particular case you would have check the message if it contained a message like “BNS Error: The maximum number of ScheduledActions of this type have already been added.”. Awful in my opinion, but it did work.

var periodicTask = new PeriodicTask(taskName)
    Description = taskDescription


catch (InvalidOperationException exception)
    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.


But this has greatly improved in the Universal app platform. As mentioned before, we have to explicitly request the execution of background tasks. This request will return a BackgroundAccessStatus.Denied if already too many background tasks are registered.

BackgroundAccessStatus registrationResult = await BackgroundExecutionManager.RequestAccessAsync();

if (registrationResult == BackgroundAccessStatus.Denied)
    //the maximum number of apps with background tasks across the system has been exceeded 
    //or the user has explicitly denied background task permissions for your app in the device's settings

Want more resources?

If we wanted more resources in Windows Phone 8.0 we registered a ResourceIntensiveTask instead of a PeriodicTask. This would help us with a BackgroundTask that can run for 10 minutes instead of the 25 seconds for the PeriodicTask.

Sounded really interesting but the constraints were very tight, in reality ResourceIntensiveTasks are only run when the phone was plugged in for a longer period of time, during the night for example.

Windows Universal apps don’t really have an equivalent for the ResourceIntensiveTask. Some Devs have pointed me towards the direction of a MaintenanceTrigger. The MaintenanceTrigger only fires when the power is plugged in, so that’s similar.

However it won’t get 10 minutes of time to execute. There’s not even a difference in execution time depending on the trigger. You’ll get 2 seconds of cpu time, which is completely different to clock time.

To get even worse, while I was testing with both the TimeTrigger and the MaintenaceTrigger, they are executed together when I plugin the power. This is something I didn’t expect because in Windows Phone 8.0 we either had a PeriodicTask or a ResourceIntensiveTask which got executed. For now I’m not implementing the ResourceIntensiveTask parts, let’s see if they are required in the end.

Porting a Windows Phone 8.0 Silverlight app to Windows Phone 8.1 Universal app - Background Transfers

Another major thing to port is the BackgroundTransfer stuff in the P | Cast app. Although the API is similar there was a lot of code that I needed to port, though a lot of this code could be deleted as well.

Starting a BackgroundTransfer

Let’s start with the easy part. We want to start a BackgroundTransfer. We are no longer bound to save the files to /Shared/Transfers which was required in Windows Phone 8.0, which makes it all much easier. Actually I think we can even download directly to a SD-card if we would like. We just create a StorageFile where we want to store the file to download. We create an instance of a BackgroundDownloader and use that to create a DownloadOperation out of the RequestUri and the StorageFile. Then we construct a CancellationTokenSource which we can use to cancel the download operation. We also construct a Progress feedback delegate. We end by starting the operation and attaching the CancellationToken and the Progress delegate.

Uri requestUri = new Uri("http://someurl.com/largefile", UriKind.RelativeOrAbsolute);

StorageFile downloadTo = await ApplicationData.Current.LocalFolder
var cts = new CancellationTokenSource(); 
BackgroundDownloader downloader = new BackgroundDownloader { Method = "GET" };
DownloadOperation operation = downloader.CreateDownload(requestUri, downloadTo);

Progress<DownloadOperation> downloadProgress = new Progress<DownloadOperation>(DownloadProgress);
await operation.StartAsync().AsTask(cts.Token, downloadProgress);

Getting a bit of feedback from the DownloadOperation

We already attached a Progress handler in the previous section. The implementation depends on what you want to do with it. Just a small example of what I used during testing.

private void DownloadProgress(DownloadOperation operation)
    Debug.WriteLine("Download: {0}: {1:P2}",
        operation.Progress.BytesReceived * 1.0 / operation.Progress.TotalBytesToReceive);


Of course we don’t only want feedback on newly created DownloadOperations but also on stuff we created in a previous app-run but which didn’t complete yet. We can easily get all the CurrentDownloads via the BackgroundDownloader. We also construct a CancellationTokenSource and a Progress delegate. We use AttachAsync to attach the Progress delegate and the CancellationTokenSource to the existing DownloadOperation.

var currentTransfers = await BackgroundDownloader.GetCurrentDownloadsAsync();

var cts = new CancellationTokenSource();
Progress<DownloadOperation> downloadProgress = new Progress<DownloadOperation>(DownloadProgress);

foreach (var currentTransfer in currentTransfers)
    await currentTransfer.AttachAsync().AsTask(cts.Token, downloadProgress);

How do I cancel that DownloadOperation?

I was trying to port the code by just using the code intellisense, but I couldn’t find a way to cancel a specific BackgroundTransfer. In the end I found something, but for comparison first the Windows Phone 8.0 method to cancel a backgroundtransfer.



The explanation of Microsoft: “Because BT is based on the BackgroundTask infrastructure, you cancel a transfer simply by canceling the task”. Sounds nice, but the amount of code is much more than you expect.

public static class DownloadOperationExtensions
    public static async Task CancelAsync(this DownloadOperation operation)
        var cts = new CancellationTokenSource();
        await operation.AttachAsync().AsTask(cts.Token);



In Windows Phone 8.0 we explicitly had to remove the completed downloads from the BackgroundTransfer queue, I couldn’t find anything pointing towards this requirement on Universal apps. So I tried doing BackgroundTransfers without explicitly removing them. And my conclusion is, you don’t need to explicitly remove them from the queue. When the transfer completed without the app running it will be in the queue the first time you start the app again. So you can handle it.

Handling very large files and how to read the different policies

One of the things you had to be aware of was even though you want to allow downloading while running on a battery this wasn’t allowed for files over 100MB. I handled this by trying to download it on battery and check if the TransferError.Message was “The transfer file size is bigger than the allowed limit”. The new BackgroundTransfer API handles this automatically.

In the old API you could set policies that were pretty simple, there were combinations of Allow Cellular and Allowing Battery. You can no longer set policies around the battery because those are handled automatically. Now you can set a policy to UnrestrictedOnly, Default and Always. This is something that needs a bit of clarification with scenario’s I found here.


Unrestricted Only

Default Always
Wi-Fi Allow Allow Allow
Metered connection, not roaming, under data limit, on track to stay under limit Deny Allow Allow
Metered connection, not roaming, under data limit, on track to exceed limit Deny Deny Allow
Metered connection, roaming, under data limit Deny Deny Allow
Metered connection, over data limit. This state only occurs when the user enables “Restrict background data in the Data Sense UI. Deny Deny Deny


Transfer Status

The possible statuses of the Transfer has changed. I tried to map them like below. You can read the details of the original TransferStatus and the new BackgroundTransferStatus if you want to know more.

TransferStatus (8.0) BackgroundTransferStatus (8.1)
Transferring Running
None / Waiting Idle
WaitingForWifi PausedCostedNetwork
Paused PausedByApplication
Completed Completed


One of the things I noticed is the grouping of the TransferStatus.WaitingForX that I couldn’t map directly but are all captured within the BackgroundTransferStatus.PausedBySystemPolicy.

We do see a status Completed in the enum, but in practice I have never seen this status. Even when the transfer is actually completed, based on the BytesReceived is equal to TotalBytesToReceive. This is for both Windows and Windows Phone, so status is still Running but all bytes are already received.

Calculate Progress

Things have been moved around a bit, but calculating progress is still easy to do. So my previous code on Windows Phone 8.0.

private double CalculateProgress(BackgroundTransferRequest request)
    if (request.TotalBytesToReceive == 0)
        return 0.0;
    return request.BytesReceived*1.0/request.TotalBytesToReceive;

Is easily rewritten to Windows Phone 8.1.

private double CalculateProgress(DownloadOperation request)
    if (request.Progress.TotalBytesToReceive == 0)
        return 0.0;
    return request.Progress.BytesReceived * 1.0 / request.Progress.TotalBytesToReceive;

Background Transfer Queue

The old BackgroundTransferService had a hard limit of 25 active and pending download requests per application. This caused any app to manage it’s queue. This limit doesn’t exist in the new Background Transfer API, it has a system limit of 1000 however. Nice, no longer managing the queue myself!

Background Transfer behaviors

There’s an important difference between the behavior of background transfers within Windows and Windows Phone. When the Windows Universal app is terminated the background transfers will be terminated as well. This is different from what we are used to within Windows Phone, where the background transfers continue without the app running.

Porting a Windows Phone 8.0 Silverlight app to Windows Phone 8.1 Universal app - Database / SQLite

Two weeks ago I wrote about the preparation of porting my P | Cast app to Windows Phone 8.1 Universal.

After this I started investigating if I would be able to port my database including the data access code.

Prepare the Windows Phone project

So of course we need to have the SQLite database engine for Windows Phone 8.1. So download this Visual Studio Extensions: SQLite for Windows Phone 8.1. Now it’s time to add a reference to the SQLite engine on the Windows Phone project. It will also add a reference to the Microsoft.VCLibs.

While in the past a special C++ project would have to be added to your Windows Phone 8.0 solution, this is much easier.


Prepare the Windows Project

While I’m still not sure if the Windows version of P | Cast will ever see the light, I want to know if my code is compatible. So I downloaded the Visual Studio Extension: SQLite for Windows Runtime (windows 8.1). So this time add a reference to the SQLite engine on the Windows project.


Time for some Data Access

As always I try to decouple the data access from the UI. It’s a best practice I always try to follow. Nowadays we have Portable Class Libraries so I add a new PCL project to the solution.


I reference this project from both the Windows Phone and the Windows project.

Next I add the same NuGet package I’m used to use in the P | Cast app, called sqlite-net.

Everything compiles, time to migrate code. First I took the code from a table definition. Actually I copied all of my table definition classes, but for this article I’ll show the Subscription definition.

public class Subscription
    [AutoIncrement, PrimaryKey]
    public int Id { get; set; }

    public string Uri { get; set; }

    public string Title { get; set; }
    public string Description { get; set; }
    public string Copyright { get; set; }
    public string ArtUri { get; set; }

    public string ExternalId { get; set; }
    public DateTime LastUpdated { get; set; }


So I tried to do actually create the database, insert data and query the data. I called the below method from the OnLaunched.

private async void TryDatabaseStuff()
    var connection = new SQLiteAsyncConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, "podcasts.db"));
    await connection.CreateTablesAsync<Subscription, Track>();

    await connection.InsertAsync(new Subscription { Uri = "http://hanselminutes.com/subscribe" });
    Debug.Assert(await connection.Table<Subscription>().CountAsync() > 0);


So to assure you, all this code works like a charm on both Windows Phone and Windows. Now it’s time to migrate some more parts.

Porting a Windows Phone 8.0 Silverlight app to Windows Phone 8.1 Universal app - Preparation

As many of you readers probably know, I wrote a Podcast app called P | Cast. I did this in the early days of Windows Phone 8.0 because it lacked an internal podcast player (for most regions), and all the alternatives from the store weren’t working for me at that moment.

But then came Windows Phone 8.1, it included a podcast player, again. I thought this would be the death of my app. But it isn’t at least it isn’t for myself, I don’t like the internal podcast player that much. So I can of course expand P | Cast to become better, but one of the most requested features, modify playbackspeed, can’t be done on the Windows Phone 8.0 model. Time to port the P | Cast app to Windows Phone 8.1 Universal app. Not an easy task though.

User Interface

Yes both User Interfaces are in Xaml, but there are significant differences, in the controls that are available and also their richness. I’m currently using the Telerik UI for Windows Phone controls. They work perfectly right now, but I can’t use them on an universal app, and their Telerik UI for Windows Universal isn’t as rich as their Windows Phone counter part yet. On the other the current xaml can probably be a good base to start with.

Background Audio

In the Windows Phone 8.0 timeframe, all you have is a Background Audio Agent. There were a lot little quirks in the events that are or aren’t called in the Background Audio Agent. I had to do a lot to make sure track progress could be saved. Hope we don’t have to worry about that anymore. Even using NamedEvents to make sure the BackgroundAudio could somehow communicate with the UI.

The background audio architecture has changed a lot. It changed so much actually that I’m sure I will have to redo all the audio code. But all will come with a very interesting feature: the ability to change the playbackrate. So in a new version we will finally be able to play podcasts at 1.5 speed or 2.0 speed if you would like to.

Background Transfers

Because the sizes of podcasts can be very large I used the BackgroundTransferService to make sure the OS handles all the issues of resuming of transfers and even keep downloading if the app isn’t running in the foreground. Universal apps have a different API for handling Background Transfers which are very similar but have some differences in limitations it seems. I hope they can be started from a background task, which couldn’t be done on Windows Phone 8.0.

Background Processing

P | Cast includes a background agent which is responsible for syncing all podcast feeds and eventually clean up of played podcasts. When the phone is plugged in for charging an even more intense version of the background agent launches which will do background downloading of podcasts. Although the Background Task API is different for Universal apps, the concepts are similar. Just Run code on the background!


All meta-data of the podcasts is stored in a SQLite database. I know you have to do something different to actually use SQLite in the app, but I hope I can still use SQLite-Net library to access the database.

Posted: Porting a Windows Phone 8.0 Silverlight app to Windows Phone 8.1 Universal app - Database / SQLite

Windows 8 app?

Yes the big question is of course, will there also be a Windows 8 app? Maybe there will be, there’s a lot of code that can be shared in Universal Apps. A new UI design will be required for a Windows 8 app of course. And every user would expect the Windows Phone and Windows apps to be in sync, always. That would require some additional thinking for me. Because I have no idea on how to do that, yet.

What’s next?

So I will write blogposts for each of the above mentioned things. I will explain what I needed to do to implement the different parts, and if possible if I could reuse code or not. If you have any tips for me, please share them in the comments.

Windows Phone 8.1–Background Audio in Windows Phone Store apps

With the introduction of Windows Phone 8.1 you’ve the choice to either continue with the Windows Phone Silverlight 8.1 option or to use the Windows Phone Store Apps model similar to Windows 8 Store Apps.

However you can’t just upgrade to Windows Phone Silverlight 8.1 in every situation. Some features just aren’t supported in Silverlight 8.1, one of them being the AudioPlayerAgent which we use when implementing Background Audio in Windows Phone 8.

Upgrading to the Windows Phone Store Apps model isn’t an easy task either, the Background Audio is implemented in a completely different way. But there are reasons for people to do upgrade to the Windows Phone Store Apps model. One of these is the ability to change the speed of playback, an often requested feature for the P | Cast podcast app I created. Another option is to share a lot of the code by creating a Universal app which will enable both a Windows Store app and a Windows Phone Store app. I will not go into the details of the Background Audio for the Windows Store apps, but they are a little bit different compared to the implementation of the Background Audio in the Windows Phone Store apps. Different, but still similar though!

Alright, enough about the background, let’s start building a very basic app with Background Audio!

A little bit of architecture

We want to play audio which stays playing while our user interface isn’t active. So we need to have a background process that’s capable of playing audio. See the green blocks at the right in below diagram. The actual audio playback occurs in the background process while the foreground process has access to the MediaPlayer information via a Proxy Object.

Background Audio Architecture Windows Phone 8.1

To manage the Universal Volume Control, like the one below we’ll need to talk to the SystemMediaTransportControl. This API that also exists in Windows 8.1 so if we ever want to create a Universal App this will come in handy.

Universal Volume Control Windows Phone 8.1

But the actual communication between the foreground process aka the UI and the background process happens through messaging. You can pass messages from foreground to background, but also the other way around. A message consists of a string message, but can also pass an additional value (only simple value types).

Life Cycle of the Background Task

The Background Task is initiated the first time the Foreground Process does a call to BackgroundMediaPlayer.Current. Upon initiation the IBackgroundTask.Run is called.

You want the background audio to continue playing, so you have to get a BackgroundTaskDeferral in the Run method of the IBackgroundTask. You’ll have to complete the deferral upon the Canceled or Completed events of the task. The actual Run method should run to the end in a timely fashion, if it’s more or less waiting in the Run method the Background Task could be terminated to release resources.

The background task for running audio can be cancelled in a couple of situations:

  • When another app with audio playback starts
  • When the background task is running but no audio is playing (paused or never started) and the foreground app is suspended

The playback will be automatically paused by media interruptions like a phone call or VoIP call. When the phone call or VoIP call ends within 5 minutes, the background audio is resumed by executing the Run method and sending a ButtonPressed (PlayButton) event on the SystemMediaTransportControls instance. When the call takes longer than 5 minutes the playback doesn’t start but the Universal Volume Control doesn’t loose state and hitting the play button will restart the Background Audio manually.

Termination of the background task happens without warning when:

  • A VoIP call comes in and there is not enough memory
  • A resource policy is violated
  • Task cancellation or completion does not end gracefully

Project Setup

Besides the creation of a Windows Phone 8.1 app, it’s required to create a Windows Runtime Component (Windows Phone).


Add the BackgroundAudioTask which implement IBackgroundTask, like below. The details of the implementation will be filled in later.

public sealed class BackgroundAudioTask : IBackgroundTask
    public void Run(IBackgroundTaskInstance taskInstance)


In the Windows Phone 8.1 App project you can add a reference to the Windows Runtime Component project. Please don’t make it a class library.

Go to the Package.appxmanifest to the Declarations tab and add a Background Task. Give it the the task type Audio and set the Entry point to the BackgroundAudioTask we created by using the full type name (namespace+type name).


The UI of the Player

Because I want to focus on the background audio, I made the UI simple, very simple. One Button, just the play button.


So the little bit of xaml that’s there to create a button with the click handler.

    <Button Content="Play" Click="PlayButtonClick"></Button>

We need the Background Task to fire up, so we have to access the BackgroundMediaPlayer.Current property. We do this in the OnNavigatedTo of the MainPage.

private MediaPlayer _mediaPlayer;
protected override void OnNavigatedTo(NavigationEventArgs e)
    _mediaPlayer = BackgroundMediaPlayer.Current;


And the PlayButtonClick is almost empty as well. We send a message to the background task. The message has a key indicating the operation Play, the value being a url to the background media we want to play. We will have to handle this in the background audio, but this is all we do in the UI.

private void PlayButtonClick(object sender, RoutedEventArgs e)
    var message = new ValueSet

Code a Background Task for Background Audio

After all the explanation above it’s time to write some real code. In the below piece of code you can see that all we do in the Run method is preparation. My advice to you is to keep this as short as possible as well. In line 3, we get a reference to the SystemMediaTransportControls, being the Universal Volume Control, and enable the Universal Volume Control.

In line 6 we subscribe to the receiving of the messages that are sent from the UI and line 7 does subscribe to the MediaPlayer state changes like Stopped, Playing and Paused.

To make sure the background task keeps running we get a deferral and also subscribe the Canceled and Completed events (line 10 – 13).

public void Run(IBackgroundTaskInstance taskInstance)
    _systemMediaTransportControl = SystemMediaTransportControls.GetForCurrentView();
    _systemMediaTransportControl.IsEnabled = true;
    BackgroundMediaPlayer.MessageReceivedFromForeground += MessageReceivedFromForeground;
    BackgroundMediaPlayer.Current.CurrentStateChanged += BackgroundMediaPlayerCurrentStateChanged;

    // Associate a cancellation and completed handlers with the background task.
    taskInstance.Canceled += OnCanceled;
    taskInstance.Task.Completed += Taskcompleted;

    _deferral = taskInstance.GetDeferral();

private SystemMediaTransportControls _systemMediaTransportControl;
private BackgroundTaskDeferral _deferral;


Let’s first make sure we handle the closing of the background task correctly. The implementation of playing music can wait a bit. Make sure that you save some state if required in the OnCanceled implementation before completing the deferral.

private void Taskcompleted(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)

private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
    // You get some time here to save your state before process and resources are reclaimed


Yes I know, now it’s time to implement the Play back code. Our UI did send a Message to the Background Audio Task, so we need to handle that message. The handling of the message happens in the MessageReceivedFromForeground method. We’re getting the ValueSet message as an argument and need to loop through the ValueSet keys to process the message. If we find a key with the value “Play” (line 8), we want to start the playback of the value passed to the message (line 10).

private void MessageReceivedFromForeground(object sender, MediaPlayerDataReceivedEventArgs e)
    ValueSet valueSet = e.Data;
    foreach (string key in valueSet.Keys)
        switch (key)
            case "Play":
                Debug.WriteLine("Starting Playback");


The implementation isn’t that difficult, most of the code behind the Play method is the updating of the Universal Volume Control with the correct information. For the playing we set AutoPlay and the UriSource (lines 3-5).

private void Play(string toPlay)
    var mediaPlayer = BackgroundMediaPlayer.Current;
    mediaPlayer.AutoPlay = true;
    mediaPlayer.SetUriSource(new Uri(toPlay));

    //Update the universal volume control
    _systemMediaTransportControl.ButtonPressed += MediaTransportControlButtonPressed;
    _systemMediaTransportControl.IsPauseEnabled = true;
    _systemMediaTransportControl.IsPlayEnabled = true;
    _systemMediaTransportControl.DisplayUpdater.Type = MediaPlaybackType.Music;
    _systemMediaTransportControl.DisplayUpdater.MusicProperties.Title = "Test Title";
    _systemMediaTransportControl.DisplayUpdater.MusicProperties.Artist = "Test Artist";


Now we have audio playing, but the Universal Volume Control isn’t working completely yet. We need to make sure that PlaybackStatus of the SystemMediaTransportControl is reflecting the MediaPlayer state. The code is straightforward but needs to be there.

private void BackgroundMediaPlayerCurrentStateChanged(MediaPlayer sender, object args)
    if (sender.CurrentState == MediaPlayerState.Playing)
        _systemMediaTransportControl.PlaybackStatus = MediaPlaybackStatus.Playing;
    else if (sender.CurrentState == MediaPlayerState.Paused)
        _systemMediaTransportControl.PlaybackStatus = MediaPlaybackStatus.Paused;


The Universal Volume Control has buttons we need to handle as well. In this example we just handle the Play and Pause button, but you can think about implementing the Next and Previous buttons as well.

private void MediaTransportControlButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
    switch (args.Button)
        case SystemMediaTransportControlsButton.Play:
        case SystemMediaTransportControlsButton.Pause:


Yes that was all. I know there’s quite a lot of preparations for getting the Background Audio working, but now we can expand this base into a fully fledged audio app.

You can download the full solution here.