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

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调试:
    eas build -p android --profile development
    
    安装后摇晃设备调出调试菜单,查看JS报错信息。

5. 简化本地Android配置(可选)

如果需要本地构建,执行以下步骤:

  1. 生成本地Android项目:
    npx expo prebuild --platform android
    
  2. 打开android/app/src/main/AndroidManifest.xml,确认相机权限已添加:
    <uses-permission android:name="android.permission.CAMERA" />
    
  3. 执行本地构建:
    ./gradlew assembleRelease
    
    生成的APK位于android/app/build/outputs/apk/release/app-release.apk。

内容的提问来源于stack exchange,提问作者Eduard Cavasi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:14:54