How to build a QR and Bar Code Reader using React Native
August 05, 2021
How to build a QR and Bar Code Reader using React Native
Getting Started
Let’s start a new RN application:
react-native init BitFritScan && cd BitFritScan
Now, we’ll need to install the following libraries in order to build our app:
First Just Follow the Docs : https://www.npmjs.com/package/react-native-qrcode-scanner
If you see aNo permission handler detected error in iOS:
Try this by adding the permissions_path with Permission-Camera
ios/Podfile
platform :ios, '10.0'
target 'AwesomeProject' do
permissions_path = '../node_modules/react-native-permissions/ios'
pod 'Permission-Camera', :path => "#{permissions_path}/Camera"
config = use_native_modules!
Then update yourInfo.plist
with wanted permissions usage descriptions:
<key>NSCameraUsageDescription</key>
<string>Our app need your permission to use your camera phone</string>
Then cd ios and run pod install it will install permission
Scan.js (React Native)
import React, {useEffect, useState} from 'react';
import { AuthHeader } from '../../Componets'
import styled from 'styled-components/native';
import GlobalStyles from '../../Componets/GlobalStyles';
import QRCodeScanner from 'react-native-qrcode-scanner';
import { RNCamera } from 'react-native-camera';
import Xml2js from 'react-native-xml2js';
import { StyleSheet,Text,TouchableOpacity } from 'react-native';
const Scan = ({navigation}) => {
const [Data, SetData] = useState(null);
const onSuccess = e => {
const {type,data}=e;
if(type==="QR_CODE"){
let parser = new Xml2js.Parser();
parser.parseString(data, (err, result)=> {
console.info(result)
SetData(result)
})
}else{
console.info(e)
SetData(data)
}
}
useEffect(() => {
const onBlur = navigation.addListener('blur', () => {
SetData(null)
});
return {onBlur};
}, [navigation]);
return (
<Container style={GlobalStyles.droidSafeArea}>
<AuthHeader Title={'Scan'} navigation={navigation}/>
<ContainerMain>
{Data?
<Text style={styles.centerText}>
{JSON.stringify(Data)}
</Text>:
<QRCodeScanner
onRead={onSuccess}
reactivate={true}
flashMode={RNCamera.Constants.FlashMode.torch}
topContent={
<Text style={styles.centerText}>
Go to{' '}
<Text style={styles.textBold}>wikipedia.org/wiki/QR_code</Text> on
your computer and scan the QR code.
</Text>
}
bottomContent={
<TouchableOpacity style={styles.buttonTouchable}>
<Text style={styles.buttonText}>OK. Got it!</Text>
</TouchableOpacity>
}
/>
}
</ContainerMain>
</Container>
)
}
const styles = StyleSheet.create({
centerText: {
flex: 1,
fontSize: 18,
padding: 32,
color: '#777'
},
textBold: {
fontWeight: '500',
color: '#000'
},
buttonText: {
fontSize: 21,
color: 'rgb(0,122,255)'
},
buttonTouchable: {
padding: 16,
}
});
const Container = styled.SafeAreaView`
flex: 1;
background-color: #343434;
`;
const ContainerMain = styled.View`
flex: 1;
background-color: #ffffff;
`;
export default Scan;
Scan.js (Expo)
import React, { useState, useEffect } from "react";
import {
Text,
View,Platform,StatusBar,
StyleSheet,Alert,
TouchableOpacity,
SafeAreaView,
Linking,
} from "react-native";
import { useTheme } from "react-native-paper";
import { useNavigation,useIsFocused } from "@react-navigation/native";
import { Button } from "cscommon/lib";
import {Camera} from 'expo-camera'
const Scan = () => {
const { colors } = useTheme();
const styles = StyleSheet.create({
scroll: {
flex: 1,
backgroundColor: "white",
},
screen: {
flex: 1,
backgroundColor: "#F2F2FC",
},
saveArea: {
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
backgroundColor: colors.secondary, // '#62d1bc',
},
topBar: {
height: 50,
backgroundColor: colors.secondary, //'#62d1bc',
alignItems: "center",
justifyContent: "center",
},
topBarTitleText: {
color: "#ffffff",
fontSize: 20,
},
caption: {
height: 120,
justifyContent: "center",
alignItems: "center",
},
captionTitleText: {
color: "#121B0D",
fontSize: 16,
fontWeight: "600",
},
btn: {
width: 240,
borderRadius: 4,
backgroundColor: colors.secondary, //'#62d1bc',
paddingHorizontal: 24,
paddingVertical: 12,
marginVertical: 8,
},
btnText: {
fontSize: 18,
color: "#ffffff",
textAlign: "center",
},
rnCamera: {
flex: 1,
width: "94%",
alignSelf: "center",
},
rmCameraResult: {
justifyContent: "center",
alignItems: "center",
backgroundColor: "#eeeeee",
},
rmCameraResultText: {
fontSize: 20,
color: "#62d1bc",
},
cameraControl: {
height: 180,
justifyContent: "center",
alignItems: "center",
},
});
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const navigation = useNavigation();
const focused = useIsFocused()
const CallAlert = () => {
Alert.alert(
"QR Code",
"Please check you QR code this is not a valid QR",
[{ text: "OK", onPress: () => setScanned(false) }],
{ cancelable: false }
);
};
const openSettings = () => {
if (Platform.OS === "ios") {
Linking.openURL("app-settings:");
} else {
Linking.openSettings();
}
};
const ReqPermission = async () => {
const {status} = await Camera.requestCameraPermissionsAsync()
console.info({status})
setHasPermission(status === "granted");
};
useEffect(() => {
ReqPermission();
}, []);
const handleBarCodeScanned = (result) => {
console.info(result);
// if(!testvalid){ //USE THIS IF QR CODE IS IN VALID LIKE MISSMATCH CONFIG KEY
// CallAlert();
// return false;
// }
navigation.navigate('Login', {result});
setScanned(!scanned);
};
return (
<View style={styles.screen}>
<SafeAreaView style={styles.saveArea}>
<View style={styles.topBar}>
<Text style={styles.topBarTitleText}>SSO Login</Text>
</View>
</SafeAreaView>
<>
{hasPermission === false ? (
<TouchableOpacity style={{ margin: 15, padding: 15 }}>
<Text onPress={openSettings} style={styles.captionTitleText}>
Camera permission is denied you can press
<Text style={{color:'blue'}}> here </Text>
to enable it and retry again
</Text>
</TouchableOpacity>
) : (
<>
<View style={styles.caption}>
<Text style={styles.captionTitleText}>
Scan your QR code for login
</Text>
</View>
{focused &&
<Camera
key={scanned ? 1 : 2}
onBarCodeScanned={(result) => {
handleBarCodeScanned(result);
}}
style={styles.rnCamera}
/>
}
</>
)}
<Stack/>
{hasPermission === false ? (
<Button
style={{margin:8}}
onPress={()=>{
ReqPermission();
}}
text={'Retry Again to Scan'}
/>
):(
<Button
style={{margin:8}}
onPress={()=>{
navigation.navigate('Login')
}}
text={'Skip QR Scan'}
/>
)
}
</>
</View>
);
};
export default Scan;