Search code examples
javascriptwebviewblazormauiios-camera

Saving camera permission when accessing camera via Javascript and MAUI on iOS


I want to create an iOS app using MAUI and WebView. I have a website, which uses the camera. The program is running nicely, but the user needs to accept the camera permission everytime the Javascript code (getUserMedia) is being called. Does anybody already tried MAUI with WebView as an app on iOS? Is it even possible to create such an app without having the user accepting the camera permissions everytime the camera is being used? In the main settings of the iPhone, the app already has camera permissions granted.

I already added the necessery permission for the MAUI app in the Info.plist:

<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>

I also tried adding a custom WebViewDelegate, which seems is never being called:

#if IOS
    public class CustomWebViewDelegate : WKUIDelegate
    {
        [Export("webView:requestMediaCapturePermissionForOrigin:initiatedByFrame:type:decisionHandler:")]
        public override void RequestMediaCapturePermission(WKWebView webView, WKSecurityOrigin origin, WKFrameInfo frame, WKMediaCaptureType type, Action<WKPermissionDecision> decisionHandler)
        {
            decisionHandler(WKPermissionDecision.Grant);//Missing this line will result in a blank camera screen
            base.RequestMediaCapturePermission(webView, origin, frame, type, decisionHandler);
        }
    }
#endif

despite being added in the CreateMauiApp.

#if IOS
    Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping("PermissionRequest", (handler, view) =>
    {
        MainThread.BeginInvokeOnMainThread(() =>
        {
            handler.PlatformView.UIDelegate = new CustomWebViewDelegate();
        });
    });
#endif

Solution

  • The solution was to implement a custom WKUIDelegate as mentioned in the accepted answer from this post. But that didn't solve the problem at first. What really made the difference was to just grant all MediaCapturePermissions and not to use the base.RequestMediaCapturePermission call. So implementing the Delegate like this:

    public class WebViewDelegate : WKUIDelegate
    {
        public override void RequestMediaCapturePermission(
            WKWebView webView,
            WKSecurityOrigin origin,
            WKFrameInfo frame,
            WKMediaCaptureType type,
            Action<WKPermissionDecision> decisionHandler
        ) => decisionHandler(WKPermissionDecision.Grant);
    }
    

    And injecting this in the AppDelegate:

    WebViewHandler.Mapper.Add("WebChromeClient", (handler, view) =>
    {
        handler.PlatformView.UIDelegate = new WebViewDelegate();
    });
    

    Now just add the permissions in the Info.plist file and the webview has all the camera request it needs.