Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] MediaElement Android crashes when OnFullscreenButtonClick #2044

Open
2 tasks done
vikher opened this issue Jul 19, 2024 · 8 comments
Open
2 tasks done

[BUG] MediaElement Android crashes when OnFullscreenButtonClick #2044

vikher opened this issue Jul 19, 2024 · 8 comments
Labels
bug Something isn't working 📽️ MediaElement Issue/PR that has to do with MediaElement unverified waiting for feedback Waiting for a response from the author or the core team member

Comments

@vikher
Copy link

vikher commented Jul 19, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Did you read the "Reporting a bug" section on Contributing file?

Current Behavior

The Android app crashes when the fullscreen button is clicked.

Expected Behavior

The app should not crash when the fullscreen button is clicked.

Steps To Reproduce

Use MediaElement version 3.1.0.
Click the fullscreen button mainly on a Galaxy S23 Ultra, Galaxy S22 Ultra, or Pixel 8 Pro.

Link to public reproduction project repository

https://github.com/vikher/testmedia

Environment

- .NET MAUI CommunityToolkit Version 9.0.2
- OS: net8.0-android
- .NET MAUI: MauiVersion 8.0.70
- CommunityToolkit.Maui.MediaElement Version 3.1.0

Anything else?

  • Occurs mostly on Galaxy S23 Ultra, Galaxy S22 Ultra, and Pixel 8 Pro.
  • Reported by Visual Studio App Center.
  • I'm using MediaElement version 3.1.0 for Android because:
  1. Version 3.1.1 breaks fullscreen functionality.
  2. Versions 4.0+ causes the app to reopen on the last visited page and continue background audio, behavior that is not desired.
  3. Awaiting approval of CommunityToolkit/Maui PR #2039 to use the latest NuGet package.

Error Details:

Error: System.ObjectDisposedException
Message: ObjectDisposed_Generic ObjectDisposed_ObjectName_Name, CommunityToolkit.Maui.Core.Views.MauiMediaElement

Xamarin Exception Stack:
System.ObjectDisposedException: ObjectDisposed_Generic
ObjectDisposed_ObjectName_Name, CommunityToolkit.Maui.Core.Views.MauiMediaElement
  at Java.Interop.JniPeerMembers.AssertSelf(IJavaPeerable )
  at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod(String , IJavaPeerable , JniArgumentValue* )
  at Android.Views.ViewGroup.AddView(View )
  at CommunityToolkit.Maui.Core.Views.MauiMediaElement.OnFullscreenButtonClick(Object sender, FullscreenButtonClickEventArgs e)
  at Com.Google.Android.Exoplayer2.UI.StyledPlayerView.IFullscreenButtonClickListenerImplementor.OnFullscreenButtonClick(Boolean isFullScreen)
  at Com.Google.Android.Exoplayer2.UI.StyledPlayerView.IFullscreenButtonClickListenerInvoker.n_OnFullscreenButtonClick_Z(IntPtr jnienv, IntPtr native__this, Boolean isFullScreen)
  at Android.Runtime.DynamicMethodNameCounter.24(IntPtr , IntPtr , Boolean )

Code Context:

I'm using DisconnectMediaElementHandler method to dispose the media element, based on this discussion:

  public override void Stop()
  {
      base.Stop();
      DisconnectMediaElementHandler();
  }

private void DisconnectMediaElementHandler()
{
    mediaElement.Handler?.DisconnectHandler();
    mediaElement.Dispose();
}

The DisconnectMediaElementHandler method is executed when the page disappears, not when the fullscreen button is clicked, at least on Android.

I'm not using ContentPage_Unloaded because, on iOS, when the fullscreen button is clicked and it enters fullscreen mode, CnkContentPage_Unloaded gets called and disposes of the media element view.

        //DO NOT DO THIS IN IOS
        void ContentPage_Unloaded(System.Object sender, System.EventArgs e)
        {
            DisconnectMediaElementHandler();
        }

Additional Information:
There is no current way to trigger a specialized event in Maui when the fullscreen button is clicked.

The following screenshot from the app center
image

@vikher vikher added bug Something isn't working unverified labels Jul 19, 2024
@ne0rrmatrix
Copy link
Contributor

There is a PR that came out last night that will add support for full screen event handling. #2041

@jfversluis jfversluis added the 📽️ MediaElement Issue/PR that has to do with MediaElement label Jul 21, 2024
@ne0rrmatrix
Copy link
Contributor

I tested against current main repo for MediaElement and toolkit. Could not reproduce issue. Will keep this open till #2041 is merged.

@ne0rrmatrix
Copy link
Contributor

Can you try the latest version? 4.1.0 Came out last week.

@brminnick brminnick added stale The author has not responded in over 30 days waiting for feedback Waiting for a response from the author or the core team member labels Sep 8, 2024
@vikher
Copy link
Author

vikher commented Sep 24, 2024

After updating to MediaElement Version 4.1.0, I can confirm the error System.ObjectDisposedException: ObjectDisposed_Generic ObjectDisposed_ObjectName_Name in CommunityToolkit.Maui.Core.Views.MauiMediaElement

