QR Code Scanning in React-Native 0.71
If you’re here you’ve probably tried all the old methods of scanning QR codes in react-native that no longer work. I’m glad you’ve found this post :)
You’ve made the right choice with React-Native Vision Camera
and Vision Camera Code Scanner
.
There’s a slight catch, though — they need some tweaks to play nicely with React-Native 0.71. But don’t worry, we’ve got you covered with a step-by-step guide to iron out these quirks and unlock the full potential of these libraries.
And once we’ve got these libraries behaving, we’ll also show you how to whip up a nifty QR code reader. So buckle up and let’s get rolling!
Step 1: Equip Your Toolkit with patch-package
First things first, let’s get patch-package
into our toolkit. This trusty tool helps us apply the necessary patches to our npm
dependencies, like a pro. Add it to your project with:
npm install patch-package
or, if you prefer yarn:
yarn add patch-package
Remember, patch-package
is a tool for your developer's kit, you won't need it in the production build!
Step 2: Smoothing Out React-Native Vision Camera
Now, let’s get react-native-vision-camera
in line. Create a new file in your project's root directory and name it react-native-vision-camera+2.15.4.patch
. Add the following content:
diff --git a/node_modules/react-native-vision-camera/android/build.gradle b/node_modules/react-native-vision-camera/android/build.gradle
index 91e64d9..579ed1f 100644
--- a/node_modules/react-native-vision-camera/android/build.gradle
+++ b/node_modules/react-native-vision-camera/android/build.gradle
@@ -50,7 +50,7 @@ def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME").split("\\
def FOR_HERMES = System.getenv("FOR_HERMES") == "True"
rootProject.getSubprojects().forEach({project ->
if (project.plugins.hasPlugin("com.android.application")) {
- FOR_HERMES = REACT_NATIVE_VERSION >= 71 && project.hermesEnabled || project.ext.react.enableHermes
+ FOR_HERMES = REACT_NATIVE_VERSION >= 71 && project.hermesEnabled.toBoolean() || project.ext.react.enableHermes
}
})
def jsRuntimeDir = {
diff --git a/node_modules/react-native-vision-camera/android/src/main/cpp/MakeJSIRuntime.h b/node_modules/react-native-vision-camera/android/src/main/cpp/MakeJSIRuntime.h
index 39045bd..c135caf 100644
--- a/node_modules/react-native-vision-camera/android/src/main/cpp/MakeJSIRuntime.h
+++ b/node_modules/react-native-vision-camera/android/src/main/cpp/MakeJSIRuntime.h
@@ -12,7 +12,7 @@
#include <hermes/hermes.h>
#else
// JSC
- #include <jsi/JSCRuntime.h>
+ #include <jsc/JSCRuntime.h>
#endif
namespace vision {
diff --git a/node_modules/react-native-vision-camera/ios/React Utils/MakeJSIRuntime.h b/node_modules/react-native-vision-camera/ios/React Utils/MakeJSIRuntime.h
index a428c01..0d80e3c 100644
--- a/node_modules/react-native-vision-camera/ios/React Utils/MakeJSIRuntime.h
+++ b/node_modules/react-native-vision-camera/ios/React Utils/MakeJSIRuntime.h
@@ -22,7 +22,7 @@
#include <v8runtime/V8RuntimeFactory.h>
#else
// JSC
- #include <jsi/JSCRuntime.h>
+ #include <React-jsc/JSCRuntime.h>
#endif
using namespace facebook;
Time to let patch-package
shine! Run the following command:
npx patch-package react-native-vision-camera
Bingo! Your first patch has been successfully applied!
Step 3: Fine-Tuning Vision Camera Code Scanner
Next up is vision-camera-code-scanner
. Again, create a new file and name it vision-camera-code-scanner+0.2.0.patch
. Add this content:
diff --git a/node_modules/vision-camera-code-scanner/android/build.gradle b/node_modules/vision-camera-code-scanner/android/build.gradle
index b6bd964..4567cfb 100644
--- a/node_modules/vision-camera-code-scanner/android/build.gradle
+++ b/node_modules/vision-camera-code-scanner/android/build.gradle
@@ -18,11 +18,11 @@ def safeExtGet(prop, fallback) {
}
android {
- compileSdkVersion safeExtGet('VisionCameraCodeScanner_compileSdkVersion', 30)
+ compileSdkVersion safeExtGet('compileSdkVersion', 30)
ndkVersion "21.4.7075529"
defaultConfig {
- minSdkVersion safeExtGet('VisionCameraCodeScanner_minSdkVersion', 21)
- targetSdkVersion safeExtGet('VisionCameraCodeScanner_targetSdkVersion', 31)
+ minSdkVersion safeExtGet('minSdkVersion', 21)
+ targetSdkVersion safeExtGet('targetSdkVersion', 31)
versionCode 1
versionName "1.0"
@@ -56,6 +56,6 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
api project(":react-native-vision-camera")
- implementation "androidx.camera:camera-core:1.1.0-alpha06"
- implementation 'com.google.mlkit:barcode-scanning:17.0.0'
+ implementation "androidx.camera:camera-core:1.1.0-alpha08"
+ implementation 'com.google.mlkit:barcode-scanning:17.0.2'
}
diff --git a/node_modules/vision-camera-code-scanner/android/src/main/java/com/visioncameracodescanner/BarcodeConverter.java b/node_modules/vision-camera-code-scanner/android/src/main/java/com/visioncameracodescanner/BarcodeConverter.java
index 74e208b..eb4ed07 100644
--- a/node_modules/vision-camera-code-scanner/android/src/main/java/com/visioncameracodescanner/BarcodeConverter.java
+++ b/node_modules/vision-camera-code-scanner/android/src/main/java/com/visioncameracodescanner/BarcodeConverter.java
@@ -7,7 +7,7 @@ import androidx.annotation.NonNull;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
-import com.google.mlkit.vision.barcode.Barcode;
+import com.google.mlkit.vision.barcode.common.Barcode;
import java.util.List;
diff --git a/node_modules/vision-camera-code-scanner/android/src/main/java/com/visioncameracodescanner/VisionCameraCodeScannerPlugin.java b/node_modules/vision-camera-code-scanner/android/src/main/java/com/visioncameracodescanner/VisionCameraCodeScannerPlugin.java
index 8198564..a3adafd 100644
--- a/node_modules/vision-camera-code-scanner/android/src/main/java/com/visioncameracodescanner/VisionCameraCodeScannerPlugin.java
+++ b/node_modules/vision-camera-code-scanner/android/src/main/java/com/visioncameracodescanner/VisionCameraCodeScannerPlugin.java
@@ -24,7 +24,7 @@ import androidx.camera.core.ImageProxy;
import com.google.android.gms.tasks.Tasks;
import com.mrousavy.camera.frameprocessor.FrameProcessorPlugin;
import com.google.android.gms.tasks.Task;
-import com.google.mlkit.vision.barcode.Barcode;
+import com.google.mlkit.vision.barcode.common.Barcode;
import com.google.mlkit.vision.barcode.BarcodeScanner;
import com.google.mlkit.vision.barcode.BarcodeScanning;
import com.google.mlkit.vision.barcode.BarcodeScannerOptions;
Now, unleash patch-package
once more:
npx patch-package vision-camera-code-scanner
Great job! You’ve successfully patched the second library.
Step 4: Ensuring Patch-Package Runs Post Installation
To ensure our patches remain active whenever we run the npm install
or yarn install
command, we'll add patch-package
to the postinstall
script in our package.json
:
"scripts": {
"postinstall": "patch-package"
}
Step 5: Building the QR Code Reader
With the libraries set, we’re now ready to create our QR code reader. Generate a new file called QRReader.tsx
and add this code:
import React, { memo, useEffect, useState } from 'react';
import { runOnJS } from 'react-native-reanimated';
import { Camera, useCameraDevices, useFrameProcessor } from 'react-native-vision-camera';
import { BarcodeFormat, scanBarcodes, Barcode } from 'vision-camera-code-scanner';
import { Container } from './styles';
interface QRReaderProps {
testID?: string;
}
const QRReader: React.FC<QRReaderProps> = ({ testID }) => {
const [hasPermission, setHasPermission] = React.useState(false);
const devices = useCameraDevices();
const device = devices.back;
const [barcodes, setBarcodes] = useState<Barcode[]>([]);
useEffect(() => {
console.log('barcodes', barcodes);
}, [barcodes]);
const frameProcessor = useFrameProcessor((frame) => {
'worklet';
const detectedBarcodes = scanBarcodes(frame, [BarcodeFormat.QR_CODE]);
runOnJS(setBarcodes)(detectedBarcodes);
}, []);
React.useEffect(() => {
(async () => {
const status = await Camera.requestCameraPermission();
setHasPermission(status === 'authorized');
})();
}, []);
return (
<Container testID={testID}>
{device && hasPermission && (
<Camera
style={{ width: '100%', height: '100%', position: 'absolute' }}
device={device}
isActive
frameProcessor={frameProcessor}
frameProcessorFps={2}
/>
)}
</Container>
);
};
export { QRReader };
export default memo(QRReader);
QRReader.defaultProps = {
testID: 'qrreader-testID',
};
This will give you a powerful QR reader that uses the back camera of your device to detect QR codes and returns its findings through console logs.
And there you have it! You’ve not only figured out how to patch your libraries in a React-Native project but also created an amazing QR code reader. But remember, patching is a temporary fix. It’s always good practice to contribute back to the open-source community by sharing your patches and improvements through a pull request. Once your changes are merged and a new version is released, you can switch to that instead of using the patch.
Here’s wishing you endless fun and success with your new QR Code Reader! Enjoy decoding!