Xamarin - 在 WebView 中请求相机权限

Posted

技术标签:

【中文标题】Xamarin - 在 WebView 中请求相机权限【英文标题】:Xamarin - Requesting camera permissions in WebView 【发布时间】:2020-05-03 09:49:09 【问题描述】:

我想为我的 Web 应用程序创建一个容器应用程序,我决定在 Xamarin 中这样做,因为该项目的其余部分也是 .NET。

最初我从 Xamarin 示例页面下载并设置项目: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/webview?tabs=windows

我只是更改了 WebPage.cs 中的一些变量:https://github.com/xamarin/xamarin-forms-samples/blob/master/WorkingWithWebview/WorkingWithWebview/WebPage.cs

using Xamarin.Forms;

namespace WorkingWithWebview

    public class WebPage : ContentPage
    
        public WebPage()
        
            var browser = new WebView();
            browser.Source = "https://xamarin.swappsdev.net";
            Content = browser;
        
    

其次,我更新了 App.cs 以满足我的需要:https://github.com/xamarin/xamarin-forms-samples/blob/master/WorkingWithWebview/WorkingWithWebview/App。

using Xamarin.Forms;

namespace WorkingWithWebview

    public class App : Application
    
        public App ()
        
            MainPage = new WebPage();
        
    

然后繁荣!我有一个应用程序。

然后是真正的斗争。在 Web 应用程序中,当我在浏览器中打开网站 (https://xamarin.swappsdev.net) 时,我可以单击向设备请求权限的按钮,然后在同一窗口中显示摄像头源。

在应用程序中执行相同操作时,没有任何反应。

然后我开始在谷歌上搜索答案,但实际上并没有找到很多答案。我找到的答案似乎是旧版本的 Xamarin (?),因为我无法将答案中的文件和结构与 Xamarin 示例页面中的文件和结构进行比较。 https://***.com/a/50560855

我尝试在这里实现 Robbit 的答案。经过长时间的努力,我设法编译它并将其安装在我的设备上,但它实际上并没有请求权限。

我不知所措,可能需要一些帮助/指导。

【问题讨论】:

希望对您有所帮助,github.com/jamesmontemagno/PermissionsPlugin 【参考方案1】:

更新:

在我之前的回答中,它展示了如何在 webview 上添加摄像头权限。

您提供的链接,现在可以使用。 https://xamarin.swappsdev.net/好像提供了相机预览功能。它需要检查 API 23+ 的权限。

在 Xamarin.Forms 上,您可以使用权限插件。 https://github.com/jamesmontemagno/PermissionsPlugin

首先,在 android Manifest 中添加摄像头权限。 您的 Project.Android> 属性> Android 清单> 所需权限> 相机。之后,它会在 AndroidManifest.xml 中生成用户权限。

  <uses-permission android:name="android.permission.CAMERA" />

创建一个 Utils.cs。

public static class Utils

    public static async Task<PermissionStatus> CheckPermissions(Permission permission)
    
        var permissionStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(permission);
        bool request = false;
        if (permissionStatus == PermissionStatus.Denied)
        
            if (Device.RuntimePlatform == Device.ios)
            

                var title = $"permission Permission";
                var question = $"To use this plugin the permission permission is required. Please go into Settings and turn on permission for the app.";
                var positive = "Settings";
                var negative = "Maybe Later";
                var task = Application.Current?.MainPage?.DisplayAlert(title, question, positive, negative);
                if (task == null)
                    return permissionStatus;

                var result = await task;
                if (result)
                
                    CrossPermissions.Current.OpenAppSettings();
                

                return permissionStatus;
            

            request = true;

        

        if (request || permissionStatus != PermissionStatus.Granted)
        
            var newStatus = await CrossPermissions.Current.RequestPermissionsAsync(permission);

            if (!newStatus.ContainsKey(permission))
            
                return permissionStatus;
            

            permissionStatus = newStatus[permission];

            if (newStatus[permission] != PermissionStatus.Granted)
            
                permissionStatus = newStatus[permission];
                var title = $"permission Permission";
                var question = $"To use the plugin the permission permission is required.";
                var positive = "Settings";
                var negative = "Maybe Later";
                var task = Application.Current?.MainPage?.DisplayAlert(title, question, positive, negative);
                if (task == null)
                    return permissionStatus;

                var result = await task;
                if (result)
                
                    CrossPermissions.Current.OpenAppSettings();
                
                return permissionStatus;
            
        

        return permissionStatus;
    

在 MainActivity.cs 中,添加 OnCreate 方法中的代码。

 Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this, savedInstanceState);

