ScaleRocket/Mobile

Camera

Using expo-camera for taking photos, QR code scanning, and handling camera permissions.

Camera

ScaleRocket Mobile uses expo-camera for taking photos and scanning QR codes. The camera requires a development build and explicit user permission.

Setup

npx expo install expo-camera

Add the camera permission description to app.json:

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSCameraUsageDescription": "We use the camera to take profile photos and scan QR codes"
      }
    }
  }
}

Permission Handling

Always request permission before showing the camera:

import { CameraView, useCameraPermissions } from "expo-camera";

export default function CameraScreen() {
  const [permission, requestPermission] = useCameraPermissions();

  if (!permission) return <Loading />;

  if (!permission.granted) {
    return (
      <View style={styles.container}>
        <Text>Camera access is required</Text>
        <Button title="Grant Permission" onPress={requestPermission} />
      </View>
    );
  }

  return <CameraView style={{ flex: 1 }} />;
}

Taking Photos

Capture a photo using a ref:

import { useRef } from "react";
import { CameraView } from "expo-camera";

export default function PhotoScreen() {
  const cameraRef = useRef<CameraView>(null);

  const takePhoto = async () => {
    if (!cameraRef.current) return;

    const photo = await cameraRef.current.takePictureAsync({
      quality: 0.8,
      base64: false,
      exif: false,
    });

    console.log("Photo URI:", photo.uri);
    // Navigate to preview or upload
  };

  return (
    <View style={{ flex: 1 }}>
      <CameraView ref={cameraRef} style={{ flex: 1 }} facing="back">
        <View style={styles.controls}>
          <TouchableOpacity style={styles.captureButton} onPress={takePhoto}>
            <View style={styles.captureInner} />
          </TouchableOpacity>
        </View>
      </CameraView>
    </View>
  );
}

Switch Camera

Toggle between front and back cameras:

function CameraWithToggle() {
  const [facing, setFacing] = useState<"front" | "back">("back");
  const cameraRef = useRef<CameraView>(null);

  const toggleFacing = () => {
    setFacing((prev) => (prev === "back" ? "front" : "back"));
  };

  return (
    <CameraView ref={cameraRef} style={{ flex: 1 }} facing={facing}>
      <TouchableOpacity style={styles.flipButton} onPress={toggleFacing}>
        <Ionicons name="camera-reverse" size={28} color="white" />
      </TouchableOpacity>
    </CameraView>
  );
}

QR Code Scanning

Use the camera's built-in barcode scanner:

import { CameraView } from "expo-camera";

function QRScanner() {
  const [scanned, setScanned] = useState(false);

  const handleBarCodeScanned = ({ type, data }: { type: string; data: string }) => {
    if (scanned) return;
    setScanned(true);

    Alert.alert("QR Code Scanned", data, [
      { text: "Scan Again", onPress: () => setScanned(false) },
      { text: "Open", onPress: () => Linking.openURL(data) },
    ]);
  };

  return (
    <CameraView
      style={{ flex: 1 }}
      facing="back"
      barcodeScannerSettings={{
        barcodeTypes: ["qr"],
      }}
      onBarcodeScanned={scanned ? undefined : handleBarCodeScanned}
    />
  );
}

Camera Overlay

Add a custom overlay for the camera viewfinder:

<CameraView style={{ flex: 1 }} facing="back">
  <View style={styles.overlay}>
    <View style={styles.scanArea}>
      {/* Transparent center for QR scanning */}
    </View>
    <Text style={styles.instructions}>
      Point your camera at a QR code
    </Text>
  </View>
</CameraView>

const styles = StyleSheet.create({
  overlay: {
    flex: 1,
    backgroundColor: "rgba(0,0,0,0.5)",
    justifyContent: "center",
    alignItems: "center",
  },
  scanArea: {
    width: 250,
    height: 250,
    borderWidth: 2,
    borderColor: "white",
    borderRadius: 12,
    backgroundColor: "transparent",
  },
  instructions: {
    color: "white",
    marginTop: 24,
    fontSize: 16,
  },
});

Important Notes

  • Camera requires a development build (not Expo Go)
  • iOS simulators have a limited camera simulation
  • Android emulators support a virtual scene camera
  • Always handle the case where permission is denied gracefully
  • Dispose of photo URIs when done to free memory

On this page