Windows Store Apps playing Background Audio with MediaElement - c#

In my Windows Phone 8.1 App, I am using Media Element. I want it to continue to play Audio even if user navigated away from app. MediaElement is using video from remote source (.mp4) file. I also tried with sample video in here;
http://go.microsoft.com/fwlink/p/?LinkID=272585
I followed example in How to play audio in the background (XAML) but could not make it work. This example is specific to Windows 8.1 not Windows Phone.
While MediaElement is playing Video Clip when I press Windows button audio stops and when I hit back it continues to work.
My code is like below;
<MediaElement x:Name="MediaElement" VerticalAlignment="Top"
HorizontalAlignment="Stretch"
AudioCategory="BackgroundCapableMedia"
MediaEnded="MediaElement_MediaEnded"
MediaFailed="MediaElement_MediaFailed"
MediaOpened="MediaElement_MediaOpened" SeekCompleted="MediaElement_SeekCompleted"
DownloadProgressChanged="MediaElement_OnDownloadProgressChanged" BufferingProgressChanged="MediaElement_BufferingProgressChanged"
AreTransportControlsEnabled="True" CurrentStateChanged="MediaElement_CurrentStateChanged" />
I have also defined Audio as Supported task Types in Package.appxmanifest
public VideoPlayer()
{
InitializeComponent();
#region SystemMediaTransportControls
// 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;
systemControls.IsStopEnabled = true;
systemControls.IsEnabled = true;
#endregion
_navigationHelper = new NavigationHelper(this);
_navigationHelper.LoadState += NavigationHelper_LoadState;
_navigationHelper.SaveState += NavigationHelper_SaveState;
}
void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
PlayMedia();
break;
case SystemMediaTransportControlsButton.Stop:
StopMedia();
break;
case SystemMediaTransportControlsButton.Pause:
PauseMedia();
break;
default:
break;
}
}
private async void StopMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
MediaElement.Stop();
});
}
async void PlayMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
MediaElement.Play();
});
}
async void PauseMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
MediaElement.Pause();
});
}
private void MediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
if (Debugger.IsAttached)
{
Debug.WriteLine("MediaElement.CurrentState: " + MediaElement.CurrentState);
}
switch (MediaElement.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;
}
}

Windows Phone doesn't use the same mechanism for Background Audio as Windows does, primarily because low-spec phones don't have enough resources to run two apps at once.
Instead, Windows Phone uses a dedicated background process to play music in the background. See the BackgroundMediaPlayer for more information on how to do this in a Windows Runtime phone app.

Related

Video player in Xamarin Forms is gone when minimized and resumed

I have implemented a video player in xamarin forms to play as a background video for my login screen. The video successfully loads at start and plays without sound and loops(as configured). But the problem is when I minimize the app and resume again, then the video is gone and I can't even play it back like video.play if paused or stopped
The links I tried are as follows
http://makanda.io/how-to-create-a-background-video-in-xamarin-forms/ (I tried this link first)
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/video-player/ (then completely replaced with this)
Both links work as desired except the issue which is the same in both links.
What I have tried to solve the issue?
I tried resuming the video as if(videoPlayer.Status == Renderers.VideoStatus.Paused) videoPlayer.Play() inside my OnAppearing() method. But it doesn't work
I am currently trying to dynamically load the video from code behind inside a stack layout. But I don't know how to set the video source from code behind. I am doing it as follows
string source = "";
switch (Device.RuntimePlatform)
{
case Device.iOS:
source = "Videos/walkthroughvideo9_16.mp4";
break;
case Device.Android:
source = "walkthroughvideo9_16.mp4";
break;
default:
source = "walkthroughvideo9_16.mp4";
break;
}
VideoPlayer video = new VideoPlayer()
{
Source = (UriVideoSource)source
};
An error says, cannot convert string to UriVideoSource
AN HELP LINK:
https://developer.android.com/reference/android/widget/VideoView
Seems like the video view does not maintain its state when the app goes into the background.
I am currently trying to dynamically load the video from code behind inside a stack layout. But I don't know how to set the video source from code behind. I am doing it as follows
I notice that your path is from local Resource, you can use the following code to load the video. If your path is an URL, you can use videoPlayer.Source = VideoSource.FromUri(source); to load it.
var videoPlayer=new VideoPlayer();
string source = "";
switch (Device.RuntimePlatform)
{
case Device.iOS:
source = "Videos/iOSApiVideo.mp4";
break;
case Device.Android:
source = "AndroidApiVideo.mp4";
break;
default:
source = "AndroidApiVideo.mp4";
break;
}
videoPlayer.Source = VideoSource.FromResource(source);
I tried resuming the video as if(videoPlayer.Status == Renderers.VideoStatus.Paused) videoPlayer.Play() inside my OnAppearing() method. But it doesn't work
Here is my running demo result, when I am back to my application, it works. I also achieve the seek to the previous time span function as well.
Here is my demo.
https://drive.google.com/file/d/1kpYbMV5mA3UdbGD7r6tLv1S2ix7AwM5B/view?usp=sharing
I used a timer as a workaround to resume the video which pauses when the app goes into sleep mode.
protected override void OnAppearing()
{
base.OnAppearing();
shouldTimerRun = true;
Device.StartTimer(new TimeSpan(0, 0, 1), () =>
{
Device.BeginInvokeOnMainThread(() =>
{
if (videoPlayer.Status == VideoStatus.Paused)
{
//videoPlayer.TimeToEnd = timeSpan;
videoPlayer.Position = timeSpan;
videoPlayer.Play();
}
});
return shouldTimerRun;
});
}
protected override void OnDisappearing()
{
base.OnDisappearing();
shouldTimerRun = false;
timeSpan = videoPlayer.Position;
}

