Purnendu Prabhat
Purnendu Prabhat

Reputation: 21

Cannot find native module 'ExpoCamera'

I am building a react-native app for android using typescript and expo. I want to access the camera. For this I have used the code from the expo documentation:

import { CameraView, CameraType, useCameraPermissions } from 'expo-camera';
import { useState } from 'react';
import { Button, StyleSheet, Text, TouchableOpacity, View } from 'react-native';

export default function App() {
  const [facing, setFacing] = useState<CameraType>('back');
  const [permission, requestPermission] = useCameraPermissions();

  if (!permission) {
    // Camera permissions are still loading.
    return <View />;
  }

  if (!permission.granted) {
    // Camera permissions are not granted yet.
    return (
      <View style={styles.container}>
        <Text style={styles.message}>We need your permission to show the camera</Text>
        <Button onPress={requestPermission} title="grant permission" />
      </View>
    );
  }

  function toggleCameraFacing() {
    setFacing(current => (current === 'back' ? 'front' : 'back'));
  }

  return (
    <View style={styles.container}>
      <CameraView style={styles.camera} facing={facing}>
        <View style={styles.buttonContainer}>
          <TouchableOpacity style={styles.button} onPress={toggleCameraFacing}>
            <Text style={styles.text}>Flip Camera</Text>
          </TouchableOpacity>
        </View>
      </CameraView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  message: {
    textAlign: 'center',
    paddingBottom: 10,
  },
  camera: {
    flex: 1,
  },
  buttonContainer: {
    flex: 1,
    flexDirection: 'row',
    backgroundColor: 'transparent',
    margin: 64,
  },
  button: {
    flex: 1,
    alignSelf: 'flex-end',
    alignItems: 'center',
  },
  text: {
    fontSize: 24,
    fontWeight: 'bold',
    color: 'white',
  },
});

When I run, I get this error:


Logs for your project will appear below. Press Ctrl+C to exit.
Android Bundled 52499ms D:\practice_codes\react-native\expo-docu\purnendu-prabhat\node_modules\expo-router\entry.js (1155 modules)
 WARN  [Reanimated] Reduced motion setting is enabled on this device. This warning is visible only in the development mode. Some animations will be disabled by default. You can override the behavior for individual animations, see https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooting#reduced-motion-setting-is-enabled-on-this-device.
    at ContextNavigator (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:146208:24)
    at ExpoRoot (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:146164:28)
    at App
    at ErrorToastContainer (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:189391:24)
    at ErrorOverlay
    at withDevTools(ErrorOverlay) (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:189110:27)
    at RCTView
    at View (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:41374:43)
    at RCTView
    at View (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:41374:43)
    at AppContainer (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:41217:25)
    at main(RootComponent) (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:120269:28)
 ERROR  Error: Cannot find native module 'ExpoCamera', js engine: hermes
    at ContextNavigator (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:146208:24)
    at ExpoRoot (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:146164:28)
    at App
    at ErrorToastContainer (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:189391:24)
    at ErrorOverlay
    at withDevTools(ErrorOverlay) (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:189110:27)
    at RCTView
    at View (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:41374:43)
    at RCTView
    at View (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:41374:43)
    at AppContainer (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:41217:25)
    at main(RootComponent) (http://192.168.1.11:8081/node_modules/expo-router/entry.bundle//&platform=android&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.routerRoot=app:120269:28)

I was expecting a smoot run and be able to capture image from mobile camera. I have tried to upgrace expo to version 51. still does not work.

Upvotes: 0

Views: 656

Answers (1)

Jonathan Sanchez
Jonathan Sanchez

Reputation: 9344

You might need to add the mode like this

<CameraView style={styles.camera} ref={cameraRef} mode="video"> or mode="picture"

Here is my code that worked for me

import { CameraView, useCameraPermissions } from "expo-camera";
import * as MediaLibrary from "expo-media-library";
import { useState, useRef, Children } from "react";
import {
  Button,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
  Image,
} from "react-native";

export default function CameraComponent() {
  const [permission, requestPermission] = useCameraPermissions();
  const [mediaLibraryPermission, requestMediaLibraryPermission] =
    MediaLibrary.usePermissions();

  const cameraRef = useRef<CameraView>(null);
  const [recording, setRecording] = useState(false);

  if (!permission) {
    // Camera permissions are still loading.
    return <View />;
  }

  const takeVideo = async () => {
    console.log("taking video");

    if (cameraRef.current) {
      try {
        setRecording(true);

        const video = await cameraRef.current.recordAsync();
        console.log("video", video);

        if (video) {
          console.log("video.uri", video.uri);
          const asset = await MediaLibrary.createAssetAsync(video.uri);
          console.log(asset);
        }
      } catch (error) {
        console.log("error", error);
      }
    }
  };

  const stopVideo = async () => {
    if (cameraRef.current) {
      try {
        const stoppingVideo = await cameraRef.current.stopRecording();
        console.log("stopping video", stoppingVideo);
        setRecording(false);
      } catch (error) {
        console.log("error", error);
      }
    }
  };

  if (!permission.granted || !mediaLibraryPermission?.granted) {
    return (
      <View style={styles.container}>
        <Text style={{ textAlign: "center" }}>
          We need your permission to show the camera
        </Text>
        <Button onPress={requestPermission} title="grant permission" />
        <Button onPress={requestPermission} title="Grant Camera Permission" />
        <Button
          onPress={requestMediaLibraryPermission}
          title="Grant Media Library Permission"
        />
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <CameraView style={styles.camera} ref={cameraRef} mode="picture">
        <View className="h-full flex-row items-end justify-center">
          <TouchableOpacity
            className="bg-red-500 p-4 rounded-lg m-2 "
            onPress={takeVideo}
            disabled={recording}
          >
            <Text className="text-white text-center text-2xl font-bold">
              {recording ? "Recording" : "Record"}
            </Text>
          </TouchableOpacity>
          <TouchableOpacity
            className="bg-red-500 p-4 rounded-lg m-2 "
            onPress={stopVideo}
          >
            <Text className="text-white text-center text-2xl font-bold">
              Stop
            </Text>
          </TouchableOpacity>
        </View>
      </CameraView>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
  },
  camera: {
    flex: 1,
  },
  button: {
    flex: 1,
    alignSelf: "flex-end",
    alignItems: "center",
  },
  text: {
    fontSize: 24,
    fontWeight: "bold",
    color: "white",
  },
});

I'm on

  "expo": "~51.0.14",
  "expo-camera": "~15.0.14",

Upvotes: 0

Related Questions