Creating a React Native Vision Camera Code Scanner – a step-by-step tutorial

Kevin October 24, 2024 9 mins read
app store

In this tutorial, we’ll walk you through how to create a barcode scanner app using the React Native Vision Camera library. This tutorial focuses exclusively on implementing the library’s barcode scanning functionality, making it easier to quickly build this feature into your mobile application.

To achieve this, we’re going to follow these steps:

  1. Create a new React Native project
  2. Install the React Native Vision Camera library
  3. Configure the permissions 
  4. Request the camera permissions
  5. Add the barcode scanner
  6. Test the app

Prerequisites

Before you start creating the project, make sure your development environment is set up with the following tools:

  • Node.js: Highly recommended when developing React Native apps. You can download it from the Node.js website if you don’t have it.
  • Android Studio: This includes the SDKs and emulators needed to build and test your app. Download the latest version from the Android Studio website.
  • Java Development Kit (JDK): React Native requires Java for Android builds. You can download the Oracle JDK or use Microsoft’s OpenJDK instead.

Ensure these tools are installed and configured before continuing with the barcode scanner tutorial.

Step 1: Create a new React Native project

As your first step, you have to create a new React Native project. Open your terminal and run the following command to create a new project named BarcodeScannerApp:

npx react-native init BarcodeScannerApp

After creating the project, navigate to your project:

cd BarcodeScannerApp

Step 2: Install the React Native Vision Camera library

To add camera capabilities to the React Native app, we will use the Vision Camera library. This library provides a range of features for working with camera streams and processing visual data. You can install it by running the following command in your project directory:

npm install react-native-vision-camera

This tutorial will focus exclusively on the Vision Camera library’s barcode scanning functionality. This feature allows the app to detect and process different barcode symbologies. 

Step 3: Configure the permissions 

To allow the app to access the camera, you need to update the AndroidManifest.xml file located at android/app/src/main/AndroidManifest.xml. Add the following permission tags to the <manifest> tag:

<uses-permission android:name="android.permission.CAMERA" />

The following code block shows how the complete AndroidManifest.xml file should look after adding the camera permission:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme"
      android:supportsRtl="true">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
        android:launchMode="singleTask"
        android:windowSoftInputMode="adjustResize"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
    </application>
</manifest>

Step 4: Request the camera permissions

Now that you’ve configured camera permissions in AndroidManifest.xml, the next step is to handle camera access within the app. To ensure that the app requests the necessary permissions from the user before accessing the camera, we’ll use a hook to ask the user permission to use the camera when the app starts. 

Open your App.tsx file and modify it to handle the permission request:

import React, { useState, useEffect } from "react";
import { SafeAreaView, Text, StyleSheet } from "react-native";
import { Camera } from "react-native-vision-camera";

const App: React.FC = () => {
  const [hasPermission, setHasPermission] = useState<boolean>(false);

  useEffect(() => {
    const getPermissions = async () => {
      const cameraPermission = await Camera.requestCameraPermission();
      setHasPermission(cameraPermission === "granted");
    };

    getPermissions();
  }, []);

  if (!hasPermission) return <Text>No camera permission</Text>;

  return <SafeAreaView style={styles.container}>...</SafeAreaView>;
};

export default App;

The code above manages camera permissions using React hooks. The useEffect hook triggers when the app starts, running the getPermissions function to request camera access. If permission is granted, the state variable hasPermission is updated to true, allowing the camera feed to display. If permission is denied, the app will show a message informing the user that camera access is required. This ensures the app doesn’t try to access the camera without user consent.

Step 5: Add the barcode scanner

After setting the permission request, you can add the barcode scanning feature code. At this step, you will use the Vision Camera library functionalities. 

First, import the necessary functions from react-native-vision-camera:

import {
  Camera,
  useCameraDevices,
  useCodeScanner,
  getCameraDevice,
} from "react-native-vision-camera";

Next, you’ll need to fetch a list of available camera devices and select the back camera for barcode scanning.

const devices = useCameraDevices();
const device = getCameraDevice(devices, "back");

Since we handled the permission request in step 4, we can now configure the barcode scanner using the useCodeScanner() hook. This hook requires two main properties:

  • codeTypes: An array specifying the types of barcodes the app will scan. For this tutorial, we’ll use EAN-13 barcodes. You can explore the Vision Camera documentation for a full list of supported barcode types.
  • onCodeScanned: A callback function that triggers when a barcode is scanned. For this tutorial, the function loops through the scanned codes and displays an alert with the barcode type.

The following code block presents the complete code for the useCodeScanner() hook.

const codeScanner: CodeScanner = useCodeScanner({
    codeTypes: ['ean-13'],
    onCodeScanned: (codes) => {
      for (const code of codes) {
        setIsScanning(false)
        console.log(`Code Value: ${code.value}`);
         Alert.alert('Scanned Code', `${code.value}`, [
           {
             text: 'OK',
             onPress: () => setIsScanning(true), // Stop scanning after alert
           },
       ]);
      }
    },
  });