Windows 10 BackgroundMediaPlayer SystemTransportControls Pause Button Not Working

I have recently decided to add Background Audio playback support for podcasts in my app. I have got most of it to work but, the pause button in the SystemTransportControls of the BackgroundMediaPlayer doesn't seem to do anything.
Here is my background audio task class file:
public sealed class AudioPlayer : IBackgroundTask
{
private BackgroundTaskDeferral _deferral;
public void Run(IBackgroundTaskInstance taskInstance)
{
_deferral = taskInstance.GetDeferral();
var control = BackgroundMediaPlayer.Current.SystemMediaTransportControls;
control.IsEnabled = true;
control.IsPauseEnabled = true;
control.IsPlayEnabled = true;
control.IsNextEnabled = false;
control.IsPreviousEnabled = false;
taskInstance.Canceled += TaskInstance_Canceled;
BackgroundMediaPlayer.MessageReceivedFromForeground += BackgroundMediaPlayer_MessageReceivedFromForeground;
}
private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
BackgroundMediaPlayer.Shutdown();
_deferral.Complete();
}
void BackgroundMediaPlayer_MessageReceivedFromForeground(object sender, MediaPlayerDataReceivedEventArgs e)
{
object obj;
e.Data.TryGetValue("MessageBody", out obj);
string url = (string)obj;
url = url.Replace("\"", "");
var source = MediaSource.CreateFromUri(new Uri(url, UriKind.Absolute));
var list = new MediaPlaybackList();
list.Items.Add(new MediaPlaybackItem(source));
BackgroundMediaPlayer.Current.Source = list;
BackgroundMediaPlayer.Current.Play();
}
}
It is important to note that the audio does start playing in the background but I don't have the ability to pause the audio.
Thanks,
P.
To react to SystemMediaTransportControls (SMTC) and handle each Universal Volume Control (UVC) button: play, pause, next, and previous, we need handle the SystemMediaTransportControls.ButtonPressed event in Run method like following:
public void Run(IBackgroundTaskInstance taskInstance)
{
var control = BackgroundMediaPlayer.Current.SystemMediaTransportControls;
control.ButtonPressed += control_ButtonPressed;
...
}
And in control_ButtonPressed method, deal with different buttons like:
private void control_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
//Todo with play
break;
case SystemMediaTransportControlsButton.Pause:
//Todo with pause
break;
case SystemMediaTransportControlsButton.Next:
//Todo with skip to next;
break;
case SystemMediaTransportControlsButton.Previous:
//Todo with skip to previous;
break;
}
}
For a complete sample, please refer to the official Background audio sample on GitHub, especially the MyBackgroundAudioTask class. And there is also a very nice post that will walk you through setting up background audio, reacting to device media controls, communicating with the background media player, and managing playlists. Read more at The Basics of Background Audio.

What's the easiest way to play audio in background in UWP?

