Skip to content

libvlcsharp.Maui (Android) can occasionally crash when VideoView is removed from UI-tree/screen

Summary

libvlcSharp.Maui - Android can crash in some circumstances. The stack trace would seem to indicate that .Net has already cleaned things up, and Java is now calling Finalize() which eventually reaches .Net code and an already-disposed .net object (the Org.Videolan.Libvlc.AWindow instance contained by LibVLCSharp.Platforms.Android.VideoView?)

Minimal project and steps to reproduce

No repro project available, currently, but it is rare and occurs when a parent Page/View of LibVLCSharp.MAUI.VideoView is removed from the UI-tree or the screen. Example: rapid/numerous page navigations to/from a Maui Page that hosts a LibVLCSharp.MAUI.VideoView. The MediaPlayerElement was not involved in my testing.

What is the current bug behavior?

In rare occasions the app will crash.

What is the expected correct behavior?

VLC should stop playing and app not crash 😅.

Does it work on other plaforms? Does it work with the official VLC apps?

Yes, iOS works as expected, or at least I haven't observed any crashes in the same circumstances.

Relevant LibVLC logs and/or screenshots

Crash report:

Xamarin Exception Stack:
System.ObjectDisposedException: ObjectDisposed_Generic
ObjectDisposed_ObjectName_Name, Org.Videolan.Libvlc.AWindow
  at Java.Interop.JniPeerMembers.AssertSelf(IJavaPeerable self)
  at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod(String encodedMember, IJavaPeerable self, JniArgumentValue* parameters)
  at Org.Videolan.Libvlc.AWindow.RemoveCallback(ICallback callback)
  at LibVLCSharp.Platforms.Android.VideoView.Detach()
  at LibVLCSharp.Platforms.Android.VideoView.Dispose(Boolean disposing)
  at Java.Lang.Object.Java.Interop.IJavaPeerable.Finalized()
  at Android.Runtime.AndroidValueManager.FinalizePeer(IJavaPeerable value)
  at Java.Lang.Object.Finalize()

Environment

  • OS: Android
  • Version 13, Android Build: TP1A.221005.002.B2
  • Device: Pixel 4
  • LibVLC version and architecture 3.6.5
  • LibVLCSharp version 3.9.4 (LibVLCSharp.Maui same version)

Possible fixes

Suspect the LibVLCSharp.Platforms.Android.VideoView.Dispose impl is at fault?

/// <summary>
/// Detach the mediaplayer from the view and dispose the view
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
    base.Dispose(disposing);

    // perhaps wrapping in if (disposing == true) { } would avoid this crash?
    Detach();
}

From IJavaPeerable metatdata, disposing should be false in this case? I would assume this would be impl in SurfaceView or it's base-type? If not, then this is a Xamarin.Android issue? :

        //
        // Summary:
        //     Called when the instance has been finalized.
        //
        // Remarks:
        //     The Finalized method is invoked after the finalizer has been invoked on the instance.
        //     The Java.Interop.IJavaPeerable.PeerReference property is NOT valid when Finalized
        //     is invoked.
        //
        //     This method should only be invoked by the Java.Interop.JniRuntime instance which
        //     will be managing the IJavaPeerable value.
        //
        //     If the type is following the typical IDisposable pattern, then the Finalized
        //     method should delegate to the Dispose(bool) method. The proscribed implementation
        //     template is:
        //
        //     [JniTypeSignature ("my/Example")]
        //     partial class ExampleBinding : IJavaPeerable {
        //
        //     	~ExampleBinding ()
        //     	{
        //     JniEnvironment.Runtime.ValueManager.TryCollectObject (this);
        //     	}
        //
        //     	protected virtual void Dispose (bool disposing)
        //     	{
        //     	}
        //
        //     	void IJavaPeerable.Finalized ()
        //     	{
        //     	 Dispose (disposing: false);
        //     	}
        //     }
        void Finalized();
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information