Afterward, you need to handle the UI response for loading the camera and managing permissions. The following code ensures the app shows a message while the device is being identified and notifies the user if camera access hasn’t been granted.

if (!device) return <Text>Loading camera...</Text>;
if (!hasPermission) return <Text>No camera permission</Text>;

Lastly, configure the app’s interface. The Camera component displays the camera feed using the back camera device. At the same time, the codeScanner processes each frame to scan for barcodes. You can also control how often frames are processed using the frameProcessorFps attribute. The following code block presents the app UI configuration.

return (
  <SafeAreaView style={styles.container}>
    <Camera
      style={StyleSheet.absoluteFill}
      device={device}
      isActive={true}
      frameProcessorFps={2}
      codeScanner={codeScanner}
    />
    <View style={styles.infoContainer}>
      <Text style={styles.infoText}>Point the camera at a code</Text>
    </View>
  </SafeAreaView>
);

Below is the complete code for the App.tsx file after adding the barcode scanning functionality:

import React, { useState, useEffect } from 'react';
import { SafeAreaView, Text, View, StyleSheet, Alert } from 'react-native';
import { Camera, useCameraDevices, useCodeScanner, getCameraDevice } from 'react-native-vision-camera';

const App: React.FC = (props) => {
  const [hasPermission, setHasPermission] = useState<boolean>(false);
  const [isScanning, setIsScanning] = useState<boolean>(true);
  const devices = useCameraDevices();
  const device = getCameraDevice(devices, 'back');

  useEffect(() => {
    const getPermissions = async () => {
      const cameraPermission = await Camera.requestCameraPermission();
      console.log(cameraPermission)
      setHasPermission(cameraPermission === 'granted');
    };

    getPermissions();
  }, []);

  const codeScanner: CodeScanner = useCodeScanner({
    codeTypes: ['ean-13'],
    onCodeScanned: (codes) => {
      for (const code of codes) {
        setIsScanning(false)
        console.log(`Code Value: ${code.value}`);
         Alert.alert('Scanned Code', `${code.value}`, [
           {
             text: 'OK',
             onPress: () => setIsScanning(true), // Stop scanning after alert
           },
       ]);
      }
    },
  });

  if (device == null) return <Text>Loading camera...</Text>;
  if (!hasPermission) return <Text>No camera permission</Text>;

  return (
    <SafeAreaView style={styles.container}>
      <Camera
        style={StyleSheet.absoluteFill}
        device={device}
        isActive={true}
        frameProcessorFps={2}
        {...props}
        codeScanner={isScanning ? codeScanner : undefined}
      />
      <View style={styles.infoContainer}>
        <Text style={styles.infoText}>Point the camera at a code</Text>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  infoContainer: {
    position: 'absolute',
    bottom: 50,
    backgroundColor: 'rgba(0,0,0,0.5)',
    padding: 10,
    borderRadius: 5,
  },
  infoText: {
    color: 'white',
    fontSize: 16,
  },
});

export default App;

Step 6: Test the app

To test your application, run the Android app with the following command:

npx react-native run-android

Then, point the camera at an EAN-13 Barcode. Once the code is scanned, an alert will display the code’s value on the screen.

The React Native Vision Camera code scanner in action

Disadvantages of using the React Native Vision Camera library for scanning barcodes

While it is a useful tool for React Native developers, there are a few notable disadvantages to using the Vision Camera library for scanning barcodes:

  • Performance and stability issues: Several developers have reported crashes when using the library for barcode scanning on Android devices, particularly after scanning a barcode, causing the application to close unexpectedly. The library also has had issues handling different device orientations.
  • Compatibility and support: There have been reports of functionality working in some versions but breaking in others. Some developers also have experienced problems with scanning barcodes on specific devices.
  • Implementation challenges: Implementing barcode scanning can be tricky, with some developers reporting difficulties in getting the scanner to recognize barcodes consistently. Frame processors, which are used for real-time image processing, also do not work well with the scanner functionality, requiring developers to find workarounds.
  • Permissions and access: Some users have encountered problems with camera permissions, particularly on Android devices, leading to errors like “Access denied finding property ‘vendor.camera.aux.packagelist'”.

We developed the Scanbot Barcode Scanner SDK as a commercial solution to help enterprises overcome these hurdles presented by free barcode scanning software. Our goal was to have a developer-friendly solution available for a wide range of platforms that consistently delivers high-quality results – even in challenging circumstances.

Integrating the SDK into your React Native app only takes a few minutes. Don’t believe us? Then give it a try yourself by heading over to our step-by-step tutorial! Or take a look at our React Native example app for an implementation similar to this Vision Camera one.

Should you have any questions, feel free to reach out to us on Slack or MS Teams or send us an email via sdksupport@scanbot.io.