I am working on my Project (a soundcloud client) and the app can play tracks just fine, but not when the app is minimized. I use the MediaElement-Object for playing the mp3 from the url. How can i force the music to continue playing the music, when the app is in the background. Or whats the easiest way/best explained tutorial to implement this. I searched alot for a good answer, but the ones, i found, was too good for me :D What means, that i didn't understand it.
To play audio in the background you will have to do a Declaration in Package.appxmanifest for a Background Tasks, enable audio and add an entry point like TestUWP.MainPage page.
Also for the user to easily be able to manage the audio you can use SystemMediaTransportControls
Here is a basic setup with Play and Pause.
xaml
<MediaElement x:Name="mediaElement" Height="100" Width="100" AreTransportControlsEnabled="True"/>
C#
public MainPage()
{
this.InitializeComponent();
systemControls = SystemMediaTransportControls.GetForCurrentView();
// Register to handle the following system transpot control buttons.
systemControls.ButtonPressed += SystemControls_ButtonPressed;
mediaElement.CurrentStateChanged += MediaElement_CurrentStateChanged;
systemControls.IsPlayEnabled = true;
systemControls.IsPauseEnabled = true;
}
private void MediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
switch (mediaElement.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;
}
}
void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
PlayMedia();
break;
case SystemMediaTransportControlsButton.Pause:
PauseMedia();
break;
case SystemMediaTransportControlsButton.Stop:
StopMedia();
break;
default:
break;
}
}
private async void StopMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement.Stop();
});
}
async void PlayMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (mediaElement.CurrentState == MediaElementState.Playing)
mediaElement.Pause();
else
mediaElement.Play();
});
}
async void PauseMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement.Pause();
});
}
Output
If you like to enable more controls you can do using the available properties for ex.
systemControls.IsNextEnabled = true;
and you have to add the case in the button switch.
case SystemMediaTransportControlsButton.Next:
//handle next song
break;

The SystemMediaTransportControls were initialized in a different mode error in mytoolkit

When i run mytoolkit after background audio player start is return "The SystemMediaTransportControls were initialized in a different mode. Please use the API associated with that mode to complete this operation" Exception.
var url = await MyToolkit.Multimedia.YouTube.GetVideoUriAsync(ID, MyToolkit.Multimedia.YouTubeQuality.Quality480P);
it works fine when background audio player not started. please help me i cant find where is the error, is there any solution for that...
In your code for background audio player use
var systemMediaControls = SystemMediaTransportControls.GetForCurrentView();
systemMediaControls.ButtonPressed += systemMediaControls_ButtonPressed;
systemMediaControls.IsPlayEnabled = true;
systemMediaControls.IsPauseEnabled = true;
systemMediaControls.IsNextEnabled = true;
systemMediaControls.IsPreviousEnabled = true;
async void systemMediaControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
break;
}
}
instead of
MediaControl.PlayPressed += MediaControl_PlayPressed;
MediaControl.PausePressed += MediaControl_PausePressed;
Control.
I think it will help for you..
Did you follow the directions as this guy did for windows 8 and not for 8.1?
"Do NOT use the MediaControl static class to attach handlers for you Windows 8.1 app or you will get the error message"

SystemMediaTransportControls Not Working

I'm having issues with the new SystemMediaTransportControls that replace MediaControl.
Currently, I have my app set up with:-
systemControls = SystemMediaTransportControls.GetForCurrentView();
systemControls.IsPlayEnabled = true;
systemControls.IsStopEnabled = true;
systemControls.IsPauseEnabled = true;
systemControls.ButtonPressed += SystemControls_ButtonPressed;
And
async void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
System.Diagnostics.Debug.WriteLine(args.Button);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
if (mediaElement1.CurrentState != MediaElementState.Playing)
{
restartSource();
}
else
{
completeClosure();
}
break;
case SystemMediaTransportControlsButton.Pause:
case SystemMediaTransportControlsButton.Stop:
completeClosure();
break;
default:
break;
}
});
}
And:
private async void completeClosure()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement1.Stop();
mediaElement1.Source = null;
timer.Stop();
});
}
private async void restartSource()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement1.Source = new Uri(holdThisSource, UriKind.Absolute);
mediaElement1.Play();
timer.Start();
});
}
When a user presses the Pause Button, args.Button shows up as "Play", hence the need for the checking for MediaElement's state. However, when I attempt to resume to media, it successfully resumes in restartSource() and updates the app accordingly but the icon on the Volume Control does not change from the Play sign, although hardware buttons still work.
Along with this, pressing the hardware Stop button NEVER works, and fails to even show up in Debug.WriteLine.
This is an online streaming app where the source does not allow resuming and thus I have to close the stream this way.
I'd love some help on this.
Since you did not update the systemControls.PlaybackStatus, the control button on transport control will not auto change to correct status.
You should always update the systemControls.PlaybackStatus property when the playback state has changed.
May this could solve your problems.

Categories