Java.Interop.JniPeerMembers.AssertSelf(IJavaPeerable )
Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod(String , IJavaPeerable , JniArgumentValue* )
Android.Views.ViewGroup.AddView(View )
CommunityToolkit.Maui.Core.Views.MauiMediaElement.OnFullscreenButtonClick(Object sender, FullscreenButtonClickEventArgs e)
Com.Google.Android.Exoplayer2.UI.StyledPlayerView.IFullscreenButtonClickListenerImplementor.OnFullscreenButtonClick(Boolean isFullScreen)
Com.Google.Android.Exoplayer2.UI.StyledPlayerView.IFullscreenButtonClickListenerInvoker.n_OnFullscreenButtonClick_Z(IntPtr jnienv, IntPtr native__this, Boolean isFullScreen)

has stopped occurring. However, I have encountered a new issue introduced in 4.1.0:

System.ArgumentNullException
System.ArgumentNullException: ArgumentNull_Generic Arg_ParamName_Name, intent
O
CommunityToolkit.Maui.Media.Services.MediaControlsService.OnStartCommand(Intent intent, StartCommandFlags flags, Int32 startId)
Android.App.Service.n_OnStartCommand_Landroid_content_Intent_II(IntPtr jnienv, IntPtr native__this, IntPtr native_intent, Int32 native_flags, Int32 startId)
Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLII_I(_JniMarshal_PPLII_I callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, Int32 p1, Int32 p2)

I noticed that your team closed issue #2163 with a similar stack trace. Therefore, I will reopen the bug and try to provide steps to reproduce the issue.
I’ve added a screenshot from App Center as evidence of this new bug. Let me know if you need any further details.

image

@dotnet-policy-service dotnet-policy-service bot removed the stale The author has not responded in over 30 days label Sep 24, 2024
@ne0rrmatrix
Copy link
Contributor

Can u test against this PR: #2076 and check and see if it fixes your issue. Based on what you have posted without testing it is the service crashing. That issue has been addressed in current PR listed above. That is waiting on review. If I can have you check that bug and verify it is fixed that would be helpful.

@brminnick
Copy link
Collaborator

brminnick commented Sep 24, 2024

System.ArgumentNullException
System.ArgumentNullException: ArgumentNull_Generic Arg_ParamName_Name, intent
O
CommunityToolkit.Maui.Media.Services.MediaControlsService.OnStartCommand(Intent intent, StartCommandFlags flags, Int32 startId)
Android.App.Service.n_OnStartCommand_Landroid_content_Intent_II(IntPtr jnienv, IntPtr native__this, IntPtr native_intent, Int32 native_flags, Int32 startId)
Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLII_I(_JniMarshal_PPLII_I callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, Int32 p1, Int32 p2)

@vikher Would you please open a new Bug Report Issue for this? We'll need you to provide us a reproduction sample to help us narrow down the problem and solve it.

Can u test against this PR: #2076 and check and see if it fixes your issue. Based on what you have posted without testing it is the service crashing. That issue has been addressed in current PR listed above. That is waiting on review. If I can have you check that bug and verify it is fixed that would be helpful.

@ne0rrmatrix PR #2076 does not solve it because it does not remove ArgumentNullException.ThrowIfNull(intent);.

The ArgumentNullException is thrown here when Android passes in an Intent that is null. I'm surprised that a null Intent is being passed in to OnStartCommand() when the app is running in the foreground; I assumed this would only happen on a BackgroundService.

Let's leverage @vikher's reproduction sample to help us understand when + why Android is passing in a null Intent OnStartCommand().

Here's what the Android docs say about OnStartCommand():

https://developer.android.com/develop/background-work/services

When a service is started, it has a lifecycle that's independent of the component that started it. The service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is complete by calling stopSelf(), or another component can stop it by calling stopService().

An application component such as an activity can start the service by calling startService() and passing an Intent that specifies the service and includes any data for the service to use. The service receives this Intent in the onStartCommand() method.

@ne0rrmatrix
Copy link
Contributor

ne0rrmatrix commented Sep 24, 2024

You get a null intent when you do not have permission to post notifications. It can be revoked or never authorized. This code addresses that issue.

async Task CheckAndRequestForegroundPermission(CancellationToken cancellationToken = default)
{
	var status = await Permissions.CheckStatusAsync<AndroidMediaPermissions>().WaitAsync(cancellationToken);
	if (status is PermissionStatus.Granted)
	{
		StartConnection();
		return;
	}

	status = await Permissions.RequestAsync<AndroidMediaPermissions>().WaitAsync(cancellationToken).ConfigureAwait(false);
	if (status is PermissionStatus.Granted) 
	{
		StartConnection();
	}
} 

That is the only place that service can be started now. It does get called in more than one place. But it will always check to see if it has authorization first now. So no null intent. Only way that could happen is if notification permission were revoked while it was playing video. I believe that would close the notification too.

@brminnick
Copy link
Collaborator

brminnick commented Sep 24, 2024

That is the only place that service can be started now. It does get called in more than one place. But it will always check to see if it has authorization first now. So no null intent. Only way that could happen is if notification permission were revoked while it was playing video. I believe that would close the notification too.

The key part we've overlooked is that the Android Operating System can start the Service. In other words, it's not just our code invoking this method.

An application component such as an activity can start the service by calling startService() and passing an Intent that specifies the service and includes any data for the service to use. The service receives this Intent in the onStartCommand() method.

Let's pause the discussion since it is unrelated to this Issue and continue the discussion once @vikher has opened a new Bug Report Issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working 📽️ MediaElement Issue/PR that has to do with MediaElement unverified waiting for feedback Waiting for a response from the author or the core team member
Projects
None yet
Development

No branches or pull requests

4 participants