Expo构建React Native条码扫描APK后白屏问题求助
问题详情
使用Expo创建React Native条码扫描应用,执行eas build -p android --profile preview生成APK后,物理设备安装完成、相机权限申请通过后仅显示白屏,但Expo开发环境运行正常。怀疑是Stack Navigator版本导致的问题。
使用的构建命令
eas build -p android --profile preview
eas.json配置
{ "cli": { "version": ">= 13.3.0", "appVersionSource": "remote" }, "build": { "preview":{ "android": { "buildType": "apk" } }, "development": { "developmentClient": true, "distribution": "internal" }, "production": { "autoIncrement": true } }, "submit": { "production": {} } }
package.json依赖
{ "name": "my-app", "version": "1.0.0", "main": "index.js", "scripts": { "start": "expo start", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web" }, "dependencies": { "@react-native-community/cli": "^15.1.2", "@react-native-community/slider": "^4.5.5", "@react-navigation/native": "^7.0.3", "@react-navigation/stack": "^7.0.4", "axios": "^1.7.7", "expo": "~52.0.7", "expo-camera": "^16.0.5", "expo-status-bar": "~2.0.0", "react": "18.3.1", "react-native": "^0.76.2", "react-native-gesture-handler": "^2.20.2", "react-native-safe-area-context": "^4.12.0" }, "devDependencies": { "@babel/core": "^7.20.0" }, "private": true }
App.js代码
import 'react-native-gesture-handler'; import React, {useState, useEffect, useContext} from "react"; import { Text } from "react-native"; import { Camera } from "expo-camera"; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import AuthentificationScreen from "./src/Authentification"; import HandleNewScan from "./src/HandleNewScan"; import Homepage from "./src/Home"; import MyItemsPage from "./src/MyItems"; import InAppScanner from "./src/ScanItem"; import Scanner from "./src/ScanToken"; import AddItem from "./src/AddItem"; import DeleteItem from "./src/DeleteItem"; import UpdateItem from "./src/UpdateItem"; import {AppContext} from "./src/AppContext"; const Stack = createStackNavigator(); export default function App() { const [hasPermission, setHasPermission] = useState(null); const [scanned, setScanned] = useState(false); const [scannedInApp, setScannedInApp] = useState(false); const [dataBarcode, setDataBarcode] = useState(); const [typeBarcode, setTypeBarcode] = useState(); const [userId, setUserId] = useState(null); useEffect(() => { const getCameraPermissions = async () => { const { status } = await Camera.requestCameraPermissionsAsync(); setHasPermission(status === "granted"); }; setScanned(false); getCameraPermissions(); }, []); if (hasPermission === null) { return <Text>Requesting for camera permission</Text>; } if (hasPermission === false) { return <Text>No access to camera</Text>; } return( <AppContext.Provider value = {{hasPermission, setHasPermission, scanned, setScanned, scannedInApp, setScannedInApp, dataBarcode, setDataBarcode, typeBarcode, setTypeBarcode, userId, setUserId}}> <NavigationContainer> <Stack.Navigator initialRouteName="Authentification"> <Stack.Screen name="Authentification" component={AuthentificationScreen} options={{ headerShown: false, // Hides the header (including the title) }}/> <Stack.Screen name="HandleNewScan" component={HandleNewScan} options={{ headerShown: false, // Hides the header (including the title) }}/> <Stack.Screen name="Home" component={Homepage} options={{ headerShown: false, // Hides the header (including the title) }}/> <Stack.Screen name="MyItems" component={MyItemsPage} options={{ headerShown: false, // Hides the header (including the title) }}/> <Stack.Screen name="ScanItem" component={InAppScanner} options={{ headerShown: false, // Hides the header (including the title) }}/> <Stack.Screen name="ScanToken" component={Scanner} options={{ headerShown: false, // Hides the header (including the title) }}/> <Stack.Screen name="AddItem" component={AddItem} options={{ headerShown: false, // Hides the header (including the title) }}/> <Stack.Screen name="DeleteItem" component={DeleteItem} options={{ headerShown: false, // Hides the header (including the title) }}/> <Stack.Screen name="UpdateItem" component={UpdateItem} options={{ headerShown: false, // Hides the header (including the title) }}/> </Stack.Navigator> </NavigationContainer> </AppContext.Provider> ); }
尝试过本地配置Android文件但操作复杂,希望通过EAS解决或得到易懂的本地配置方案。
解决方案
1. 修复导航版本兼容性问题
你使用的@react-navigation/stack v7.0.4和@react-navigation/native v7.0.3属于React Navigation 7版本,与Expo 52存在兼容性风险。建议降级到稳定的v6版本(Expo官方推荐适配版本):
- 卸载当前导航依赖:
npm uninstall @react-navigation/native @react-navigation/stack - 安装v6稳定版:
npm install @react-navigation/native@6.x @react-navigation/stack@6.x - 同步更新配套依赖:
npx expo install react-native-screens react-native-safe-area-context - 检查页面组件的导航参数获取逻辑,确保适配v6版本(如使用
useRoute()钩子获取参数)。
2. 修正权限申请后的渲染逻辑
当前权限申请完成后直接渲染导航容器,可能存在异步状态未就绪导致的异常:
- 将
setScanned(false)移到权限获取成功后执行:useEffect(() => { const getCameraPermissions = async () => { const { status } = await Camera.requestCameraPermissionsAsync(); setHasPermission(status === "granted"); setScanned(false); // 权限确认后再重置扫描状态 }; getCameraPermissions(); }, []);
3. 优化EAS构建配置
修改eas.json的preview配置,保留调试信息方便排查问题:
"preview": { "android": { "buildType": "apk", "env": { "EXPO_DEBUG": "true" } }, "distribution": "internal" }
执行带缓存清理的重新构建:
eas build -p android --profile preview --clear-cache
4. 白屏调试方法
- 连接物理设备到电脑,执行
adb logcat *:E查看Android系统级错误日志,定位具体异常。 - 构建开发版APK调试:
安装后摇晃设备调出调试菜单,查看JS报错信息。eas build -p android --profile development
5. 简化本地Android配置(可选)
如果需要本地构建,执行以下步骤:
- 生成本地Android项目:
npx expo prebuild --platform android - 打开
android/app/src/main/AndroidManifest.xml,确认相机权限已添加:<uses-permission android:name="android.permission.CAMERA" /> - 执行本地构建:
生成的APK位于./gradlew assembleReleaseandroid/app/build/outputs/apk/release/app-release.apk。
内容的提问来源于stack exchange,提问作者Eduard Cavasi
相关产品推荐
相关产品推荐

