React Native iOS端RNCamera扫码相机无法打开,显示黑屏求助
React Native iOS 相机扫描QR码黑屏问题
我在React Native开发iOS应用时,调用相机扫描QR码出现黑屏。已完成相机权限申请逻辑,Info.plist中配置了NSCameraUsageDescription,日志显示权限已授予且成功获取到QR字符串,但无任何报错或警告,相机仅显示空白黑屏。
我的代码
import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import { RNCamera } from 'react-native-camera'; import { request, PERMISSIONS, check, RESULTS } from 'react-native-permissions'; import axios from 'axios'; import Toast from 'react-native-simple-toast'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { API_DOMAIN, GET_EVENT_DETAILS } from '../../components/apiConstants'; const CheckedIn = ({ navigation, route }) => { const [isCheckedIn, setIsCheckedIn] = useState(false); const [checkInMessage, setCheckInMessage] = useState(''); const [eQRstring, setEQRstring] = useState(''); useEffect(() => { fetchQRString(); }, []); const fetchQRString = async () => { try { const storedEvent = await AsyncStorage.getItem('selectedSeminar'); const selectedSeminar = JSON.parse(storedEvent); const eventID = selectedSeminar.eid; const pocid = await AsyncStorage.getItem('pocid'); const response = await axios.get( `${API_DOMAIN}${GET_EVENT_DETAILS}?eid=${eventID}&poid=${pocid}` ); console.log(response.data.data.eQRstring); if (response.data.data.eQRstring) { const qrString = response.data.data.eQRstring; setEQRstring(qrString); console.log('QR String:', qrString); } else { console.error('eQRstring is undefined in the response data'); } } catch (error) { console.error('Error fetching QR string:', error); } }; const handleScanSuccess = async (event) => { try { const scannedStringData = event.data.trim(); console.log('Scanned Data:', scannedStringData); console.log('Expected QR String:', eQRstring); if (scannedStringData === eQRstring) { Toast.show('Check-in Successful!', Toast.SHORT); navigation.navigate('HomeScreen'); } else { setCheckInMessage('Invalid QR code'); console.log('Invalid QR code'); Toast.show('Invalid QR code!', Toast.SHORT); navigation.navigate('HomeScreen'); } } catch (error) { setCheckInMessage('Error handling scan'); console.error('Error handling scan:', error); } }; const requestCameraPermission = async () => { const result = await check(PERMISSIONS.IOS.CAMERA); if(result === RESULTS.GRANTED){ console.log('Camera permission granted'); } else{ const permissionResult = await request(PERMISSIONS.IOS.CAMERA); if (permissionResult !== 'granted') { console.error('Camera permission denied'); } else{ console.log('Camera permissions granted'); } } }; useEffect(() => { requestCameraPermission(); }, []); const renderQRCodeScanner = () => { console.log('Rendering QR Code Scanner'); return ( <RNCamera style={styles.cameraStyle} onRead={handleScanSuccess} onCameraReady={()=> console.log('Camera is ready')} showMarker={true} markerStyle={styles.markerStyle} captureAudio={false} ratio='16:9' /> ); }; return ( <View style={styles.container}> {isCheckedIn ? ( <Text style={styles.text}>Checked In!</Text> ) : ( <> {renderQRCodeScanner()} {checkInMessage ? ( <Text style={styles.message}>{checkInMessage}</Text> ) : null} </> )} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, cameraStyle: { flex: 1, borderWidth: 1, backgroundColor: 'red', justifyContent: 'center', alignItems: 'center', }, markerStyle: { borderColor: 'red', borderRadius: 10, }, text: { fontSize: 24, fontWeight: 'bold', color: 'green', }, message: { fontSize: 16, color: 'red', marginTop: 20, }, }); export default CheckedIn;
Info.plist权限配置
<key>NSCameraUsageDescription</key> <string>We need access to your camera to scan QR codes.</string>
日志信息
- LOG QR String: 1688236200
- LOG Camera permission granted
排查与解决方法
1. 修复相机视图样式
当前cameraStyle的backgroundColor: 'red'会覆盖相机画面,且布局设置不合理。修改样式确保相机占满屏幕:
const styles = StyleSheet.create({ container: { flex: 1, // 移除justifyContent和alignItems,让相机视图自然填充 }, cameraStyle: { flex: 1, width: '100%', height: '100%', // 移除backgroundColor和无关布局属性 }, // 其他样式保持不变 });
2. 确保权限生效后再渲染相机
现在两个useEffect并行执行,可能出现相机先渲染但权限未完全生效的情况。添加状态控制相机渲染时机:
const [cameraPermissionGranted, setCameraPermissionGranted] = useState(false); // 修改权限请求函数 const requestCameraPermission = async () => { const result = await check(PERMISSIONS.IOS.CAMERA); if(result === RESULTS.GRANTED){ console.log('Camera permission granted'); setCameraPermissionGranted(true); } else { const permissionResult = await request(PERMISSIONS.IOS.CAMERA); if (permissionResult === RESULTS.GRANTED) { console.log('Camera permissions granted'); setCameraPermissionGranted(true); } else { console.error('Camera permission denied'); } } }; // 修改相机渲染函数 const renderQRCodeScanner = () => { if(!cameraPermissionGranted) return null; console.log('Rendering QR Code Scanner'); return ( <RNCamera style={styles.cameraStyle} onRead={handleScanSuccess} onCameraReady={()=> console.log('Camera is ready')} showMarker={true} markerStyle={styles.markerStyle} captureAudio={false} ratio='16:9' /> ); };
3. 验证依赖兼容性与项目配置
- 确保
react-native-camera版本与当前React Native版本兼容,执行更新命令:npm install react-native-camera@latest --save cd ios && pod install && cd .. - 打开Xcode,清理编译缓存(
Product > Clean Build Folder)后重新编译项目。 - 确认
Info.plist中NSCameraUsageDescription配置无误,字符串不为空。
4. 改用真机测试
iOS模拟器的相机功能有限,黑屏问题大概率在真机上会消失,直接使用真机进行测试验证。
内容的提问来源于stack exchange,提问作者Aashi
相关产品推荐
相关产品推荐

