You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置React WebApp仅在首次进入相机页面时请求相机权限?

解决方案:仅首次进入相机页面请求权限

问题根源分析

  1. Expo WebView 存储持久化问题:默认配置下,Expo WebView 的 localStorage 可能未开启持久化,导致应用重启后存储的权限状态被清空。
  2. 权限校验逻辑漏洞:原代码仅在用户允许权限时标记“已请求”,若用户拒绝,下次进入仍会重复弹窗。
  3. 扫描器初始化时机不当:qr-scanner 的 start() 方法会自动触发权限请求,若未提前确认权限状态,会绕过自定义校验逻辑。

具体修复步骤

1. 开启 Expo WebView 持久化存储

在 React Native 端的 WebView 组件中添加配置,确保 localStorage 能跨会话保存:

import { WebView } from 'react-native-webview';

<WebView
  source={{ uri: '你的WebApp地址' }}
  domStorageEnabled={true}
  allowFileAccess={true}
  persistentStorageEnabled={true} // Android 专属,启用持久化存储
/>

2. 完善权限校验逻辑

修改 checkCameraPermission,无论用户允许/拒绝权限,都标记为“已请求”,同时实时查询系统权限状态:

async function checkCameraPermission() {
    const permissionAsked = localStorage.getItem('cameraPermissionAsked');
    if (permissionAsked === 'true') {
        // 已请求过,直接查询当前系统权限状态
        const currentPermission = await navigator.permissions.query({ name: 'camera' });
        return currentPermission.state === 'granted';
    }
    // 首次请求权限
    const hasPermission = await requestCameraPermissionAndStopStreams();
    // 不管结果如何,标记为已请求
    localStorage.setItem('cameraPermissionAsked', 'true');
    return hasPermission;
}

3. 调整扫描器初始化时机

确保仅在获取权限后才初始化并启动扫描器,避免库自动触发权限请求:

async function initQrScanner() {
    if (!qrCodeScanner && videoRef?.current) {
        const hasPermission = await checkCameraPermission();
        if (!hasPermission) {
            alert('请授予相机权限以使用扫码功能');
            return;
        }
        const qrScanner = new QrScanner(videoRef.current, (result) => {
            if (result?.data) {
                setNumber(formatNumber(result?.data));
            }
        },{
            preferredCamera: 'environment',
            highlightCodeOutline: true,
            highlightScanRegion: false           
        });
        qrScanner.start().catch(err => console.error('扫描器启动失败:', err));
        setQrCodeScanner(qrScanner);
    }
}

4. 页面加载时的权限同步

在相机页面的 useEffect 中添加权限检查,确保应用重启后能同步系统权限状态:

useEffect(() => {
    async function setupCamera() {
        const permissionState = await navigator.permissions.query({ name: 'camera' });
        if (permissionState.state === 'granted') {
            initQrScanner();
        } else if (permissionState.state === 'prompt') {
            const hasPermission = await checkCameraPermission();
            hasPermission && initQrScanner();
        } else {
            alert('相机权限已被拒绝,请在系统设置中开启');
        }
    }
    setupCamera();

    // 页面卸载时清理扫描器
    return () => {
        if (qrCodeScanner) {
            qrCodeScanner.stop();
            qrCodeScanner.destroy();
        }
    };
}, [videoRef]);

内容的提问来源于stack exchange,提问作者Gabriel Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 23:57:29