React Native Expo on iOS: Camera is black on iPhone after granting permissions

224 views Asked by At

I'm new to using react native with Expo framework. I'm trying to access the cell phone's camera. I tested the application on an Android phone, the application asks me to accept permissions and the camera works correctly. Exactly same code, different device: iPhone. Using Testflight, I published the same App for iOS, downloaded TestFlight and installed the App. When my App asks for Camera permissions, I accept, but the Camera remains black. I tried checking the permissions in the iPhone settings and they are all set correctly on "allow". I tried deleting and reinstalling the app on iPhone, but the problem remains.

My app works using screens and Navigation

I'm using "expo-camera": "~13.4.4"

Here the Scanner screen code where the camera should used:

const ScannerScreen = ({ navigation, route }) => {
    const { host, tokenData, canvas, petShopData } = useContext(Contesto);
    const { _t } = useContext(LanguageContext);

    const [hasPermission, setHasPermission] = useState(null);
    const [scanned, setScanned] = useState(false);
    const [loader, setLoader] = useState(false);
    
    const cameraRef = useRef(null);
    
const [isFocused, setIsFocused] = useState(false);

    useEffect(() => {
        navigation.setOptions({
            title: _t("scanAProductBarcode"),
            headerTintColor: "#0071bb",
            headerBackTitleVisible: false,
            headerTitleAlign: 'center',
        });
    }, [navigation])

    /*********************************************** */
    /**************** PERMISSIONS REQUESTS ***********/
    /*********************************************** */

    useFocusEffect(
        React.useCallback(() => {
            setIsFocused(true);
            const startCamera = async () => {
                const { status } = await Camera.requestCameraPermissionsAsync();
                if (status === 'granted' && isFocused) {
                    setHasPermission(true);
                    await cameraRef.current?.resumePreview();
                    console.log('Camera started');
                }
                if (Platform.OS == 'ios' && status !== 'granted') {
                    Linking.openSettings();
                }
            };

            startCamera();

            return () => {
                setIsFocused(false);
                stopCamera();
            };
        }, [])
    );

    const stopCamera = async () => {
        await cameraRef.current?.pausePreview();
        console.log('Camera stopped');
    };
    
    useEffect(() => {
        console.log("------##### SCANNER SCREEN LOADED  ########----")
        getBarCodeScannerPermissions();
    }, []);
    

    /** CAMERA-BARCODE PERMISSIONS */
    const getBarCodeScannerPermissions = async () => {
        //console.log("camera permissions requested");
        const { status } = await Camera.requestCameraPermissionsAsync();// .requestPermissionsAsync();
        if (status) {
            setHasPermission(status === 'granted');
        }
        if (Platform.OS == 'ios' && status !== 'granted') {
            Linking.openSettings();
        }
    };

    /** /CAMERA-BARCODE PERMISSIONS */

This the return View:

            <View style={barscan.container}>
                {(hasPermission === null) &&
                    <View>
                        <Text style={[globalStyles.bigSubtitle, { textAlign: "center" }]}>{_t("waitingCameraPermissions")}</Text>
                    </View>
                }
                {(hasPermission === false) &&
                    <View style={{ width: "100%", flex: 1, flexDirection: "column", alignContent: "center", justifyContent: "center", }}>
                        <Text style={[globalStyles.bigSubtitle, { textAlign: "center" }]}>No access to camera</Text>
                        <Text style={[globalStyles.bigSubtitle, { textAlign: "center" }]}>In order to scan codes, please grant access to camera
                            <TouchableOpacity onPress={getBarCodeScannerPermissions}>
                                <Text style={[globalStyles.btnReqCamPerm, globalStyles.buttonInfo, { textAlign: "center" }]}>
                                    <AntDesign name="camera" size={26} color="#fff" /> {_t("grantCameraPermissions")}
                                </Text>
                            </TouchableOpacity>
                        </Text>
                    </View>
                }
                {(hasPermission !== null && hasPermission !== false) && isFocused && 
                    <>
                        <Camera
                            ref={cameraRef}
                            type={0}
                            autoFocus={true}
                            onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
                            style={[barscan.barCodeCamera,]}
                        />
                    </>
                }
            </View>

As for the Android app, when I allow the camera to be used, the <Camera component starts to be active and works. On Android phones the code works correctly, but on iPhone I receive the popup message granting, I confirm and authorize, but the Camera component appears black and does not work.

I tested the application on 3 different iPhones (X, 12 and 15) using Testflight and the result did not change: Black Camera component.

I'm wondering if it could be a script or TestFlight issue at this point.

0

There are 0 answers