Delen via


How to play audio in the background (XAML)

[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]

To play audio in the background, declare the Audio background task and handle the SystemMediaTransportControls buttons.

Important  Windows 8.1 introduces the SystemMediaTransportControls class which replace the MediaControl class. You should use SystemMediaTransportControls in your app.

 

Note  If a video stream is enabled to play in the background, when the app is switched to the background you will hear the audio but not see the video. This is by design. This reduces the power requirements of the device while it is playing the video in the background.

 

To see this feature in action as part of a complete media-playback sample, see Media playback, start to finish.

Prerequisites

This topic assumes that you know how to create a basic Windows Store app using C++, C#, or Visual Basic. For help creating your first app, see Create your first Windows Store app using C# or Visual Basic.

This topic assumes you are familiar with the MediaElement class. For an introduction on using the MediaElement class, see the Quickstart: video and audio.

Instructions

Step 1: Declare the background audio task

You must explicitly declare that your app will perform background tasks.

  1. Open the project file for your app in Microsoft Visual Studio.

  2. Double-click the Package.appmanifest file in the Solution Explorer to open the Package.appmanifest dialog box.

  3. Click the Declarations tab, then select Background Tasks from the Available Declarations drop-down box.

  4. Click Add, then check the Audio checkbox.

    You can also make a background declaration for a video stream by using the same manifest file that you created for audio in the preceding steps. To do this, set the "Task Type" attribute to audio.

  5. Specify the entry point. In most cases, if your project is named Foo you will specify Foo.App.

Step 2: Set the AudioCategory

Set the AudioCategory property on the MediaElement to either Communications or BackgroundCapableMedia. You can also specify this property in code.

The following XAML creates a MediaElement and sets the AudioCategory to BackgroundCapableMedia.

<MediaElement Name="media" 
              AudioCategory="BackgroundCapableMedia" 
              Source="Somesong.mp3" />

Step 3: Support SystemMediaTransportControls

Windows 8.1 introduces the SystemMediaTransportControls class which replaces the MediaControl class. You should use SystemMediaTransportControls in your app. For completeness, the steps to implement background audio support with MediaControl are included below, but you should only use SystemMediaTransportControls. See How to use the system media transport controls for a more in-depth how-to on using SystemMediaTransportControls.

Even if an app is declared to play audio in the background, the app must enable the SystemMediaTransportControls play and pause buttons by setting IsPlayEnabled and IsPauseEnabled to true. The app must also handle the ButtonPressed event, which notifies the app when the system media transport control buttons are pressed. By providing this minimal event handling support, you make it possible for the user to play or pause the audio without bringing the app to the foreground.

In order to update objects on the UI thread from the ButtonPressed event handler, such as the MediaElement object, you must marshal the calls through the CoreDispatcher. This is because the ButtonPressed event handler will not be called from the UI thread. And only the UI thread can modify objects on the UI thread. If you attempt to modify UI objects from a non-UI thread, an exception will be thrown. The code example below shows how to do this.

In addition to handling the ButtonPressed event, you must also notify the SystemMediaTransportControls when the media state changes, such as when it is paused or playing. To notify the SystemMediaTransportControl about media state changes, set its PlaybackStatus property to one of the values in MediaPlaybackStatus.

Here is some code that sets up SystemMediaTransportControls in an app that plays audio in the background. The code does the following steps:

Here is the code that creates MediaElement.

<MediaElement x:Name="musicPlayer" 
          Source="Music/music1.mp3"
          AudioCategory="BackgroundCapableMedia"
          CurrentStateChanged="MusicPlayer_CurrentStateChanged" />

Here is the code that sets up the SystemMediaTransportControls.

SystemMediaTransportControls systemControls;

void InitializeTransportControls()
{
    // 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;
}

Here is the code that handles the CurrentStateChanged event of the MediaElement and updates the PlaybackStatus property of SystemMediaTransportControls.

