首页 > 解决方案 > 在运行时询问 WebView 的摄像头权限

问题描述

我想通过 Android WebView 在 PWA 中使用 QR 码扫描仪。

问题是似乎没有授予权限。此外,权限请求被重复多次。

安卓代码

显现

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature
            android:name="android.hardware.camera"
            android:required="true" />

根据上一个问题的答案,我在 WebViewHelper 类中有这段代码

lateinit var webkitPermissionRequest : PermissionRequest
...
webView.webChromeClient = object : WebChromeClient() {

    override fun onPermissionRequest(request: PermissionRequest) {
        webkitPermissionRequest = request
        val requestedResources = request.resources
        for (r in requestedResources) {
            if (r == PermissionRequest.RESOURCE_VIDEO_CAPTURE) {
                // In this sample, we only accept video capture request.
                val alertDialogBuilder = AlertDialog.Builder(activity)
                    .setTitle("Allow Permission to camera")
                    .setPositiveButton("Allow") { dialog, which ->
                        dialog.dismiss()
                        webkitPermissionRequest.grant(arrayOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE))
                        Log.d(TAG, "Granted")
                    }
                    .setNegativeButton("Deny") { dialog, which ->
                        dialog.dismiss()
                        webkitPermissionRequest.deny()
                        Log.d(TAG, "Denied")
                    }
                val alertDialog = alertDialogBuilder.create()
                alertDialog.show()
                break
            }
        }
    }
    ...
}

日志:授权后再次请求(多次)

D/WebViewHelper: Granted
V/InputMethodManager: Reporting focus gain, without startInput
I/PermissionManager: camera remind result:true
I/CameraManager: open camera: 1, package name: "myApp"
I/BackgroundPermManager: pkgName: "myApp", pid: 31365 ,uidOf3RdApk: 10197 ,permType: 0 ,permCfg: 1
I/HwCameraUtil: notifySurfaceFlingerCameraStatus : isFront = true , isOpend = true
I/HwCameraUtil: notifySurfaceFlingerFrontCameraStatus 8011 transact success!
E/cr_VideoCapture: CameraDevice.StateCallback onOpened
I/WebViewHelper: onPermissionRequest
    onPermissionRequest

这似乎是问题

I/GRALLOC: LockFlexLayout: baseFormat: 11, yStride: 640, ySize: 307200, uOffset: 307200,  uStride: 640
E/ion: ioctl c0044901 failed with code -1: Invalid argument
I/chromium: "Unhandled rejection", source: "PWA
            "Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture.", source: "PWA"

最后,这个错误重复(无限期)

I/GRALLOC: LockFlexLayout: baseFormat: 11, yStride: 640, ySize: 307200, uOffset: 307200,  uStride: 640

JavaScript 代码

JS 端的代码运行良好,直到在 WebView 中打开。

    app.ports.scanQR.subscribe(() => {
        // Delay until page loaded
        setTimeout(function(){
            const video = document.getElementById('media-video');
            function returnResult(result) {
                app.ports.onGotQR.send(result);
                scanner.destroy();
            }
        const scanner = new QrScanner(video, result => returnResult(result));
        scanner.start();
        }, 50);
    });
}

如果我直接调用 getUserMedia,问题仍然存在

if (navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia({ video: true })
    .then(function (stream) {
        video.srcObject = stream;
    })
    .catch(function (err0r) {
        console.log("Something went wrong!");
    });
}

获取相机的App权限:

在 WebviewHelper.kt

webView.webChromeClient = object : WebChromeClient() {
    override fun onPermissionRequest(request: PermissionRequest) {
        Log.i(TAG, "onPermissionRequest")

        // grants permission for app. video not showing
        if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED
        ) {
            Log.i(TAG, "Request Permission")
            requestPermissions(activity, arrayOf(Manifest.permission.CAMERA), 1010)
        } else {
            Log.i(TAG, "Permission already granted")
        }
    ...
}

在 MainActivity.kt

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        when (requestCode) {
            cameraRequestCode -> {
                Log.d("MainActivity", "onRequestPermissionsResult: Camera Request")
                if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                    Log.d("MainActivity", "Camera Request: Permission granted")
                    // permission was granted, yay!
                } else {
                    // permission denied, boo!
                    Log.d("MainActivity", "Camera Request: Permission denied")
                }
                return
            }
...

当授予相机的应用权限时,会按预期导致以下日志:

D/MainActivity: onRequestPermissionsResult: Camera Request
    Camera Request: Permission granted

标签: androidandroid-webviewandroid-permissions

解决方案


您的所有原始代码在onPermissionRequest(...). 您缺少的关键代码行是webView.settings.mediaPlaybackRequiresUserGesture = false.


推荐阅读