Windows Phone 8.1 for Developers–The Background Media Player
This blog post is part of a series about how Windows Phone 8.1 affects developers. This blog post talks about how to use the background media player and is written by Per-Olof Bondesson, Robert Hedgate and Andreas Hammar at Jayway and was originally posted here.
Dude… what is going on here?!
Right! You are developing a new music app on Windows phone 8.1 and nothing looks like it did a week ago. Gone is the MediaService to find the music, the BackgroundPlayer and all other classes that you were used to. This post is here to help you find your bearing with the new API’s.
Creating the background service
Adding the lib
Create a new Windows Runtime Component. This is where your entry point for the Audio task will be. The entry point is a class that implements IBackgroundTask. This gives you one method that will be invoked on startup of the Audio task named Run. In order to keep the Task alive indefinitely you need to keep track of the deferral that exists on the IBackgroundTaskInstance. Placing the deferral in a field for safe keeping will be enough. When the operating system cancels your task you will need to call Complete on this said deferral. An example of a bare bone implementation of your task should look something like the following
public sealed class AudioPlayer : IBackgroundTask
{
private BackgroundTaskDeferral _deferral;
public void Run(IBackgroundTaskInstance taskInstance)
{
_deferral = taskInstance.GetDeferral();
taskInstance.Canceled += TaskInstance_Canceled;
}
private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
_deferral.Complete();
}
}
Note that right now the task isn’t really an audio player. But it is enough code to test that we have a functioning task. At least we will be able to test it, as soon as we have enabled it in the app manifest.
Enabling the background player
Open the app manifest. In Declarations add a BackgroundTask, then check the Audio task type and point the Entry Point to the AudioPlayer class that we created in the previous part. It should look something like the following
After this, we need to reference the Windows Runtime Component in the app project. There is no need to use a BackgroundTaskBuilder for an Audio task. The way we start the background task is by simply by accessing BackgroundMediaPlayer.Current. You can verify this by adding a break point in the AudioPlayer class. That’s it for the basic set up. Next up is how we use the code we have made to play some music.
Background player
Playing music
The new background player got three simple methods for playing songs. SetFileSource, SetStreamSource and SetUriSource. Only one of these can be called from the foreground application, namely the SetUriSource method. The others needs to be used from your task instead. The reason for this is that the background player don´t have access to the memory where SetFIleSource or SetStreamSource is located unless it is set in the task.
Play next song when the current song ended
In our AudioPlayer class we can hook up to the MediaEnded event. Here we can find the next song to play and start playing it.
Hey where is the “Tag”?! (Communication with the foreground app)
Tag is no more! The communication between the two processes is now done by using events.
Changing song from the foreground
If you want to change song from the foreground you just call:
BackgroundMediaPlayer.Current.SetUriSource(new Uri("ms-appx:///Assets/Media/Ring02.wma"));
BackgroundMediaPlayer.Current.Play();
Remember to use SetUriSource because the other overloads will throw exceptions.
Changing song from the background
To do this we need to tell the background to start playing a song. This is done by calling the BackgroundMediaPlayer function SendMessageToBackground:
BackgroundMediaPlayer.SendMessageToBackground(new ValueSet { { "play", "0" } });
The background AudioPlayer need to have set up to listen to the message in the Run method:
BackgroundMediaPlayer.MessageReceivedFromForeground += BackgroundMediaPlayer_MessageReceivedFromForeground;
After receiving the message just do the same as in the forground to play songs.
Listen to event from the system
When your app is not active but your set up background player is the user can click on the player and expect your app to respond to these events. It can be for example play, pause, next and previous. To do this you need to set up this code in your AudioTask:
systemmediatransportcontrol = SystemMediaTransportControls.GetForCurrentView();
systemmediatransportcontrol.ButtonPressed += systemmediatransportcontrol_ButtonPressed;
systemmediatransportcontrol.PropertyChanged += systemmediatransportcontrol_PropertyChanged;
systemmediatransportcontrol.IsEnabled = true;
systemmediatransportcontrol.IsPauseEnabled = true;
systemmediatransportcontrol.IsPlayEnabled = true;
systemmediatransportcontrol.IsNextEnabled = true;
systemmediatransportcontrol.IsPreviousEnabled = true;
Then in the function systemmediatransportcontrol_ButtonPressed your app will receive the events from the phone. You can then from the AudioTask send an event to the forground using BackgroundMediaPlayer.SendMessageToForeground. This has to be set up in the foreground to work:
BackgroundMediaPlayer.MessageReceivedFromBackground += BackgroundMediaPlayer_MessageReceivedFromBackground;
You can now change your app if it is running to correspond to what the background is up to, changing song, pause etc.
Summary
This was a quick introduction on how to use the BackgroundMediaPlayer. It is a bit of work to get it to work but luckily there is a lot of help. Please look at https://msdn.microsoft.com/en-US/library/windows/apps/xaml/dn642090 for info and https://code.msdn.microsoft.com/wpapps/BackgroundAudio-63bbc319 to see a working example.
Comments
Anonymous
June 04, 2014
I tried implementing it and everything works just fine. But is there a way i can play music directly from the music library folder? Currently i need to first copy it in the application's local folder and then play from there.Anonymous
March 05, 2015
Thanks for the artice, I have tried your way, The media is played in the background, but the controls (systemmediatransportcontrol) are not displayed. any ideas?Anonymous
March 22, 2015
You may try to run the SMTC update method async to make it workAnonymous
April 08, 2015
Many times after media has begun playing in a background task, the foreground app will suspend (screen turns off, etc). At this point (occasionally and never in the debugger) the background task cancellation event will be fired with the "SystemPolicy" reason. What the is going on? How the heck do you debug this? How do you ensure the background task will continue when the foreground app is killed?