Android webview加载页面获取摄像头(h5页面中含有扫描二维码功能)

作者 : admin 本文共4353个字,预计阅读时间需要11分钟 发布时间: 2024-06-16 共1人阅读

场景介绍:
Android app中的webview加载含摄像头相关逻辑的H5页面,进行赋权的操作

H5页面调取摄像头识别二维码逻辑:
vue编写

<template>
<div class="getQrcode" :style="{ width: windowWidth + 'px', height: windowHeight + 'px' }">
<div class="box">
<div class="line"></div>
<div class="angle"></div>
</div>
<div class="box2" v-if="isUseTorch">
<div class="track" @click="openTrack">
{{ trackStatus ? '关闭闪光灯' : '打开闪光灯' }}
</div>
</div>
<canvas ref="canvasRef"></canvas>
</div>
</template>
<script setup lang="ts">
import { nextTick, ref } from 'vue'
import jsQr from 'jsqr'
const emit = defineEmits(['success'])
interface IProps {
/** 使用后置还是前置摄像头 */
exact?: 'environment' | 'user'
/** 获取摄像头视频像素 false 正常, true高清 */
definition?: boolean
/** 是否持续监听 */
continue?: boolean
}
const props = withDefaults(defineProps<IProps>(), {
exact: 'environment',
definition: false,
continue: false
})
if (origin.indexOf('https') === -1) throw '请在 https 环境中调用摄像头。'
const canvasRef = ref<HTMLCanvasElement>()
const windowWidth = document.documentElement.clientWidth || document.body.clientWidth
const windowHeight = document.documentElement.clientHeight || document.body.clientHeight
let video: HTMLVideoElement,
canvas2d: CanvasRenderingContext2D,
stream: MediaStream,
track: MediaStreamTrack,
isUseTorch = ref(false)
const trackStatus = ref(false)
nextTick(() => {
video = document.createElement('video')
video.setAttribute('playsinline', 'true')
video.setAttribute('webkit-playsinline', 'true')
video.width = windowWidth
video.height = windowHeight
canvasRef.value!.width = windowWidth
canvasRef.value!.height = windowHeight
canvas2d = canvasRef.value!.getContext('2d')!
openScan()
})
async function openScan() {
const width = transtion(windowHeight)
const height = transtion(windowWidth)
const videoParam = {
audio: false,
video: {
facingMode: { exact: props.exact },
width,
height
}
}
try {
stream = await navigator.mediaDevices.getUserMedia(videoParam)
video.srcObject = stream
video.play()
tick()
track = stream.getVideoTracks()[0]
setTimeout(() => {
const t: any = track.getCapabilities()
isUseTorch.value = t.torch || null
}, 500)
} catch (error) {
console.log('设备不支持,请检查是否允许摄像头权限', error)
throw error
}
}
function tick() {
if (video.readyState === video.HAVE_ENOUGH_DATA) {
canvas2d.drawImage(video, 0, 0, windowWidth, windowHeight)
const imageData = canvas2d.getImageData(0, 0, windowWidth, windowHeight)
const codeRes = jsQr(imageData.data, imageData.width, imageData.height, {
inversionAttempts: 'dontInvert'
})
if (codeRes) {
drawLine(codeRes.location.topLeftCorner, codeRes.location.topRightCorner, '#FF3B58')
drawLine(codeRes.location.topRightCorner, codeRes.location.bottomRightCorner, '#FF3B58')
drawLine(codeRes.location.bottomRightCorner, codeRes.location.bottomLeftCorner, '#FF3B58')
drawLine(codeRes.location.bottomLeftCorner, codeRes.location.topLeftCorner, '#FF3B58')
if (codeRes.data) {
getData(codeRes.data)
}
}
}
requestAnimationFrame(tick)
}
interface Point {
x: number
y: number
}
function drawLine(begin: Point, end: Point, color: string) {
canvas2d.beginPath()
canvas2d.moveTo(begin.x, begin.y)
canvas2d.lineTo(end.x, end.y)
canvas2d.lineWidth = 4
canvas2d.strokeStyle = color
canvas2d.stroke()
}
function getData(data: string) {
emit('success', data)
if (!props.continue) return closeCamera()
}
function closeCamera() {
if (stream) {
stream.getTracks().forEach((track) => {
track.stop()
})
}
}
function transtion(number: number) {
return props.definition ? number * 1.6 : number
}
const openTrack = () => {
trackStatus.value = !trackStatus.value
const ww: any = {
advanced: [{ torch: trackStatus.value }]
}
track.applyConstraints(ww)
}
</script>

问题:在app端访问时,扫描摄像头直接出不来显示无权限。

Android部分
一:AndroidManifest.xml部分
新增相关权限

    <uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.webkit.PermissionRequest" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

一:webview部分

1,首先在webview 的 initview 方法中添加如下方法

XXPermissions.with(this)
.permission(Permission.READ_EXTERNAL_STORAGE,
Permission.WRITE_EXTERNAL_STORAGE, Permission.CAMERA)
.request(new PermissionCallback() {
@Override
public void onGranted(List<String> permissions, boolean all) {
}
@Override
public void onDenied(List<String> permissions, boolean never) {
super.onDenied(permissions, never);
}
});

2,需要在 BrowserChromeClient 方法中添加如下方法

   @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onPermissionRequest(android.webkit.PermissionRequest request) {
System.out.println("onPermissionRequest");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
request.grant(request.getResources());
}
}
本站无任何商业行为
个人在线分享 » Android webview加载页面获取摄像头(h5页面中含有扫描二维码功能)
E-->