- Published on
QR Code Scanner in React Native
- Authors
- Name
- PatharaNor
Dependency versioning
I testing on :
- macOS
M1
- React version
18.2.0
- Android
- Build tool version
33.0.0
- NDK version
23.1.7779620
- Build tool version
- iOS
- Ruby version
2.7.6
- Cocoapods version
1.11.3
- Gem version
3.1.6
- Ruby version
Prepare environment
Common
Create React Native project :
npx react-native init AutoQRKPaySandbox
Install react-native dependencies to support camera usage and QR code scan :
cd AutoQRKPaySandbox && \
yarn add react-native-camera \
react-native-qrcode-scanner \
react-native-permissions && \
yarn
Create directory src
then move App.tsx
to src/App.tsx
. Don't forget revise import source in index.js
:
import App from './src/App'
// ...
iOS
Modify ios/Podfile
:
# ...
target 'AutoQRKPaySandbox' do
permissions_path = '../node_modules/react-native-permissions/ios'
pod 'Permission-Camera', :path => "#{permissions_path}/Camera"
pod 'react-native-camera', path: '../node_modules/react-native-camera', subspecs: [
'TextDetector',
'FaceDetectorMLKit',
'BarcodeDetectorMLKit'
]
# ...
end
Then adding key to ios/AutoQRKPaySandbox/Info.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- ... -->
<key>NSCameraUsageDescription</key>
<string>Scan QR from K-Payment sandbox</string>
<!-- Include this only if you are planning to use the camera roll -->
<key>NSPhotoLibraryUsageDescription</key>
<string>Access QR image in photo</string>
</dict>
</plist>
Then install Pods from root of the project :
cd ios && (pod install || :) && cd ..
Android
Adding uses-permission
for accessing camera, in android/app/src/main/AndroidManifest.xml
:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- ... -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- ... -->
</manifest>
With Android 7 and higher you need to add the "Vibration" permission to your AndroidManifest.xml of your project. This should be found in your android/app/src/main/AndroidManifest.xml Add the following:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- ... -->
<uses-permission android:name="android.permission.VIBRATE"/>
<!-- ... -->
</manifest>
Adding missingDimensionStrategy
for react-native-camera
to Android's defaultConfig
in android/app/build.gradle
:
// ...
android {
ndkVersion rootProject.ext.ndkVersion
compileSdkVersion rootProject.ext.compileSdkVersion
namespace "com.autoqrkpaysandbox"
defaultConfig {
// ...
missingDimensionStrategy 'react-native-camera', 'mlkit'
// ...
}
// ...
}
// ...
src/App.tsx
Adding QR scanner function to import '../ignoreWarnings'
import React, { createRef } from 'react'
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
import QRCodeScanner from 'react-native-qrcode-scanner'
import { RNCamera } from 'react-native-camera'
function App(): JSX.Element {
let scanner = createRef<QRCodeScanner>()
const onSuccess = (e) => {
let data = e.data
console.log('scanned data : ', data)
try {
// Set state for success case
} catch (err) {
// Set state for fail case
}
}
const doSomthing = () => {
// Set state
// To re-activate the scanner to re-scan
// you need to call "reactivate"
if (scanner) {
scanner.current?.reactivate()
}
}
return (
<QRCodeScanner
ref={scanner}
onRead={onSuccess}
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 onPress={doSomthing} style={styles.buttonTouchable}>
<Text style={styles.buttonText}>Do somthing</Text>
</TouchableOpacity>
}
/>
)
}
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,
},
})
export default App
After the first time you scanned QR code,
QRCodeScanner
will be stuck (not scan). You need to callreactivate()
viaref
variable to allow it scan QR code again.Ref. above script at line number 29-31
if (scanner) { scanner.current?.reactivate() }
Usage
Clear old-dependencies :
rm -rf node_modules package-lock.json Gemfile.lock yarn.lock ios/Podfile.lock android/app/build
Install dependencies :
yarn
Pods install :
cd ios && (pod install || :) && cd ..
Let's start :
yarn android
# or
# yarn ios
Issues
ViewPropTypes will be removed from React Native. Migrate to ViewPropTypes exported from 'deprecated-react-native-prop-types
Temporary solution
Create
ignoreWarnings.js
at root of the project :import { LogBox } from "react-native"; if (__DEV__) { const ignoreWarns = [ "EventEmitter.removeListener", "[fuego-swr-keys-from-collection-path]", "Setting a timer for a long period of time", "ViewPropTypes will be removed from React Native", "AsyncStorage has been extracted from react-native", "exported from 'deprecated-react-native-prop-types'.", "Non-serializable values were found in the navigation state.", "VirtualizedLists should never be nested inside plain ScrollViews", ]; const warn = console.warn; console.warn = (...arg) => { for (const warning of ignoreWarns) { if (arg[0].startsWith(warning)) { return; } } warn(...arg); }; LogBox.ignoreLogs(ignoreWarns);
In
src/App.tsx
, just import the script :// import at the very top of everything. import '../ignoreWarnings' // ...