Skip to content

Instantly share code, notes, and snippets.

@srolija
Last active August 1, 2022 15:51
Show Gist options
  • Save srolija/9b5b52236c73bdf88f1240ceabe54e1d to your computer and use it in GitHub Desktop.
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.
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);
}
});
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;
//
// 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