从相机胶卷React Native解码QR码图像

时间:2017-03-11 13:57:34

标签: javascript react-native path uri qr-code

我正在尝试在我的应用中实现一项功能,用户可以从相机胶卷中选择一张照片,然后该应用就会检测到图像中的二维码。

我目前正在使用react-native-camera-roll-picker:https://github.com/jeanpan/react-native-camera-roll-picker 和react-native-qrcode-local-image:https://github.com/remobile/react-native-qrcode-local-image

问题是本地QR码图像库要求我传递本地路径,并且与react-native-camera-roll-picker提供的本机uri不兼容。我会使用另一个库来解码图像二维码,但这个图像似乎是唯一可以在iOS和Android上运行并从现有图像而不是实际相机进行扫描的库。

我也尝试过实现react-native-fetch-blob以暂时在本地保存相机胶卷图像,但这也给我带来了麻烦:https://github.com/wkh237/react-native-fetch-blob

这是我目前尝试的函数,我在react-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)
  });
})*/
}

我现在完全失去了所以任何方法或见解都会受到高度赞赏。

5 个答案:

答案 0 :(得分:1)

您可以使用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}
/>

答案 1 :(得分:1)

This answer为我解决了该问题。 创建了本机方法来隐藏路径中的uri,这是我的代码:

    @ReactMethod
    public void getRealPathFromURI(String contentUriString, Promise promise) {
        Uri contentUri = Uri.parse(contentUriString);
        Cursor cursor = null;
        try {
            String wholeID = DocumentsContract.getDocumentId(contentUri);
            String id = wholeID.split(":")[1];

            String[] column = { MediaStore.Images.Media.DATA };

            String sel = MediaStore.Images.Media._ID + "=?";

            cursor = reactContext.getContentResolver().
                    query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                            column, sel, new String[]{ id }, null);

            int columnIndex = cursor.getColumnIndex(column[0]);

            String filePath = "";
            if (cursor.moveToFirst()) {
                filePath = cursor.getString(columnIndex);
            }
            promise.resolve(filePath);
        } catch (Throwable e) {
            promise.reject(e);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

和js:

DocumentPicker.pick({ type }).then((document: DocumentPickerResponse) => {
    MyNativeModule.getRealPathFromURI(document.uri).then((path) => {
        QRCodeLocalImage.decode(path, (err, res) => {
            callback(err, { qrData: res });
        });
    });
});

答案 2 :(得分:1)

您可以只使用react-native-rn-zxing

npm i react-native-rn-zxing

然后将其链接:

react-native link react-native-rn-zxing

用法:

import RnZxing from 'react-native-rn-zxing';
 
...
// Pass the callback as a parameter
RnZxing.showQrReader(this.onBarcodeScanned);
 
...
// Define the callback function to handle data after scan
onBarcodeScanned = (data) => {
        this.setState({data: data});
};

答案 3 :(得分:0)

您可以使用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

答案 4 :(得分:0)

您可以使用rn-qr-generator

它可以检测图像中的QR码


RNQRGenerator.detect({
  uri: PATH_TO_IMAGE, // local path of the image. Can be skipped if base64 is passed.
  base64: imageBase64String, // If uri is passed this option will be skipped.
})
  .then(response => {
    const { values } = response; // Array of detected QR code values. Empty if nothing found.
  })