MainActivity.cs 中需要 OnRequestPermissionsResult。

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, 
[GeneratedEnum] Android.Content.PM.Permission[] grantResults)

    PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

然后实现它。

private async void _button_Clicked(object sender, EventArgs e)
    
        webView.Source = "https://xamarin.swappsdev.net/";//"https://test.webrtc.org/";

        var status = PermissionStatus.Unknown;

        status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera);

        if (status != PermissionStatus.Granted)
        

            status = await Utils.CheckPermissions(Permission.Camera);
        

    

我已在我的 GitHub 上上传。检查文件夹。测试/CameraRuntimePermission_WebView/RuntimePermission

https://github.com/WendyZang/Test.git

编辑:

如果你不想在按钮点击事件中调用它,你可以删除 MainPage.xaml 中的按钮。

MainPage.xaml.cs

 public MainPage()
    
        InitializeComponent();
        webView.Source = "https://xamarin.swappsdev.net/";
    

    protected override void OnAppearing()
    
        base.OnAppearing();
        RunTimePermission();
    

    public async void RunTimePermission()
    
        var status = PermissionStatus.Unknown;

        status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera);

        if (status != PermissionStatus.Granted)
        

            status = await Utils.CheckPermissions(Permission.Camera);
        

    

【讨论】:

温迪,这太棒了!太感谢了。最后一件事,是否需要单击按钮,或者是否可以在启动应用程序时触发权限请求或有某种启动画面? 不可以,没有按钮也可以加载,但是需要在页面加载后询问运行时权限。我在编辑中提供了代码。 我并不自豪承认这一点,但我错过了您将 webView.Source = "https://xamarin.swappsdev.net/"; 移动到构造函数中的部分。我花了一段时间才弄清楚为什么我只是在看一个白屏,但除此之外它就可以工作。非常感谢您的帮助和时间!!【参考方案2】:

我尝试在这里实现 Robbit 的答案。经过长时间的努力,我设法编译它并将其安装在我的设备上,但它实际上并没有请求权限。

我尝试了 Robbit 从链接中提供的代码。Camera on Xamarin WebView

实际上,它运作良好。为了更好地理解,您可以使用下面的链接进行检查。 https://test.webrtc.org/

如果我使用 webview 直接加载 url,它会抛出如下错误。

如果我使用 Robbit 的自定义渲染器,它会请求 MyWebViewRenderer 中代码的许可。

public override void OnPermissionRequest(PermissionRequest request)
        
            mContext.RunOnUiThread(() =>
            
                request.Grant(request.GetResources());

            );

        

我也检查了你使用的链接,没有发生任何事情。该链接无法在 Android 设备中打开相机。

使用 Robbit 的代码。

在您的项目中创建 MyWebView。

public class MyWebView : WebView



在项目的 Android 部分中创建 MyWebViewRenderer.cs。

[assembly: ExportRenderer(typeof(MyWebView), typeof(MyWebViewRenderer))]
namespace WebViewDemo.Droid

public class MyWebViewRenderer : WebViewRenderer

    Activity mContext;
    public MyWebViewRenderer(Context context) : base(context)
    
        this.mContext = context as Activity;
    
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
    
        base.OnElementChanged(e);
        Control.Settings.javascriptEnabled = true;
        Control.ClearCache(true);
        Control.SetWebChromeClient(new MyWebClient(mContext));
    
    public class MyWebClient : WebChromeClient
    
        Activity mContext;
        public MyWebClient(Activity context)
        
            this.mContext = context;
        
        [TargetApi(Value = 21)]
        public override void OnPermissionRequest(PermissionRequest request)
        
            mContext.RunOnUiThread(() =>
            
                request.Grant(request.GetResources());

            );

        
    
    

