XamarinCommunityToolkit
XamarinCommunityToolkit copied to clipboard
[Bug] MediaElement AutoPlay even if property set to false on Android
Description
See attached project
Stack Trace
The are no stacktrace
Link to Reproduction Sample
https://github.com/JoacimWall/Joacim_Bug_Report.git
Steps to Reproduce
- Run the attached project target Android device
- Video autoplay when Autoplay set to false.
Expected Behavior
Actual Behavior
Basic Information
- Version with issue:
- Last known good version:
- IDE:Visual studio for Mac 8.10.13 (Build 11)
- Platform Target Frameworks:
- iOS:
- Android:Android 11.0
- UWP:
- Android Support Library Version:
- Nuget Packages:
- Affected Devices:
Workaround
Reproduction imagery
I had the same issue when using an online video source. AutoPlay
and IsLooping
are both set to false, but for some reason, as soon as the media loads, it decides to autoplay.
My workaround is extremely hacky - call this method from the MediaOpened
event:
private void VideoElement_MediaOpened(object sender, EventArgs e)
{
/// ...
Task.Run(() =>
{
videoContent.Stop();
videoContent.Play();
videoContent.Stop();
videoContent.Play();
videoContent.Pause();
videoContent.Play();
videoContent.Pause();
videoContent.Play();
videoContent.Pause();
});
}
And yes, Task.Run()
and the many redundant calls are necessary in my case (for unknown reasons). Hope this helps!
Same issue :(
Setting the Speed to 0 seems to workaround this.
And yes,
Task.Run()
and the many redundant calls are necessary in my case (for unknown reasons). Hope this helps!
For me, it worked without Task.Run()
and the many redundant calls, just like this:
private void OnMediaOpened(object sender, EventArgs e)
{
((MediaElement) sender).Stop();
}
Setting the Speed to 0 seems to workaround this.
Thanks for providing that work around, I'm a little surprised these features make their way into the main branch though, I think the features themselves need to be ironed abit further in the dev branch before merging.
@LeoJHarris sadly due to the limited time we each have things like this have crept in to the main
branch. This did lead to some issues in terms of quality of features plus their associated documentation, etc. As we are now migrating to the new .NET MAUI Community Toolkit the team have devised a solid plan for dealing with proposals/implementations before they can be merged.
That said we are still only a small number of maintainers so we really need help from the community to aid in all stages of the development of new features, etc.
Yes, setting the speed to 0 fixed it for me.
I found that setting the speed to 0 gave the illusion of working but it was still had "Playing" status in the background which caused issues with controls that worked of this state. I found a few issues like this and errors when scrolling in a collectionview.
This renderer seems to fix these issues. Naturally you will need to customise it for your mediaelement wrapper class if you use one. Mine is nfMediaElement which is what's used here. Its a bit of a hack but seems to work
Hope it helps someone
using Android.Content; using Android.Media; using NetFrame.Mobile.Xamarin.Controls.Core; using Xamarin.CommunityToolkit.UI.Views; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; using ToolKitMediaElement = Xamarin.CommunityToolkit.UI.Views.MediaElement;
[assembly: ExportRenderer(typeof(nfMediaElement), typeof(NetFrame.Mobile.Xamarin.Android.Renderers.nfMediaElementRenderer))] namespace NetFrame.Mobile.Xamarin.Android.Renderers {
public class nfMediaElementRenderer : MediaElementRenderer, MediaPlayer.IOnPreparedListener, MediaPlayer.IOnInfoListener
{
bool isDisposed;
VisualElementTracker tracker;
IMediaElementController? Controller => MediaElement;
public nfMediaElementRenderer(Context context) : base(context)
{
}
bool MediaPlayer.IOnInfoListener.OnInfo(MediaPlayer? mp, MediaInfo what, int extra)
{
if (view == null || mp == null || Controller == null)
return false;
switch (what)
{
case MediaInfo.BufferingStart:
Controller.CurrentState = MediaElementState.Buffering;
mp.BufferingUpdate += OnMpBufferingUpdate;
break;
case MediaInfo.BufferingEnd:
mp.BufferingUpdate -= OnMpBufferingUpdate;
Controller.CurrentState = MediaElementState.Paused;
break;
case MediaInfo.VideoRenderingStart:
view.SetBackground(null);
// Only set to playing if AutoPlay is on. This was leaving it in Palying status when the
// view was in a collection view and scrolling back and forward over it
if (MediaElement.AutoPlay)
{
Controller.CurrentState = MediaElementState.Playing;
}
break;
}
mediaPlayer = mp;
return true;
}
void OnMpBufferingUpdate(object? sender, MediaPlayer.BufferingUpdateEventArgs e)
{
if (Controller != null)
Controller.BufferingProgress = e.Percent / 100f;
}
protected override void Dispose(bool disposing)
{
if (isDisposed)
return;
isDisposed = true;
ReleaseControl();
if (disposing)
{
SetOnClickListener(null);
SetOnTouchListener(null);
tracker?.Dispose();
if (Element != null)
UnsubscribeFromEvents((ToolKitMediaElement)Element);
}
base.Dispose(disposing);
}
void MediaPlayer.IOnPreparedListener.OnPrepared(MediaPlayer? mp)
{
if (Controller == null || mp == null || MediaElement == null)
return;
Controller.OnMediaOpened();
UpdateLayoutParameters();
mediaPlayer = mp;
UpdateVolume();
UpdateSpeed();
mp.Looping = MediaElement.IsLooping;
mp.SeekTo(0);
if (MediaElement.AutoPlay)
{
mediaPlayer.Start();
Controller.CurrentState = MediaElementState.Playing;
}
else
{
// Call pause here. Not sure if it makes a difference but seemed needed
mediaPlayer.Pause();
Controller.CurrentState = MediaElementState.Paused;
}
}
protected override void ReleaseControl()
{
if (view != null)
{
// I was getting errors when i put this control in a collection view and they were being disposed on scrolling
// An issue of workig with objects already disposed so i put this in a try catch to ignore the error
try
{
view?.SetOnPreparedListener(null);
view?.SetOnCompletionListener(null);
RemoveView(view);
view?.Dispose();
}
catch { }
view = null;
}
if (controller != null)
{
controller?.Dispose();
controller = null;
}
if (mediaPlayer != null)
{
mediaPlayer?.Dispose();
mediaPlayer = null;
}
base.ReleaseControl();
}
}
}
I also used the workaround with the playback speed, however, this is not ideal. I think this should still be fixed. We just switched to MediaElement in an existing Xamarin.Forms app, because the other player is not maintained anymore. Since we're planning to eventually migrate to MAUI with that app, the MediaElement seemed convenient, because it was already ported to MAUI. Fortunately, the MAUI version of the MediaElement works quite well and doesn't seem to suffer from this issue.
I've created a repository showcasing some of the MediaElement bugs, including this one: https://github.com/ewerspej/MediaCustomTransport