React Native安卓应用首次启动时二维码扫描器显示空白问题
安卓设备首次启动时react-native-qrcode-scanner显示空白页面
问题详情
- 仅安卓设备出现该问题:应用首次启动时,基于react-native-qrcode-scanner实现的二维码扫描器显示空白页面
- 此前代码运行正常,二维码扫描功能可正常使用,近期突然出现该状况
- 重启应用后扫描器可恢复正常工作,有时需重启2-3次
使用的依赖版本
"react": "17.0.2", "react-native": "0.66.3", "react-native-camera": "^4.2.1", "react-native-qrcode-scanner": "^1.5.5",
二维码扫描器实现代码
import React, { useState } from 'react'; import Colors from '../../utility/Colors'; import { TouchableOpacity, Image, View } from 'react-native'; import QRCodeScanner from 'react-native-qrcode-scanner'; import { useDispatch } from 'react-redux'; import * as booking from '../../store/action/booking'; import TextView from '../../components/UI/TextView'; import StringConstants from '../../utility/StringConstants'; import {Dimensions } from "react-native"; import normalize from '../../utility/ViewPortScaling'; import Images from '../../utility/Images'; const BarcodeReader = (props) => { const dispatch = useDispatch(); const [isBarcodeRead, setBarcode] = useState(false); const screenHeight = Math.round(Dimensions.get('window').height); const onSuccess = e => { // console.log("inside success", e.data); dispatch(booking.isBarcodeRead(true, e.data)); props.navigation.goBack(); }; return ( <View style={{height:'100%', width: '100%', backgroundColor: Colors.toledo, paddingTop:30}}> <View style={{marginStart:20,flexDirection:'row',height:150}}> {/* back button */} <View style={{ height: 80, width: 50 }}> <TouchableOpacity style={{height:80,width:50}} onPress={() => { props.navigation.goBack(); }}> <Image style={{top:50, height:15,resizeMode: 'contain' }} source={Images.backArrow} /> </TouchableOpacity> </View> <View style={{flexDirection:'column',alignItems:'center',justifyContent:'center',alignContent:'center',alignSelf:'auto'}}> {/* company logo */} <View style={{alignItems:'flex-start'}}> <Image style={{ height: 77 }} source={Images.logo} /> </View> <View style={{ alignItems:'flex-end',paddingTop:15 }}> <TextView style={{fontSize: 14,fontFamily:'Montserrat-SemiBold',lineHeight:normalize(21)}}>{StringConstants.scanString}</TextView> </View> </View> </View> <QRCodeScanner onRead={onSuccess} cameraStyle={{height: screenHeight}} reactivate={true} reactivateTimeout={20000} fadeIn={false} /> <View style={{height:50,width:50,right:10,position:'absolute',alignSelf:'flex-end',flex:1,bottom:10}}> <TouchableOpacity style={{height:100,width:50}} onPress={() => { props.navigation.goBack(); }}> <Image style={{ width:50, height:50,resizeMode: 'contain' }} source={Images.closeWithBox} /> </TouchableOpacity> </View> </View> ); } export default BarcodeReader;
测试设备
- Vivo X60(Android 13)
- Realme 5pro(Android 11)
解决方案建议
1. 主动管控相机权限时机
安卓首次启动时,相机权限请求可能未及时完成,导致扫描器初始化失败。可以在组件挂载时主动检查并请求权限,确保权限获取后再渲染扫描器:
import { PermissionsAndroid } from 'react-native'; import { useEffect, useState } from 'react'; const BarcodeReader = (props) => { const dispatch = useDispatch(); const [isBarcodeRead, setBarcode] = useState(false); const [hasCameraPermission, setHasCameraPermission] = useState(false); const screenHeight = Math.round(Dimensions.get('window').height); useEffect(() => { const requestCameraPermission = async () => { try { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.CAMERA, { title: '相机权限申请', message: '应用需要访问相机以扫描二维码', buttonNeutral: '稍后再问', buttonNegative: '取消', buttonPositive: '允许', }, ); setHasCameraPermission(granted === PermissionsAndroid.RESULTS.GRANTED); } catch (err) { console.warn(err); } }; requestCameraPermission(); }, []); const onSuccess = e => { dispatch(booking.isBarcodeRead(true, e.data)); props.navigation.goBack(); }; if (!hasCameraPermission) { return <View style={{flex:1, justifyContent:'center', alignItems:'center'}}><TextView>正在获取相机权限...</TextView></View>; } return ( // 原渲染内容 ); }
2. 延迟渲染扫描器
react-native-qrcode-scanner依赖的react-native-camera模块,首次启动时可能存在初始化延迟。可以添加短暂延迟后再渲染扫描器:
import { useEffect, useState } from 'react'; const BarcodeReader = (props) => { // ...其他状态 const [isScannerReady, setIsScannerReady] = useState(false); useEffect(() => { const timer = setTimeout(() => { setIsScannerReady(true); }, 100); return () => clearTimeout(timer); }, []); return ( <View style={{height:'100%', width: '100%', backgroundColor: Colors.toledo, paddingTop:30}}> {/* 顶部导航和logo部分 */} {isScannerReady && ( <QRCodeScanner onRead={onSuccess} cameraStyle={{height: screenHeight}} reactivate={true} reactivateTimeout={20000} fadeIn={false} /> )} {/* 关闭按钮 */} </View> ); }
3. 检查权限配置与依赖兼容性
确保安卓Manifest文件中已正确配置相机权限:
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
同时可尝试重新安装依赖,确保依赖版本与react-native@0.66.3兼容:
npm install react-native-camera@4.2.1 react-native-qrcode-scanner@1.5.5 --save
4. 添加初始化失败重试逻辑
若首次初始化失败,可通过更新组件key强制重新渲染扫描器:
const BarcodeReader = (props) => { const [scannerKey, setScannerKey] = useState(0); const handleScannerError = () => { setScannerKey(prev => prev + 1); }; return ( // ...其他内容 <QRCodeScanner key={scannerKey} onRead={onSuccess} cameraStyle={{height: screenHeight}} reactivate={true} reactivateTimeout={20000} fadeIn={false} onError={handleScannerError} /> // ...其他内容 ); }
内容的提问来源于stack exchange,提问作者Neerav Shah
相关产品推荐
相关产品推荐

