I tired a different way to implement qr code reading functionality and I want to share it with you. Since the general approach of using react-native-qrcode-scanner
, this package not updated recently or not maintained. So I went to try out this react-native-vision-camera package.
Package
yarn add react-native-vector-icons
yarn add react-native-vision-camera
Configuration
iOS
cd ios && pod install
info.plist
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) needs access to your Camera.</string>
Android
AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
gradle.properties
VisionCamera_enableCodeScanner=true
HomePage
import React, { useState } from "react";
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Dimensions,
} from "react-native";
import Ionicons from "react-native-vector-icons/Ionicons";
import QRScanner from "./qrScanner";
const dWidth = Dimensions.get("window").width;
const clr1 = "mediumseagreen";
const ScanQRPage = () => {
const [showQR, setShowQR] = useState(false);
const [qrCode, setQrCode] = useState("");
const openQRscanner = () => {
setShowQR(true);
};
const onQrRead = (qrtext) => {
setQrCode(qrtext);
setShowQR(false);
};
return (
<View style={styles.page}>
{qrCode ? (
<Text style={{ fontSize: 16, color: "black" }}>
{"QR Value \n" + qrCode}
</Text>
) : null}
<Ionicons
name={"scan-circle-outline"}
size={qrCode ? dWidth * 0.4 : dWidth * 0.75}
color={clr1}
/>
<TouchableOpacity onPress={() => openQRscanner()} style={styles.btn}>
<Text style={{ color: clr1 }}>Scan QR</Text>
</TouchableOpacity>
{showQR ? <QRScanner onRead={onQrRead} /> : null}
</View>
);
};
export default ScanQRPage;
const styles = StyleSheet.create({
page: {
flex: 1,
backgroundColor: "white",
alignItems: "center",
justifyContent: "space-evenly",
},
btn: {
backgroundColor: "transparent",
alignItems: "center",
borderRadius: 10,
paddingVertical: "3%",
width: "50%",
borderWidth: 2,
borderColor: clr1,
},
btnText: {
color: clr1,
},
});
QR Scanner / Reader Component
import React, { useState, useEffect } from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
import {
Camera,
useCameraDevice,
useCodeScanner,
} from "react-native-vision-camera";
import Ionicons from "react-native-vector-icons/Ionicons";
const QRScanner = (props) => {
const [hasPermission, setHasPermission] = useState(false);
const [refresh, setRefresh] = useState(false);
const device = useCameraDevice("back");
const codeScanner = useCodeScanner({
codeTypes: ["qr"],
onCodeScanned: (codes) => {
console.log(`onCodeScanned `, codes);
console.log(`onCodeScanned value`, codes[0].value);
props.onRead(codes[0].value);
},
});
useEffect(() => {
// exception case
setRefresh(!refresh);
}, [device, hasPermission]);
useEffect(() => {
const requestCameraPermission = async () => {
const permission = await Camera.requestCameraPermission();
console.log("Camera.requestCameraPermission ", permission);
setHasPermission(permission === "granted");
};
requestCameraPermission();
//if it is idle for 15 secs, it will be closed
setTimeout(() => {
props.onRead(null);
}, 15 * 1000);
}, []);
if (device == null || !hasPermission) {
return (
<View style={styles.page2}>
<Text style={{ backgroundColor: "white" }}>
Camera not available or not permitted
</Text>
</View>
);
}
return (
<View style={styles.page2}>
<Camera
codeScanner={codeScanner}
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
/>
<View style={styles.backHeader}>
<TouchableOpacity
style={{ padding: 10 }}
onPress={() => {
props.onRead(null);
}}
>
<Ionicons name={"arrow-back-outline"} size={25} color={"snow"} />
</TouchableOpacity>
</View>
<View style={styles.footer}>
<TouchableOpacity
style={{
paddingVertical: 8,
paddingHorizontal: 10,
borderWidth: 1,
borderRadius: 5,
borderColor: "snow",
alignItems: "center",
}}
onPress={() => {
props.onRead(null);
}}
>
<Text style={{ color: "snow", fontSize: 14 }}>Close</Text>
</TouchableOpacity>
</View>
</View>
);
};
export default QRScanner;
const styles = StyleSheet.create({
page2: {
flex: 1,
position: "absolute",
top: 0,
width: 0,
height: "100%",
width: "100%",
alignItems: "center",
justifyContent: "center",
},
backHeader: {
backgroundColor: "#00000090",
position: "absolute",
top: 0,
left: 0,
right: 0,
padding: "2%",
height: "5%",
width: "100%",
alignItems: "flex-start",
justifyContent: "center",
},
footer: {
backgroundColor: "#00000090",
position: "absolute",
bottom: 0,
left: 0,
right: 0,
padding: "10%",
height: "20%",
width: "100%",
alignItems: "center",
justifyContent: "center",
},
});
On Success
Thank you.
Source code here
Tags: #javascript, #react, #react-native, #android, #ios, #qrcode, #qrscan, #qrread, #mobile
Top comments (4)
The react-native-vision-camera package is a good open-source solution. However, if you're looking for advanced scanning functionalities, I'd recommend looking into commercial solutions. There is a significant difference in performance (speed, reliability) and developer support.
Full transparency: I work for Scanbot SDK. A colleague of mine recently wrote a barcode tutorial comparing Zxing and our own SDK. I'll link it here in case anyone is interested!
ok josh, i'll check this and give my feedback
I'm getting suck with this meanwhile midnight. Thanks for saving my life and sleeping time!
i am glad