void MusicPlayer_CurrentStateChanged(object sender, RoutedEventArgs e)
{
    switch (musicPlayer.CurrentState)
    {
        case MediaElementState.Playing:
            systemControls.PlaybackStatus = MediaPlaybackStatus.Playing;
            break;
        case MediaElementState.Paused:
            systemControls.PlaybackStatus = MediaPlaybackStatus.Paused;
            break;
        case MediaElementState.Stopped:
            systemControls.PlaybackStatus = MediaPlaybackStatus.Stopped;
            break;
        case MediaElementState.Closed:
            systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
            break;
        default:
            break;
    }
}

Here is the code for the ButtonPressed event handler and helper methods to play and pause the MediaElement. Notices that the calls to Play and Pause are marshaled to the UI thread through the CoreDispatcher using Dispatcher.RunAsync.

void SystemControls_ButtonPressed(SystemMediaTransportControls sender,
    SystemMediaTransportControlsButtonPressedEventArgs args)
{
    switch (args.Button)
    {
        case SystemMediaTransportControlsButton.Play:
            PlayMedia();
            break;
        case SystemMediaTransportControlsButton.Pause:
            PauseMedia();
            break;
        default:
            break;
    }
}

async void PlayMedia()
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        musicPlayer.Play();
    });
}

async void PauseMedia()
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        musicPlayer.Pause();
    });
}

For more info on the SystemMediaTransportControl, see How to use the system media transport controls and the SystemMediaTransportControls sample

Step 4: Register handlers on MediaControl (Windows 8 only)

Important  

MediaControl has been replaced in Windows 8.1 SystemMediaTransportControl. You should use SystemMediaTransportControl instead.

 

Even if an app is registered to play music or video in the background, the app must handle the following MediaControl events: PlayPressed, PausePressed, StopPressed, and PlayPauseTogglePressed. By providing this minimal event handling support, you make it possible for the user to play or pause the music or video stream in the background without bringing the application to the foreground.

In most cases you will probably want to create transport controls (buttons for playing, stopping, and pausing) to control the MediaElement. This article does not show this, but for examples of how to do this see the Quickstart: video and audio and Quickstart: create a media player application.

MediaControl is a static class, so you just add the event handlers directly onto the events of the class.

  1. In the Solution Explorer pane, click your app’s C# file to open it. In this example the we are using the MainPage.xaml.cs file.

  2. Use the following code to register for the Play, Pause, Stop, and Play/Pause toggle buttons for your app:

    MediaControl.PlayPauseTogglePressed += MediaControl_PlayPauseTogglePressed;
    MediaControl.PlayPressed += MediaControl_PlayPressed;
    MediaControl.PausePressed += MediaControl_PausePressed;
    MediaControl.StopPressed += MediaControl_StopPressed;
    
  3. Use the following code to handle the events that are raised when the Play, Pause, Stop, and Play/Pause events are raised.

    void MediaControl_StopPressed(object sender, object e)
    {
        // media is a MediaElement defined in XAML
        media.Stop();
    }
    
    void MediaControl_PausePressed(object sender, object e)
    {
        // media is a MediaElement defined in XAML
        media.Pause();
    }
    
    void MediaControl_PlayPressed(object sender, object e)
    {
        // media is a MediaElement defined in XAML
        media.Play();
    }
    
    void MediaControl_PlayPauseTogglePressed(object sender, object e)
    {
        if (MediaControl.IsPlaying == true)
        {
            // media is a MediaElement defined in XAML
            media.Pause();
        }
        else
        {
            // media is a MediaElement defined in XAML
            media.Play();
        }
    }
    

Remarks

Note  If you have an app that performs other tasks in addition to streaming audio or video, then when the app loses focus and is no longer the active window, your app should stop doing non-media related work. Your app can still stream audio and, in the case of an audio-video stream, video streaming will stop automatically.

 

Complete example

For a complete example of how to stream audio and video, see the XAML media playback sample.

How to use the system media transport controls

SystemMediaTransportControls sample

Playback manager sample

Quickstart: video and audio

Quickstart: create a media player application

Media playback, start to finish