How to switch from MediaElement to BackgroundMedia

2019-08-07 08:29发布

问题:

I have a music player page like PlayMusic.xaml and it uses MediaPlayer element to play music.

I want to switch BackgroundMediaPlayer whenever user clicks back button or Windows Button or Lock Screen.

I also would like to continue where ever song is remained. (Like BackgroundMediaPlayer should continue from 30th second)

Is there any mechanism in Windows phone like when ever when I lose focus from MediaPlayer I can switch to BackgroundMediaPlayer and continue playing music?

Note: I can directly use BackgroundMediaPlayer then it always plays music but on this case I cannot use MediaPlayer in PlayMusic.xaml which gives ability to watch video clip, fullscreen and seek controls.

回答1:

There is no specific mechanism for this that I know of. You can build one yourself, but it is not simple:

  1. First, you need to have a working background audio task and know how to communicate with it (this is not easy in itself, this example helped me a bit).
  2. When you start playing anything in the MediaPlayer, your background audio task gets canceled. When you use it again, its Run method is called once more in the same process. Because of this, the background task must have its lifecycle properly managed, i.e. you need to subscribe to events and get a deferral in the Run method, and unsubscribe from events, call BackgroundMediaPlayer.Shutdown() and release the deferral in the Cancel event. Also, I found that I need to subscribe to BackgroundMediaPlayer.MessageReceivedFromBackground in the foreground process again after the task is restarted, because the restart seems to clear it.
  3. You can detect that the MediaPlayer "lost focus" (and start background playback) when the page is being navigated from. However, this will not cover the case of the user multitasking away from your application or the case of the screen being turned off. You can catch these using the CoreWindow.GetForCurrentThread().Activated event.
  4. When you are switching to background audio, you need to pass it the current position. This can be done using messaging (BackgroundMediaPlayer.SendMessageToBackground).
  5. You can start the background playback on the specified position by turning AutoPlay off and setting the position after MediaOpened fires.

I hope this helps. I am still battling with this (it is one giant trial and error endeavor), but it seems to be working.



回答2:

In Your Package Manifest you need to go to Declarations Tab and select Background Tasks and then select Audio and also select an entry point for your applications.

Inside Your Xaml

<MediaElement AutoPlay="True"
    AreTransportControlsEnabled="True"
    x:Name="musicPlayer"
    Source="Assets/video1.mp4"
    AudioCategory="BackgroundCapableMedia"
    CurrentStateChanged="MusicPlayer_CurrentStateChanged"/>

Code Behind C#

SystemMediaTransportControls systemControls;

public BlankPage7()
{
    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;

}

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

        case SystemMediaTransportControlsButton.Pause:
            PauseMedia();
            break;

        default:
            break;
    }
}

private 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;
    }
}

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();
    });
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    if (systemControls != null)
    {
        systemControls.ButtonPressed -= SystemControls_ButtonPressed;
        systemControls.IsPlayEnabled = false;
        systemControls.IsPauseEnabled = false;

        systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
    }
}

This would i hope solve your purpose... For further details you can refer MSDN Link.