XamarinCommunityToolkit icon indicating copy to clipboard operation
XamarinCommunityToolkit copied to clipboard

[Bug] MediaElement AutoPlay even if property set to false on Android

Open JoacimWall opened this issue 2 years ago • 9 comments

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

  1. Run the attached project target Android device
  2. 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

JoacimWall avatar Nov 11 '21 07:11 JoacimWall

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!

Tornadocraver avatar Jan 07 '22 20:01 Tornadocraver

Same issue :(

mhrastegari avatar Feb 02 '22 19:02 mhrastegari

Setting the Speed to 0 seems to workaround this.

jgold6 avatar Feb 05 '22 00:02 jgold6

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

xmak avatar Mar 29 '22 20:03 xmak

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 avatar Apr 18 '22 21:04 LeoJHarris

@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.

bijington avatar Apr 19 '22 08:04 bijington

Yes, setting the speed to 0 fixed it for me.

FingerMoonSoftware avatar Oct 31 '22 12:10 FingerMoonSoftware

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

}

burrowj avatar Feb 06 '23 21:02 burrowj

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

ewerspej avatar Mar 29 '23 10:03 ewerspej