Maui icon indicating copy to clipboard operation
Maui copied to clipboard

[BUG] SIGABRT on iOS when Permissions.Camera not Granted

Open nk-alex opened this issue 11 months ago • 5 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

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

  • [x] I have read the "Reporting a bug" section on Contributing file: https://github.com/CommunityToolkit/Maui/blob/main/CONTRIBUTING.md#reporting-a-bug

Current Behavior

The first thing I do when I navigate to a page containing CameraView is checking permissions for Camera. If I don't grant permission on iOS, the application keeps on crashing due to SIGABRT when navigating to this page.

Here I attach full output:

**CommunityToolkit.Maui.Core.CameraException:** 'No camera available on device'

2025-02-14 14:18:27.710420+0100 SampleCameraView[12160:68715] 
Unhandled Exception:
CommunityToolkit.Maui.Core.CameraException: No camera available on device
   at CommunityToolkit.Maui.Core.CameraManager.<PlatformStartCameraPreview>d__33.MoveNext()
   at CommunityToolkit.Maui.Core.CameraManager.<PlatformConnectCamera>d__34.MoveNext()
   at CommunityToolkit.Maui.Core.Handlers.CameraViewHandler.ConnectHandler(UIView platformView)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
   at Foundation.NSAsyncSynchronizationContextDispatcher.Apply() in /Users/builder/azdo/_work/2/s/xamarin-macios/src/Foundation/NSAction.cs:line 179
--- End of stack trace from previous location ---
   at ObjCRuntime.Runtime.ThrowException(IntPtr gchandle) in /Users/builder/azdo/_work/2/s/xamarin-macios/src/ObjCRuntime/Runtime.cs:line 2719
   at UIKit.UIApplication.UIApplicationMain(Int32 argc, String[] argv, IntPtr principalClassName, IntPtr delegateClassName) in /Users/builder/azdo/_work/2/s/xamarin-macios/src/
UIKit/UIApplication.cs:line 64
   at UIKit.UIApplication.Main(String[] args, Type principalClass, Type delegateClass) in /Users/builder/azdo/_work/2/s/xamarin-macios/src/UIKit/UIApplication.cs:line 96
   at SampleCameraView.Program.Main(String[] args) in C:\Users
k-alex\Documents\ProjectsPersonal\CameraView\SampleCameraView\SampleCameraView\Platforms\iOS\Program.cs:line 13
2025-02-14 14:18:27.712810+0100 SampleCameraView[12160:68715] Unhandled managed exception: No camera available on device (CommunityToolkit.Maui.Core.CameraException)
   at CommunityToolkit.Maui.Core.CameraManager.<PlatformStartCameraPreview>d__33.MoveNext()
   at CommunityToolkit.Maui.Core.CameraManager.<PlatformConnectCamera>d__34.MoveNext()
   at CommunityToolkit.Maui.Core.Handlers.CameraViewHandler.ConnectHandler(UIView platformView)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state)
   at Foundation.NSAsyncSynchronizationContextDispatcher.Apply() in /Users/builder/azdo/_work/2/s/xamarin-macios/src/Foundation/NSAction.cs:line 179
--- End of stack trace from previous location ---
   at ObjCRuntime.Runtime.ThrowException(IntPtr gchandle) in /Users/builder/azdo/_work/2/s/xamarin-macios/src/ObjCRuntime/Runtime.cs:line 2719
   at UIKit.UIApplication.UIApplicationMain(Int32 argc, String[] argv, IntPtr principalClassName, IntPtr delegateClassName) in /Users/builder/azdo/_work/2/s/xamarin-mac
ios/src/UIKit/UIApplication.cs:line 64
   at UIKit.UIApplication.Main(String[] args, Type principalClass, Type delegateClass) in /Users/builder/azdo/_work/2/s/xamarin-macios/src/UIKit/UIApplication.cs:line 96
   at SampleCameraView.Program.Main(String[] args) in C:\Users
k-alex\Documents\ProjectsPersonal\CameraView\SampleCameraView\SampleCameraView\Platforms\iOS\Program.cs:line 13

=================================================================
	Native Crash Reporting
=================================================================
Got a SIGABRT while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

=================================================================
	Native stacktrace:
=================================================================
	0x1031f82e4 - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/libmonosgen-2.0.dylib : mono_dump_native_crash_info
	0x1031a9588 - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/libmonosgen-2.0.dylib : mono_handle_native_crash
	0x10336a944 - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/libmonosgen-2.0.dylib : sigabrt_signal_handler.cold.1
	0x1031f7b10 - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/libmonosgen-2.0.dylib : mono_runtime_setup_stat_profiler
	0x102017760 - /usr/lib/system/libsystem_platform.dylib : _sigtramp
	0x1021c3408 - /usr/lib/system/libsystem_pthread.dylib : pthread_kill
	0x1801704ec - /Library/Developer/CoreSimulator/Volumes/iOS_22C150/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.2.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/libsystem_c.dylib : abort
	0x1025928d4 - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/libxamarin-dotnet-debug.dylib : xamarin_find_protocol_wrapper_type
	0x10327b5d0 - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/libmonosgen-2.0.dylib : mono_invoke_unhandled_exception_hook
	0x10316cb4c - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/libmonosgen-2.0.dylib : mono_jit_exec
	0x1025a7984 - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/libxamarin-dotnet-debug.dylib : xamarin_main
	0x101786474 - /Users/nk/Library/Developer/CoreSimulator/Devices/30DB2FD0-E4AC-4B84-85B2-7483382D53E4/data/Containers/Bundle/Application/40DCB2B4-F309-4E5A-863C-EFD400300220/SampleCameraView.app/SampleCameraView : main
	0x10233d410 - Unknown
	0x10207e274 - Unknown

