Background audio in Windows Phone 7.5 (Part 1)
Summary
Using background audio for Windows Phone 7.5 is a great way of playing audio content such as internet radio stations, podcasts and music tracks even when your application is no longer in the foreground and when the phone is locked.
This series of blog posts will help you get the most of the capabilities of this new “Mango” feature and to avoid several gotchas associated with it.
What are we covering in these blog posts
This first post will start with some introduction to the Background Audio, how to get started, the Marketplace Certification requirements and how to integrate your background audio app with the Music+Videos Hub on the phone.
The second post will deal with some implementation advice on how to specify a playlist and look in more detail at how a Background Audio app works.
The third post will discuss particular challenges of keeping a great user experience when playing audio files which are streamed from a remote server.
Getting Started with Background Audio
A good first place to look for advice if you’re new to a Windows Phone feature is on MSDN. In particular there is a great overview of background audio here. This includes a code-walkthrough which will get you to create a simple project with a foreground application and a background audio agent which is responsible for providing audio to the Zune Media Queue. The Windows Phone 7.1 SDK sample for background audio can be found here. And the sample for this article series can be downloaded from this location.
This MSDN article also has a good architectural diagram for Background Audio as shown below.
For the purpose of these blog posts, it is assumed that you are writing “Background Audio Playlist Application” rather than the more complex “Background Audio Streaming Application”.
BackgroundAudioPlayer (BAP)
(BackgroundAudioPlayer MSDN class reference link)
As can be seen from the architecture diagram the BackgroundAudioPlayer (BAP) is the key to understanding the background audio feature.
However notice from the diagram that the Application UI code (“app code”) is isolated from the AudioPlayerAgent code (“agent code”), via the Zune Media Queue. This is easy to overlook as from both app code and agent code perspective, it appears they are sharing the same BAP object.
Universal Volume Control (UVC)
The Universal Volume Control (UVC) allows the user to control any audio playing in the background (whether it is from Zune, IE or your app). It allows users to play, pause, rewind, fast-forward and skip and also launch your application for more in-depth control of the audio that is playing. It also displays the current playing track title and author. In the case of the picture of the UVC above it can be seen from the icon before the title that the phone is streaming audio content from a remote server. This streaming icon is automatically added by the phone OS if you are playing from a remote server, rather than playing from your app’s Isolated Storage.
Background Audio Marketplace Certification requirements
As with any other Windows Phone feature it’s worth checking out the Marketplace Certification Requirements early in your development to check what you are allowed to do and what is required of your application which uses a particular feature. The Marketplace certification requirements can be found on MSDN here. For the Background Audio feature, the relevant sections are under “Additional Requirements for Specific Application types”.
Music and Videos Hub integration
Firstly you have a choice to make for your application: should it be registered to the Music and Videos Hub or not? Summarizing this choice focusing on technical issues:
Certification Section | Non-Music and Video Hub app | Music and Video Hub app |
6.4 Music + Videos Hub Application | Not applicable | Must comply, in particular watch out for: 6.4.2 - Music + Videos Hub History and Now Playing List Functionality 6.4.3 - Music + Videos Hub History List Updates 6.4.4 - Music + Videos Hub New List Updates |
6.5 Non Music + Videos Hub Applications That Play Media | Must comply, in particularly watch out for: 6.5.1 – Initial Launch Functionality 6.5.2 - Configurable Functionality 6.5.3 - Applications that Play a Video or Audio Segment | Not applicable |
In this series we will focus on music application which implements background audio playback and integrates into Music and Video hub on the phone.
Background Audio Marketplace Certification Requirements
The additional requirements for Background Audio in section 6.9 are fairly straightforward to adhere to if you follow a few key design principles for the Background Audio player.
Requirement | Design Principle |
6.9.1- User Initiated Background Audio | All audio should be started by the user (not automatically from code) |
6.9.2 – Stopping Background Audio | User should be able to find the playback controls easily |
6.9.3 – Universal Volume Control Commands | UVC should be able to control the audio when the app isn’t running in the foreground |
6.9.4 – Universal Volume Control Strings | UVC content should be relevant |
6.9.5 – Background Audio Streaming Agent | (Not applicable for a AudioPlayerAgent which only tells the Zune Media Queue which file or URL to play) Streaming agent should only contain code relevant to streaming |
These aren’t technical issues so we won’t cover them any more in these blog posts – however it is clear that your application design should meet all of these requirements.
Integrating with the Music+Videos Hub on the phone
If you have decided to integrate with the Music+Video hub, the following MSDN link contains details how to achieve that: “How to: Integrate with the Music and Videos Hub for Windows Phone”.
To summarize this page you will need to:
- Test the integration on a physical Windows Phone device (the emulator doesn’t have the Music + Videos Hub).
- Update your Application Manifest file to be able to test the Hub integration.
- Update the ‘Now Playing’ tile (do this from the background agent when switching between tracks as it’s the only way to keep it accurate)
- Update the ‘History’ list
- Update the ‘New’ list
It is worth noting that when providing icons for your audio to the Music + Videos Hub these must be local to the device, and therefore be either part of the application XAP or be found in the application’s Isolated Storage. This ensures that the phone will always be able to show an image in the Music + Videos Hub, even if your device is disconnected from the internet, or if images are not available on a remote server.
Integration between the Music hub and your app’s “playback experience”
A lot of the technical detail you will need to integrate your app and the Music Hub is covered in the MSDN page above, however it is worth expanding on how to achieve the integration between the Music and Video hub and your application’s “playback experience”.
Consider Marketplace Requirement 6.4.2:
When a user taps a tile associated with the application in the History or Now Playing list of the Music + Videos Hub, the application must either (a) launch the playback experience for the content identified in the tile, or (b) launch a view that provides information about the previously played media content and allows the user to resume. The application must not launch to the main or default landing page when the user taps on a content tile in the History, Now Playing, or New list of the Music + Videos Hub.
It is worth breaking down the Now Playing scenario:
- User initiates playback from the UI
- The agent code will provide an AudioTrack to the BAP which describes the audio to play. This will be used to set up the UVC and start playback.
- At the same time the agent code should inform the Music and Videos Hub about the track that is currently playing (and add it to the history).
- User can at a later time tap the Now Playing tile (or the UVC track title which will use the same information).
If you skip step 3 then your application will launch, but only on the main page, and your app will fail requirement 6.4.2.
To fix this you will need to pass in PlayerContext to the MediaHistoryItem so that you can detect on application launch that this is a special launch from the Music + Videos Hub or the UVC.
For example, for a very simple agent which just plays a single episode of a web radio, and uses a file “Image.png” as the media image to be displayed in the Music + Videos Hub:
protected override void OnPlayStateChanged(
BackgroundAudioPlayer player,
AudioTrack track,
PlayState playState)
{
switch (playState)
{
case PlayState.TrackEnded:
player.Track = GetNextTrack();
break;...
private AudioTrack GetNextTrack()
{
// set the next track - in this case one hardcoded track
AudioTrack track = new AudioTrack(
new Uri("https://traffic.libsyn.com/wpradio/WPRadio_52.mp3"),
"WP Radio #52",
"WP Radio",
"",
null);
// get the stream of "Image.png" which is in the application XAP as Content
StreamResourceInfo sri = Application.GetResourceStream(
new Uri("Image.png", UriKind.Relative));
using (Stream imageStream = sri.Stream)
{
MediaHistoryItem nowPlayingItem = new MediaHistoryItem();
nowPlayingItem.Title = track.Title;
nowPlayingItem.PlayerContext.Add("LaunchNowPlaying", "true");
nowPlayingItem.ImageStream = imageStream;
MediaHistory.Instance.NowPlaying = nowPlayingItem;// reuse the same image stream for recent item, need to reset it first however
imageStream.Seek(0, SeekOrigin.Begin);
MediaHistoryItem recentItem = new MediaHistoryItem();
recentItem.Title = track.Title;
recentItem.PlayerContext.Add("LaunchRecentItem", "1"); // put an ID of the recent item to add
recentItem.ImageStream = imageStream;
MediaHistory.Instance.WriteRecentPlay(recentItem);
}
return track;
}
To complete the integration, in main application’s initial page code-behind (e.g. MainPage.xaml.cs) you need to detect that the application was launched from the Music + Videos Hub or the UVC. Here is a simple example which works with the PlayerContext set in the agent code sample above.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { var queryString = NavigationContext.QueryString; string queryStringValue; if (queryString.TryGetValue("LaunchNowPlaying", out queryStringValue)) { MessageBox.Show("LaunchNowPlaying is " + queryStringValue, "Launch from UVC / Hub Now Playing!", MessageBoxButton.OK); // TODO: navigate to "Now Playing" experience } else if (queryString.TryGetValue("LaunchRecentItem", out queryStringValue)) { MessageBox.Show("LaunchRecentItem is " + queryStringValue, "Launch from Hub Recent item", MessageBoxButton.OK); // TODO: Find the item specified, start playing it, navigate to "Now Playing" experience } else { MessageBox.Show("Normal launch", "Normal launch", MessageBoxButton.OK); } }
In an application using the MVVM pattern you should pass down the navigation query string from the View to the ViewModel in a message – this will stop you having too much application logic in the View class.
What next
This blog post explained the principles needed to implement a Background Audio agent which will meet the Marketplace Certification requirements and will be integrated to the Music and Videos Hub on the phone.
The next blog post in this series will tackle further implementation strategies for a background audio player application.
Written by Paul Annetts