React Native二維碼的生成和掃描

二維碼掃描已經(jīng)是移動app中很常見的功能了,原生端實現(xiàn)掃碼是非常簡單的事,Android一般使用ZXing庫來實現(xiàn),iOS可以使用原生SDK、ZXing或ZBar的SDK來實現(xiàn)。React Native中要實現(xiàn)二維碼掃描無外乎兩種方式:

  • 原生端封裝掃碼功能組件,RN端render函數(shù)中以標(biāo)簽形式引用
  • 原生端直接實現(xiàn)所有功能,RN端直接跳轉(zhuǎn)到原生掃碼界面

第一種方式,掃碼相關(guān)的業(yè)務(wù)邏輯處理還是在RN端,第二種業(yè)務(wù)邏輯一般都在原生端,處理完畢后跳回RN頁面。既然我們工程主體是以RN為主,所以這里只說明第一種實現(xiàn)掃碼的方式,第二種方式實現(xiàn)也更簡單,熟悉原生開發(fā)的應(yīng)該都知道怎么做。

這里我使用了第三方的react-native-camera來實現(xiàn)掃碼功能。二維碼的生成則使用了react-native-qrcode-svg。下面是android和iOS掃碼的效果圖:

android.jpg

ios.png

生成二維碼相對更簡單,先來說明下RN中如何生成二維碼。

生成二維碼

之前在github上搜索了下RN生成二維碼的庫,很多人好像用的都是react-native-qrcode。我自己也嘗試了下,確實可以生成二維碼,但是生成的二維碼無法識別,無論用微信、支付寶還是任何其它有掃碼功能的app都識別不了,所以這個庫生成的二維碼是有問題的,根本不能用。

經(jīng)過搜索和實踐之后,我發(fā)現(xiàn)react-native-qrcode-svg才是RN端真正有效的二維碼生成庫。集成也非常簡單,使用npm install --save或者yarn add命令安裝react-native-qrcode-svg、react-native-svg,然后react-native link react-native-svg就行了。

react-native-svgreact-native-qrcode-svg的基礎(chǔ)庫必須安裝,由react-native-community開源,可靠性更高。集成完畢后用法如下:

<QRCode
    value={"This is a QR code string, string cannot be null"}
    size={140}
/>

需要注意的是value不能是空字符串“”或者null,否則會報錯。生成二維碼用任何掃碼功能的app掃都是可以識別的,包括本demo中的掃碼功能。具體效果可以查看demo,地址在文末。

掃描二維碼

掃描二維碼推薦使用第三方庫react-native-camera,也是react-native-community出品。這里提醒一下,RN端很多掃碼的第三方庫也是依賴于此庫的,而且有些已經(jīng)過期不再維護(hù)了,這是RN端最可靠的掃碼庫。

iOS集成
iOS集成非常簡單,按照文檔說明安裝就可以了。步驟如下:

  1. yarn add react-native-camera安裝
  2. react-native link react-native-camera
  3. 用Xcode打開iOS工程,找到TARGETS——>點擊target在右側(cè)找到Build Phases——>展開Link Binary With Libraries,刪掉默認(rèn)link進(jìn)來的libRNCamera,點擊+號重新搜索添加一遍。上面link react-native-svg的時候也是這個操作步驟。
  4. 在info.plist中添加相機(jī)使用權(quán)限”Privacy - Camera Usage Description“并寫明使用權(quán)限的用處。

Android集成
安卓端集成有點頭大,react-native-camera的文檔中android的配置有點多。不仔細(xì)讀清楚盲目配置容易出錯。下面是我的demo項目中g(shù)radle的配置:

  1. android/build/gradle配置
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        jcenter()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        maven { url "https://jitpack.io" }
        google()
    }
}

ext {
    buildToolsVersion = "26.0.3"
    minSdkVersion = 16
    compileSdkVersion = 26
    targetSdkVersion = 26
    supportLibVersion = "26.1.0"
}

subprojects {
  project.configurations.all {
     resolutionStrategy.eachDependency { details ->
       if (details.requested.group == 'com.android.support'
             && !details.requested.name.contains('multidex') ) {
          details.useVersion "26.1.0"
      }
    }
  }
}
  1. android/gradle/wrapper/gradle-wrapper.properties中修改distributionUrl為:
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
  1. android/app/build.gradle中主要配置如下(從"android {" 這行開始往下):
android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        applicationId "com.qrcode"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86"
        }
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
            def versionCodes = ["armeabi-v7a":1, "x86":2]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }
        }
    }
}

dependencies {
    compile project(':react-native-camera')
    compile project(':react-native-svg')
    compile fileTree(dir: "libs", include: ["*.jar"])
    compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    compile "com.facebook.react:react-native:+"  // From node_modules
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

gradle配置需要特別注意保持版本的統(tǒng)一,不然很容易出錯。

  1. 在AndroidManifest文件中添加權(quán)限:
<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"/>

其實這里只需要CAMERA和VIBRATE(震動)的權(quán)限就可以了,因為我們只用到了react-native-camera掃碼的功能,錄視頻和讀寫存儲的沒用到。

RN端調(diào)用掃碼

新建一個js頁面作為掃碼頁面,在render函數(shù)中渲染RNCamera組件。需要注意的是在demo中我給Android和iOS都分別指定了組件的掃碼類別type。因為我們只需要掃二維碼,所以 指定type以免其它類型的碼也被掃出來了,這個根據(jù)項目需要設(shè)置。

由于android和iOS原生實現(xiàn)方式不一樣,所以在RN中調(diào)用組件時,type的屬性名不一致,iOS中是barCodeTypes,它是一個數(shù)組,可以指定多個掃碼類型:

<RNCamera
    style={styles.preview}
    type={RNCamera.Constants.Type.back}
    barCodeTypes={[RNCamera.Constants.BarCodeType.qr]}
    flashMode={RNCamera.Constants.FlashMode.auto}
    onBarCodeRead={(e) => this.barcodeReceived(e)}
>

而android中是googleVisionBarcodeType,用于單個掃碼類型:

<RNCamera
    style={styles.preview}
    type={RNCamera.Constants.Type.back}
    googleVisionBarcodeType={RNCamera.Constants.GoogleVisionBarcodeDetection.BarcodeType.QR_CODE}
    flashMode={RNCamera.Constants.FlashMode.auto}
    onBarCodeRead={(e) => this.barcodeReceived(e)}
>

總結(jié)

至此RN調(diào)用第三方掃碼和生成二維碼就完成了。主要用到以下庫:

  1. react-native-camera
  2. react-native-qrcode-svg
  3. react-native-svg

RN掃碼用react-native-camera,界面可以自己發(fā)揮定制。生成二維碼用react-native-qrcode-svg和react-native-svg更可靠。

Demo地址:https://github.com/mrarronz/react-native-blog-examples/tree/master/Chapter12-QRCodeScanGenerate/QRCode

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容