=================================================================
	Basic Fault Address Reporting
=================================================================
Memory around native instruction pointer (0x1024dd008):0x1024dcff8  c0 03 5f d6 c0 03 5f d6 10 29 80 d2 01 10 00 d4  .._..._..)......
0x1024dd008  e3 00 00 54 fd 7b bf a9 fd 03 00 91 ee e2 ff 97  ...T.{..........
0x1024dd018  bf 03 00 91 fd 7b c1 a8 c0 03 5f d6 c0 03 5f d6  .....{
...._..._.
0x1024dd028  70 0a 80 d2 01 10 00 d4 e3 00 00 54 fd 7b bf a9  p..........T.{..

=================================================================
	Managed Stacktrace:
=================================================================
=================================================================
INFO: Closing debug session after launching on simulator...
The app has been terminated.

Expected Behavior

To be able to handle this exception and avoid application from crashing

Steps To Reproduce

  1. Create a simple page with CameraView on it.
  2. On the related ViewModel, ask for Camera permissions.
  3. If you accept permissions, everything works as expected.
  4. If you DON'T accept permissions, application will crash showing SIGABRT

Link to public reproduction project repository

https://github.com/nk-alex/CameraView/tree/main

Environment

- .NET MAUI CommunityToolkit.Maui: 9.0.2
- .NET MAUI CommunityToolkit.Maui.Camera: 1.0.5
- OS:
- .NET MAUI: 8.0.71

Anything else?

Due to several dependencies I'm not going to be able to update my project to .NET 9 by now. So I'm looking for a possible workaround for .NET 8

nk-alex avatar Feb 14 '25 13:02 nk-alex

I check device permission beforehand to avoid the crash on iOS. This doesn't work on Windows for me because Windows returns granted for all Permissions. Therefore I'm unable to detect a denied permission on Windows.

The docs give this example to check and request permission: https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/appmodel/permissions?view=net-maui-9.0&tabs=windows

public async Task<PermissionStatus> CheckAndRequestLocationPermission()
{
    PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();

    if (status == PermissionStatus.Granted)
        return status;

    if (status == PermissionStatus.Denied && DeviceInfo.Platform == DevicePlatform.iOS)
    {
        // Prompt the user to turn on in settings
        // On iOS once a permission has been denied it may not be requested again from the application
        return status;
    }

    if (Permissions.ShouldShowRationale<Permissions.LocationWhenInUse>())
    {
        // Prompt the user with additional information as to why the permission is needed
    }

    status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();

    return status;
}

You can adjust the function to take a Permission generic so it can be reused for all Permissions if you'd like.

itsazoo avatar Mar 13 '25 14:03 itsazoo

CameraViewHandler.ConnectHandler doesn't actually check the result of the permission request:

https://github.com/CommunityToolkit/Maui/blob/e6c7c4d75682a95e68d00ca47ff64290fd75743a/src/CommunityToolkit.Maui.Camera/Handlers/CameraViewHandler.shared.cs#L87-L97

https://github.com/CommunityToolkit/Maui/blob/e6c7c4d75682a95e68d00ca47ff64290fd75743a/src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs#L26-L33

I think a fix becomes a question of: "How should the control behave when camera authorization is not granted"?

  • Is it possible to bubble-up a PermissionException and let consumers respond?
  • Should it display some sort of default "error" view? Something like CollectionView's EmptyView
  • etc...

phunkeler avatar Mar 29 '25 21:03 phunkeler

I think the first solution seems most appropriate for this issue: bubble-up a PermissionException and let consumers respond.

PR created: https://github.com/CommunityToolkit/Maui/pull/2634

zhitaop avatar Apr 17 '25 11:04 zhitaop

I think the first solution seems most appropriate for this issue: bubble-up a PermissionException and let consumers respond.

PR created: #2634

I tend to agree, but don't know if handlers are the best place to be throwing exceptions. Wouldn't that require consumers to derive from CameraViewHandler?

MyCameraViewHandler.cs
public class MyCameraViewHandler: CameraViewHandler
{
    protected override async void ConnectHandler(NativePlatformCameraPreviewView platformView)
    {
        try
        {
            base.ConnectHandler(platformView);
        }
        catch (PermissionException ex)
        {
            // Handle
        }
    }
}

Handling the exception internally and providing notification via an event or "error" property might make consumption a bit easier.

What do you think about leveraging the existing OnMediaCaptureFailed in this case?

phunkeler avatar Apr 17 '25 15:04 phunkeler

@phunkeler I agree that throwing exceptions in the handlers isn't ideal for consumers to handle. However, I feel that the OnMediaCaptureFailed event doesn't seem appropriate for this use case either, as its name implies it should only be triggered when a media capture operation fails. It might make more sense to introduce a new event specifically for this kind of scenario?

zhitaop avatar Apr 25 '25 12:04 zhitaop