用法:

MainPage.xaml

 <StackLayout>
    <Button x:Name="_button" Clicked="_button_Clicked" />
    <local:MyWebView
        x:Name="webView"
        HeightRequest="500"
        WidthRequest="500" />
</StackLayout>

MainPage.xaml.cs

private void _button_Clicked(object sender, EventArgs e)
    
        webView.Source = "https://test.webrtc.org/";//"https://xamarin.swappsdev.net/";
    

您可以从 GitHub 文件夹 CameraRuntimePermission_WebView 下载整个项目。 Page1 用于测试与 webview 的链接。 MainPage 用于使用自定义渲染器进行测试。 https://github.com/WendyZang/Test.git

【讨论】:

您好,Wendy,非常感谢您非常详细的回复。但是,我仍然遇到同样的旧权限问题。我在您的“CameraRuntimePermission_WebView”项目中加载并尝试在不进行任何修改的情况下运行它。它编译得很好,并向我显示了您在 gif 中显示的空白按钮,但它也告诉我它无法访问 webrtc-test 中所需的硬件。之后我尝试使用自己的链接:这是我在自己的链接上运行它时的日志。 pastebin.com/3c9nKsTd 这是我通常会面朝前撞墙的地方。它从不请求权限。 我已经修复了错误,我需要一些时间来编辑我的回复。请稍等。 感谢您抽出宝贵的时间撰写此答案。非常感谢!!它按预期工作..【参考方案3】:

按照几个指南启用WebView的摄像头,我终于成功了。

我按照上述所有步骤操作,尽管收到允许使用相机的提示,但我始终无法摆脱权限错误(即使调试显示权限已被授予)。然后我将 MyWebViewRenderer 代码(Wendy 上面给出的)替换为以下代码(如 https://forums.xamarin.com/discussion/183988/how-to-give-camera-and-microphone-permission-to-webview-with-xamarin-forms-on-android 给出的):

[assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace App19F_8.Droid

    public class CustomWebViewRenderer : WebViewRenderer
    
        public CustomWebViewRenderer(Context context) : base(context)
        
        
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        
            base.OnElementChanged(e);

            if (e.NewElement != null)
            
                Control.SetWebChromeClient(new MyWebChromeClient(MainActivity.Instance));
                Control.Settings.JavaScriptEnabled = true;
            
        
    

    public class MyWebChromeClient : WebChromeClient
    
        Activity mActivity = null;
        public MyWebChromeClient(Activity activity)
        
            mActivity = activity;
        
        public override void OnPermissionRequest(PermissionRequest request)
        
            mActivity.RunOnUiThread(() => 
                request.Grant(request.GetResources());
            );
        
    

如果上面的链接失效,我应该提一下,在 Android 的 MainActivity 中你应该插入以下内容:

 public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    
        public static MainActivity Instance  get; private set; 
        protected override void OnCreate(Bundle savedInstanceState)
        
            ...
            base.OnCreate(savedInstanceState);

            Instance = this;
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
        

现在摄像头终于开始工作了 :-) 我不确定之前代码中的罪魁祸首是什么。非常感谢 Wendy、Yelinzh 和所有人的彻底回复。

【讨论】:

感谢您的意见!您永远不知道此信息何时变得相关,因此感谢您抽出宝贵时间来编译此答案。 它按预期工作。感谢您抽出宝贵的时间来写这个答案。能否请您告诉我 ios 是否需要任何类似的程序? @Thameem - 很抱歉回复很晚 - 不幸的是,我还没有在 iOS 上测试过这个 - 只有 Android。希望你来对了... 有效!!值得一提的是,它需要创建一个 CustomWebView 并像这里提到的那样使用它:docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/…

以上是关于Xamarin - 在 WebView 中请求相机权限的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin WebView 上的相机

Xamarin.Forms WebView 不适用于 WebRTC

Xamarin Zxing 手机摄像头权限

Xamarin.Forms webview 进行身份验证,导航到新页面(Shell)并需要再次重新验证?

在 WebView 问题中查看 PDF (Xamarin.ios)

在 Xamarin UWP 中打印具有多个页面的 WebView