hjam40 / Camera.MAUI

A CameraView Control for preview, take photos and control the camera options
MIT License
449 stars 72 forks source link

Java.Lang.IllegalStateException: 'CameraDevice was already closed' on Android #86

Open usausa opened 1 year ago

usausa commented 1 year ago

In the Android environment, Quickly and repeatedly calling StartCameraAsync()/StopCameraAsync() while adding/removing a CameraView to the parent will result in a Java.Lang.IllegalStateException: 'CameraDevice was already closed' exception.

    0xFFFFFFFFFFFFFFFF in Android.Runtime.JNIEnv.monodroid_debugger_unhandled_exception C#
    0x1A in Android.Runtime.JNINativeWrapper._unhandled_exception at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:12,5 C#
    0x1E in Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:122,26  C#
    0x17 in System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw    C#
    0x69 in Java.Interop.JniEnvironment.InstanceMethods.CallObjectMethod at /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:11524,5    C#
    0x26 in Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeAbstractObjectMethod at /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:848,6   C#
    0x29 in Android.Hardware.Camera2.CameraDeviceInvoker.CreateCaptureRequest at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net7.0/android-33/mcw/Android.Hardware.Camera2.CameraDevice.cs:756,5   C#
    0x14B in Camera.MAUI.Platforms.Android.MauiCameraView.StartPreview  C#
    0x15 in Camera.MAUI.Platforms.Android.MauiCameraView.MyCameraStateCallback.OnOpened C#
    0x11 in Android.Hardware.Camera2.CameraDevice.StateCallback.n_OnOpened_Landroid_hardware_camera2_CameraDevice_ at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net7.0/android-33/mcw/Android.Hardware.Camera2.CameraDevice.cs:161,5  C#
    0x9 in Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPL_V at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:121,5    C#
usausa commented 1 year ago

For example, could this problem be avoided by using TaskCompletionSource to prevent StartCameraAsync() from exiting until CameraDevice.StateCallback.OnOpened() is called?

    internal async Task<CameraResult> StartRecordingAsync(string file, Microsoft.Maui.Graphics.Size Resolution)
    {
...
                        if (OperatingSystem.IsAndroidVersionAtLeast(28))
                            cameraManager.OpenCamera(cameraView.Camera.DeviceId, executorService, stateListener);
                        else
                            cameraManager.OpenCamera(cameraView.Camera.DeviceId, stateListener, null);
                        started = true;

                        // await CameraDevice.StateCallback.OnOpened()
                        await stateListener.Completion.Task;
...
    private class MyCameraStateCallback : CameraDevice.StateCallback
    {
        public TaskCompletionSource<bool> Completion { get; } = new();

        private readonly MauiCameraView cameraView;
        public MyCameraStateCallback(MauiCameraView camView)
        {
            cameraView = camView;
        }

        public override void OnOpened(CameraDevice camera)
        {
            if (camera != null)
            {
                cameraView.cameraDevice = camera;
                cameraView.StartPreview();
            }

            // Open completed
            Completion.TrySetResult(true);
        }
...

It is also desirable to have status checks and exception handling in StartPreview().

jimpmatehw commented 1 year ago

Have you got any solution? I am also faciing same issue.

programatix commented 9 months ago

You can try my pull (https://github.com/hjam40/Camera.MAUI/pull/107). It should have resolved almost all the crashes.