I’m still working away on my latest Windows App Store app, and one of the features I wanted to make sure to support was background audio: that is, I wanted the app to still play music when it was snapped to the side of the screen, or even pushed to the back when another app was launched. I found there was plenty of information about on the web, but because things changed a little from the progression from Windows 8 Preview to Windows 8 to Windows 8.1, the documentation I found was of varying degrees of usefulness.

In a nutshell, here’s what you need to do:

  1. Play the audio using the MediaElement control,
  2. Change the app manifest to support background audio and provide it with the name of the app,
  3. Support SystemMediaTransportControls

Here’s those steps in a little more detail.

 

Playing audio with MediaElement

Using MediaElement is a piece of cake: just add the control in XAML (or create it in code) and set the source to point where the audio is stored. The MediaElement control will play back your audio from either a file stored locally, or a stream from over the network.  There’s a little bit of faffing around to set the stream to the local Music folder, but when you’ve done it once just save the code snippet away in your collection of useful things to know.

Assuming we’ve defined mediaplayer to be a MediaElement control, here’s how to do it in C#:

Playing Audio from the Internet

mediaplayer.Source = "http://mywebsite.com/myaudio.mp3";

Playing Audio from a file stored in the Music folder

var audioFile = await KnownFolders.MusicLibrary.GetFileAsync("myaudiofile.mp3");

var stream = await audioFile.OpenAsync(Windows.Storage.FileAccessMode.Read);

mediaplayer.SetSource(stream, audioFile.ContentType);

Here’s a link to some MSDN docs for more details on using MediaElement.

 

Editing the App Manifest

Open up the Package.appxmanifest file, where all the goodies hang out. Select the Declarations tap, and then add Background Tasks under Available Declarations. Under Properties, select Audio and then in the Entry Point: field, enter the name of your app. There, that’s wasn’t so bad, was it? Here's a picture to prove it really was that easy.

 

Support your local SystemMediaTransportControls

At this point, you’re probably thinking something like “Uh-oh, that was easy. Things are never this easy. The last part must be a huge pain in the ass”, right? Well, I’m sorry to let you down, but it’s actually quite straightforward.

But first: what exactly is SystemMediaTransportControls?

Essentially it's a pop-up control panel which happens when you press a physical volume control on your PC, or a play/pause/volume button if your device has those. Think about it: if your app is playing away in the background, how can the user quickly tell it to shut the heck up without switching through all the other running apps trying to find it and then stabbing frantically at a mute button?

The SystemMediaTransportControls eh.. control is a high-level play/pause and volume control that can float over all the other apps on your system. All the Windows tablets I have seen have volume control buttons, and it is this control which appears when you press them. It’s up to you to hook up your app into this control, so that the user can access it and stop or adjust the audio,  no matter what else they are up to. It’s nice too: it even has a little thumbnail graphic you can change.

 

By the way, did you know there is a handy shortcut for taking screen captures from a Windows tablet? Just hold down the Windows key, and press the Volume Down button. The current screen will be saved into the Pictures library, under the Screenshots folder. I grabbed that image from my delightful Dell Venue Pro 8 tablet. Don't press Windows and Volume Up unless you want to activate Narrator and freak yourself out.

Supporting SystemMediaTransportControls is a matter of declaring an instance and then supporting some handlers. This is all the code I needed to add:

 

public Playback() // My class constructor

{

   this.InitializeComponent();

   // Hook up app to system transport controls.

   systemControls = SystemMediaTransportControls.GetForCurrentView();

   systemControls.ButtonPressed += SystemControls_ButtonPressed;

   // Register to handle the following system transpot control buttons.

   systemControls.IsPlayEnabled = true;

   systemControls.IsPauseEnabled = true;

}

void SystemControls_ButtonPressed(SystemMediaTransportControls sender,

SystemMediaTransportControlsButtonPressedEventArgs args)

{

   switch (args.Button)

   {

       caseSystemMediaTransportControlsButton.Play:

      PlayMedia();

      break;

   caseSystemMediaTransportControlsButton.Pause:

      PauseMedia();

      break;

   default:

   break;

  }

}

async void PlayMedia()

{

 await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>

   {

   mediaplayer.Play();

});

}

 async void PauseMedia()

{

   await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>

   {

      mediaplayer.Pause();

   });

}

 

A surprisingly small amount of code. You can also change that thumbnail image, by playing with SystemMediaTransportControlsDisplayUpdater, like this:

 

SystemMediaTransportControlsDisplayUpdater updater = systemControls.DisplayUpdater;

updater.Thumbnail = RandomAccessStreamReference.CreateFromUri(new Uri(/* pointer to image */));

updater.Update();

 

Here’s the MSDN docs to help you with more details: playing in the background, and supporting SystemMediaTransportControls. If you are searching for code samples, in Windows 8 you had to support MediaControl rather than SystemMediaTransportControls. Yes, it had a snappier name, but it’s now deprecated so bear that in mind when looking at code samples.

OK, back to work for me, and Happy New Year to you!