Last active
August 1, 2022 15:51
-
-
Save srolija/9b5b52236c73bdf88f1240ceabe54e1d to your computer and use it in GitHub Desktop.
QR Scanner in React Native - Unlike most tutorials out there this one cares about performance and therefore uses most performant packages on each platform along with validation of permissions with best UX on both platforms.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { PermissionsAndroid, Platform } from 'react-native'; | |
import BarcodeScanner, { | |
BarcodeType, | |
TorchMode, | |
PrecisionMode, | |
} from 'react-native-barcode-scanner-google'; | |
export default ({ callback, torch = false }) => ( | |
<BarcodeScanner | |
barcodeType={BarcodeType.QR_CODE} | |
onBarcodeRead={({ data }) => { callback(data); }} | |
precisionMode={PrecisionMode.RESPONSIVE} | |
style={{ flex: 1 }} | |
torchMode={torch ? TorchMode.ON : TorchMode.OFF} | |
/> | |
); | |
export const checkPermission = () => new Promise((resolve) => { | |
// Android 6.0+ (SDK 23+) | |
if (Platform.OS === 'android' && Platform.Version >= 23) { | |
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA, { | |
title: 'Camera required', | |
message: 'We need access in order to scan QR codes.', | |
}).then((granted) => { | |
if (granted === PermissionsAndroid.RESULTS.GRANTED) { | |
resolve(true); | |
} else { | |
resolve(false); | |
} | |
}); | |
} | |
// Older Android devices | |
else { | |
resolve(true); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import Camera from 'react-native-camera'; | |
export default ({ callback, torch = false }) => ( | |
<Camera | |
onBarCodeRead={(code) => { callback(code.data); }} | |
barCodeTypes={[Camera.constants.BarCodeType.qr]} | |
torchMode={torch ? Camera.constants.TorchMode.on : Camera.constants.TorchMode.off} | |
keepAwake | |
style={{ flex: 1 }} | |
/> | |
); | |
export const checkPermission = Camera.checkVideoAuthorizationStatus; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Example real-life usage of QR code scanner in react-native. | |
// | |
// Dependencies: | |
// react-native-camera - for iSO native QR reading | |
// https://github.com/ekreutz/react-native-barcode-scanner-google - for Android scanning using Google Vision API | |
// | |
// This example assumes that following PR is merged (or that branch is used) | |
// in order to support torch and for scanning preview to look smooth. | |
// https://github.com/ekreutz/react-native-barcode-scanner-google/pull/7 | |
// | |
// In order to get PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA, cb) | |
// working it is expected that android/build.gradle targetSdkVersion is set to 23 | |
// (on lower devices) API returns always true so we cannot validate permission. | |
// As described here: https://github.com/facebook/react-native/issues/13097 | |
// | |
import React, { Component } from 'react'; | |
import { StyleSheet, View, Text, Button, Platform, Linking } from 'react-native'; | |
import Camera, { checkPermission } from './camera'; | |
const style = StyleSheet.create({ | |
mainContainer: { | |
flex: 1, | |
}, | |
cameraPreview: { | |
flex: 1, | |
}, | |
absoluteContainer: { | |
position: 'absolute', | |
top: 0, | |
bottom: 0, | |
left: 0, | |
right: 0, | |
alignContent: 'flex-end', | |
}, | |
}); | |
class CameraScene extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
permissionLoaded: false, | |
permissionStatus: false, | |
}; | |
} | |
componentDidMount() { | |
checkPermission().then((status) => { | |
this.setState({ | |
permissionLoaded: true, | |
permissionStatus: status, | |
}); | |
}); | |
} | |
render() { | |
// Permission status unknown | |
if (!this.state.permissionLoaded) { | |
return ( | |
<View> | |
<Text>Waiting on permissions...</Text> | |
</View> | |
); | |
} | |
// Permission denied | |
if (!this.state.permissionStatus) { | |
if (Platform.OS === 'ios') { | |
return ( | |
<View style={style.container}> | |
<Text> | |
Permission denied, but you are on iOS so you can open app settings to enable it. | |
</Text> | |
<Button | |
onPress={() => { | |
Linking.openURL('app-settings:'); | |
}} | |
title="Setting" | |
/> | |
</View> | |
); | |
} | |
return ( | |
<Text> | |
Permission denied, but you are on Android so you need to manually go to Setting to enable it. | |
</Text> | |
); | |
} | |
// Allowed camera, button is on overlay that is absolutely positioned. | |
return ( | |
<View style={style.mainContainer}> | |
<Camera | |
callback={(code) => { | |
console.log(code); | |
}} | |
torch={this.state.torch} | |
/> | |
<View style={style.absoluteContainer}> | |
<Button onPress={() => this.setState({ torch: !this.state.torch })} title="[FLASH]" /> | |
</View> | |
</View> | |
); | |
} | |
} | |
export default CameraScene; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment