android - 在运行时询问 WebView 的摄像头权限
问题描述
我想通过 Android WebView 在 PWA 中使用 QR 码扫描仪。
- PWA 在 chrome 浏览器上按预期工作。
- 我确实有权在应用程序 -> 应用程序名称 -> 权限下设置相机
minSdkVersion 26
和targetSdkVersion 28
- 在搭载 Android 9 的华为手机上测试
问题是似乎没有授予权限。此外,权限请求被重复多次。
安卓代码
显现
<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
解决方案
您的所有原始代码在onPermissionRequest(...)
. 您缺少的关键代码行是webView.settings.mediaPlaybackRequiresUserGesture = false
.
推荐阅读
- sql - Oracle 12c:我可以从 WITH 子句中调用一个函数,该函数既接受又返回一个表?
- javascript - 使用 tabletop.js 的传单地图中的标记为什么它不起作用?
- javascript - 在 rails 中使用 Vue 组件(带有 video.js)的问题
- swift - 创建一个Publisher,一一通知订阅者,相互等待
- android - Gradle 在 Windows 10 上的 Android Studio 3.5 中去了哪里?
- c# - reCAPTCHA V3 ASP.NET 框架实现
- node.js - 动态匹配变量MongoDB
- autodesk-forge - 是否有 API 来获取项目用户的服务访问权限?
- python-3.x - notimplementederror: can't perform this operation for unregistered loader type python : trying to convert py to .exe using cx_freeze
- javascript - 当有多个具有相同类名和属性名的元素时,获取一个元素的特定文本值