How to play background audio for Windows Phone 8
[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]
This topic demonstrates how to create a Windows Phone app that continues playing audio when the app is no longer in the foreground. There are two types of background audio apps: one plays local media, and the other plays streaming media. In this topic we describe how to implement a Windows Phone app that plays local media by using an audio playback agent.
Tip
For a description of the architecture of a background audio app, see Background audio overview for Windows Phone 8. The overview includes best practices to follow when you implement background audio in your app. For examples of how you can implement background audio in a Windows Phone app, download the Background Audio Player Sample and the Background Audio Streamer Sample.
This topic contains the following sections.
- Creating a background audio app
- Creating an audio playback agent
- Testing the sample app
- Related Topics
Creating a background audio app
To play background audio, create a project that uses the Windows Phone Audio Playback Agent project template in Visual Studio. Then, reference the background agent project from the main project for your app.
To create a background audio app
In Visual Studio, create a new C# project using the **Windows Phone App ** template.
In the Name box, type a name for your project, and then click OK. In this topic we use the project name BackgroundAudioPlayerSample.
For the target Windows Phone OS version, click Windows Phone OS 8.0, and then click OK.
To add audio files
In Solution Explorer, right-click the app project, click Add, and then click New Folder. Name the folder Audio.
Right-click the Audio folder, click Add, and then click Existing Item.
In the Add Existing Item dialog box, find and select several audio files, for example, MP3 music files in your Music library, and then click Add. For info about file formats that you can use with the background audio player, see Supported media codecs for Windows Phone 8.
In Solution Explorer, in the Audio folder, select all of the audio files you just added. In the Properties pane, in the Copy to Output Directory box, click the drop-down arrow, and then click Copy if newer.
To create the UI
In Solution Explorer, double-click MainPage.xaml to open it in Designer.
Replace the StackPanel element named TitlePanel with the following XAML code:
<!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="BACKGROUND AUDIO PLAYER" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="play a song" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel>
Replace the Grid element named ContentPanel with this XAML code:
<!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel Orientation="Horizontal" Width="420" Margin="18,40,18,0" VerticalAlignment="Top"> <Button Content="prev" x:Name="prevButton" Height="140" Width="140" Click="prevButton_Click"/> <Button Content="play" x:Name="playButton" Height="140" Width="140" Click="playButton_Click"/> <Button Content="next" x:Name="nextButton" Height="140" Width="140" Click="nextButton_Click"/> </StackPanel> <TextBlock x:Name="txtCurrentTrack" Height="75" HorizontalAlignment="Left" Margin="12,193,0,0" VerticalAlignment="Top" Width="438" TextWrapping="Wrap" /> </Grid>
A StackPanel is a convenient element for arranging buttons. In this case, you arrange them horizontally by using the Orientation property.
The view in Designer now looks like this:
To add the code for the main page
In Solution Explorer, right-click MainPage.xaml, and then click View Code.
Add the following using statement to the top of the MainPage.xaml.cs file:
using Microsoft.Phone.BackgroundAudio;
Add the following button click event handler code to the MainPage class in MainPage.xaml.cs:
#region Button Click Event Handlers private void prevButton_Click(object sender, RoutedEventArgs e) { BackgroundAudioPlayer.Instance.SkipPrevious(); } private void playButton_Click(object sender, RoutedEventArgs e) { if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState) { BackgroundAudioPlayer.Instance.Pause(); } else { BackgroundAudioPlayer.Instance.Play(); } } private void nextButton_Click(object sender, RoutedEventArgs e) { BackgroundAudioPlayer.Instance.SkipNext(); } #endregion Button Click Event Handlers
Notice that the playButton_Click handler actually toggles between play and pause depending on the current state of playback.
In the constructor for the MainPage class, add an event handler for the PlayStateChanged event.
BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged);
Implement the Instance_PlayStateChanged method as follows:
void Instance_PlayStateChanged(object sender, EventArgs e) { switch (BackgroundAudioPlayer.Instance.PlayerState) { case PlayState.Playing: playButton.Content = "pause"; break; case PlayState.Paused: case PlayState.Stopped: playButton.Content = "play"; break; } if (null != BackgroundAudioPlayer.Instance.Track) { txtCurrentTrack.Text = BackgroundAudioPlayer.Instance.Track.Title + " by " + BackgroundAudioPlayer.Instance.Track.Artist; } }
Because this app plays audio in the background, it’s likely that audio is already playing when the app resumes. The app UI shows this by displaying the current state of playback and the currently playing track.
To update the UI when the app is opened, override the OnNavigatedTo virtual method by adding the following code to the MainPage class in MainPage.xaml.cs:
protected override void OnNavigatedTo(NavigationEventArgs e) { if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState) { playButton.Content = "pause"; txtCurrentTrack.Text = BackgroundAudioPlayer.Instance.Track.Title + " by " + BackgroundAudioPlayer.Instance.Track.Artist; } else { playButton.Content = "play"; txtCurrentTrack.Text = ""; } }
To add the code for app initialization
In Solution Explorer, right-click App.xaml, and then click View Code.
Add the following using statements to App.xaml.cs:
using System.IO.IsolatedStorage; using System.Windows.Resources;
The BackgroundAudioPlayer can only play files from isolated storage or from a remote URI. Add the following method to the App class to copy the audio files from the app’s installation folder to isolated storage. Make sure the files array contains the actual names of the audio files you added to the project.
private void CopyToIsolatedStorage() { using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication()) { string[] files = new string[] { "Kalimba.mp3", "Maid with the Flaxen Hair.mp3", "Sleep Away.mp3" }; foreach (var _fileName in files) { if (!storage.FileExists(_fileName)) { string _filePath = "Audio/" + _fileName; StreamResourceInfo resource = Application.GetResourceStream(new Uri(_filePath, UriKind.Relative)); using (IsolatedStorageFileStream file = storage.CreateFile(_fileName)) { int chunkSize = 4096; byte[] bytes = new byte[chunkSize]; int byteCount; while ((byteCount = resource.Stream.Read(bytes, 0, chunkSize)) > 0) { file.Write(bytes, 0, byteCount); } } } } } }
Call the CopyToIsolatedStorage method in the constructor for the App class.
// Copy media to isolated storage. CopyToIsolatedStorage();
Creating an audio playback agent
The AudioPlayerAgent is the piece of the app that continues to run in the background when the user switches to another foreground app.
To add the Audio Playback Agent project to the solution
In Solution Explorer, right-click your solution, click Add, and then click New Project.
In the Add New Project dialog box, click Windows Phone Audio Playback Agent.
In the Name box, type a name for your project, and then click OK. In this topic we use the project name MyAudioPlaybackAgent.
For the target Windows Phone OS version, click Windows Phone OS 8.0, and then click OK.
The solution now has two projects, the app project and the background agent project.
In Solution Explorer, in your app project, right-click References, and then click Add Reference.
In the Reference Manager dialog box, click Solution, and then click Projects. Select the background agent project that you created earlier, and then click OK.
To implement the audio player agent
In Solution Explorer, double-click AudioPlayer.cs in the Agent project to open the file in the code editor.
Add the following using statement to the top of AudioPlayer.cs:
using System.Collections.Generic;
In the AudioPlayer.cs file, declare a static integer at class scope level in the AudioPlayer class. This variable keeps the current track number.
// What's the current track? static int currentTrackNumber = 0;
Create a static list of tracks by adding the following code to the AudioPlayer class in AudioPlayer.cs:
// A playlist made up of AudioTrack items. private static List<AudioTrack> _playList = new List<AudioTrack> { new AudioTrack(new Uri("Kalimba.mp3", UriKind.Relative), "Kalimba", "Mr. Scruff", "Ninja Tuna", null), new AudioTrack(new Uri("Maid with the Flaxen Hair.mp3", UriKind.Relative), "Maid with the Flaxen Hair", "Richard Stoltzman", "Fine Music, Vol. 1", null), new AudioTrack(new Uri("Sleep Away.mp3", UriKind.Relative), "Sleep Away", "Bob Acri", "Bob Acri", null), // A remote URI new AudioTrack(new Uri("https://traffic.libsyn.com/wpradio/WPRadio_29.mp3", UriKind.Absolute), "Episode 29", "Windows Phone Radio", "Windows Phone Radio Podcast", null) };
It’s important to make the playlist a static class so that it isn’t recreated every time a call is made into the background agent.
To handle user actions such as clicking the play, next, and previous buttons, add the following three methods to the AudioPlayer class in AudioPlayer.cs:
private void PlayNextTrack(BackgroundAudioPlayer player) { if (++currentTrackNumber >= _playList.Count) { currentTrackNumber = 0; } PlayTrack(player); } private void PlayPreviousTrack(BackgroundAudioPlayer player) { if (--currentTrackNumber < 0) { currentTrackNumber = _playList.Count - 1; } PlayTrack(player); } private void PlayTrack(BackgroundAudioPlayer player) { if ((player.Track == null) || (player.Track.Title != _playList[currentTrackNumber].Title)) { // If it's a new track, set the track player.Track = _playList[currentTrackNumber]; } // Play it if ((player.Track != null) && (player.PlayerState != PlayState.Playing)) { player.Play(); } }
To handle play state changes, add the following switch statement to the OnPlayStateChanged method, before the call to NotifyComplete:
switch (playState) { case PlayState.TrackEnded: PlayNextTrack(player); break; // Handle other PlayState changes here }
To handle user actions, add the following switch statement to the OnUserAction method, before the call to NotifyComplete:
switch (action) { case UserAction.Play: PlayTrack(player); break; case UserAction.Pause: player.Pause(); break; case UserAction.SkipPrevious: PlayPreviousTrack(player); break; case UserAction.SkipNext: PlayNextTrack(player); break; }
Testing the sample app
This is all the code necessary to implement a basic app that plays audio in the background. This app runs under the lock screen, and the universal volume control (UVC) controls the playback. There are more features that you can add, such as a richer UI, and support for playing audio from a remote source using a web URI to an audio file. You can also implement support for user actions such as stop, fast forward, rewind, or seek.
To test the sample app
Run the app in the emulator.
On the main page of the app, tap play to play the first song.
Press the F12 key twice to engage the lock screen. The universal volume control appears temporarily.
For more info, see How to use the computer keyboard with the emulator for Windows Phone 8.
To increase or decrease the volume, and to display the UVC again temporarily, press F9 or F10.
To stop playback, display the UVC and press the pause button, or close the emulator.
See Also
Reference
Microsoft.Phone.BackgroundAudio