Декодировать QR-код изображения из Camera Roll React Native

Я пытаюсь реализовать функцию в своем приложении, где пользователь может выбрать изображение из списка своих камер, и приложение будет декодировать QR-код в обнаруженном изображении.

В настоящее время я использую средство выбора реагирующей камеры: https://github.com/jeanpan/react-native-camera-roll-picker и response-native-qrcode-local-image: https://github.com/remobile/react-native-qrcode-local-image

Проблема заключается в том, что локальная библиотека изображений QR-кода требует, чтобы я пропустил локальный путь, и не совместима с нативным URI, предоставляемым реагирующим средством выбора камеры. Я бы использовал другую библиотеку для декодирования QR-кода изображения, но этот, похоже, единственный, который работает на iOS и Android и сканирует существующие изображения, а не реальную камеру.

Я также попытался реализовать response-native-fetch-blob, чтобы временно сохранить изображение с камеры, но это также доставляло мне проблемы: https://github.com/wkh237/react-native-fetch-blob

Это моя текущая попытка в функции, которую я вызываю в опоре "обратного вызова" для команды response-native-camera-roll-picker (с предыдущими попытками, закомментированными):

_pickedImage(array,currentImg) {
console.log(currentImg)
var path = RNFS.DocumentDirectoryPath + '/pickedqr';
let rnfbURI = RNFetchBlob.wrap(RNFetchBlob.fs.asset(currentImg.uri))
const Blob = RNFetchBlob.polyfill.Blob
Blob.build(rnfbURI, {type:'image/jpg'}).then((b) => {
  tmpBlob = b;
  RNFetchBlob.fs.readFile(tmpBlob, 'base64').then((data) => {
    console.log("Base64", data)
    QRDecoder.decode('data:image/gif;base64,${data}', (error, result)=>{
      console.log("Code", result)
      console.log("Error", error)
    });
  });
})
/*fullPath = currentImg.uri.replace("assets-library://", "cdvfile://localhost/assets-library/")
QRDecoder.decode(fullPath, (error, result)=>{
  console.log("Code", result)
  console.log("Error", error)
});*/
/*let blb = Blob.build( rnfbURI, { type: 'image/jpg'})
console.log(blb)*/
/*RNFetchBlob.fs.readFile(rnfbURI, 'base64').then((data) => {
  console.log("Base64", data)
  QRDecoder.decode('data:image/gif;base64,${data}', (error, result)=>{
    console.log("Code", result)
    console.log("Error", error)
  });
})*/
}

В данный момент я в полной растерянности, поэтому любые методы или понимание будут высоко оценены.

Ответ 1

Вы можете использовать react-native-qrcode-scanner для сканирования QR с изображений или непосредственно через камеру.

УСТАНОВКА:

установить зависимость с помощью этой команды:

yarn add react-native-camera react-native-qr-scanner

свяжите эти библиотеки, используя:

react-native link react-native-camera && react-native-qr-scanner

вам нужно добавить разрешение в ваш AndroidManifest.xml вашего проекта. Это должно быть найдено в вашем android/app/src/main/AndroidManifest.xml Добавьте следующее:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE"/>

В iOS 10 и выше необходимо добавить ключ "Конфиденциальность - описание использования камеры" в список info.plist вашего проекта. Это должно быть найдено в your_project/ios/your_project/Info.plist. Добавьте следующий код:

<key>NSCameraUsageDescription</key>
<string/>
<key>NSPhotoLibraryUsageDescription</key>
<string/>
<key>NSMicrophoneUsageDescription</key>
<string/>
<key>NSPhotoLibraryAddUsageDescription</key>
<string/>

Использование:

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import {QRreader} from 'react-native-qr-scanner';
import ImagePicker from 'react-native-image-picker';

export default class Scanner extends Component {
  constructor(props) {
    super(props);
    this.state = {
      reader: {
        message: null,
        data: null
      }
    };
  }
  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={()=>{
          this.openPhoto();
        }}>
          <Text style={{marginTop: 20}}>打开相册识别二维码</Text>
        </TouchableOpacity>
        <View>
        {!this.state.reader? <Text>{!this.state.reader.message?'':'${this.state.reader.message}'}</Text>: <Text>{!this.state.reader.message?'':'${this.state.reader.message}:${this.state.reader.data}'}</Text>}
        </View>
      </View>
    );
  }

  openPhoto(){
    console.log('ImagePicker');
    ImagePicker.launchImageLibrary({}, (response) => {
      console.log('Response = ', response);

      if (response.didCancel) {
        console.log('User cancelled image picker');
      }
      else if (response.error) {
        console.log('ImagePicker Error: ', response.error);
      }
      else if (response.customButton) {
        console.log('User tapped custom button: ', response.customButton);
      }
      else {
        if(response.uri){
          var path = response.path;
          if(!path){
              path = response.uri;
          }
          QRreader(path).then((data)=>{
            this.setState({reader: {
              message: '识别成功',
              data: data
            }});
            // 十秒后自动清空
            setTimeout(() => {
              this.setState({reader: {
                message: null,
                data: null
              }})
            }, 10000);
          }).catch((err)=>{
            this.setState({reader: {
              message: '识别失败',
              data: null
            }});
          });

      }
      }
    });
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff'
  }
});

вы можете узнать больше об этой библиотеке здесь: https://www.npmjs.com/package/react-native-qr-scanner

Ответ 2

Вы можете использовать react-native-camera, чтобы легко решить эту проблему.

Вот простой фрагмент кода для этого.

handleCodeDetected = (data) => {
// do whatever you want to do with data    
}

...
...

<RNCamera
  type={RNCamera.Constants.Type.back}
  barCodeTypes={[RNCamera.Constants.BarCodeType.qr]}
  onBarCodeRead={this.handleCodeDetected}
  style={styles.preview}
/>