二維碼掃描已經(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掃碼的效果圖:
生成二維碼相對更簡單静盅,先來說明下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-svg
是react-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集成非常簡單累颂,按照文檔說明安裝就可以了。步驟如下:
- yarn add react-native-camera安裝
- react-native link react-native-camera
- 用Xcode打開iOS工程凛俱,找到TARGETS——>點擊target在右側(cè)找到Build Phases——>展開Link Binary With Libraries紊馏,刪掉默認(rèn)link進(jìn)來的libRNCamera,點擊+號重新搜索添加一遍蒲犬。上面link react-native-svg的時候也是這個操作步驟朱监。
- 在info.plist中添加相機(jī)使用權(quán)限”Privacy - Camera Usage Description“并寫明使用權(quán)限的用處。
Android集成
安卓端集成有點頭大原叮,react-native-camera的文檔中android的配置有點多赫编。不仔細(xì)讀清楚盲目配置容易出錯。下面是我的demo項目中g(shù)radle的配置:
- 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"
}
}
}
}
- android/gradle/wrapper/gradle-wrapper.properties中修改distributionUrl為:
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
- 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)一奋隶,不然很容易出錯擂送。
- 在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)用第三方掃碼和生成二維碼就完成了。主要用到以下庫:
- react-native-camera
- react-native-qrcode-svg
- react-native-svg
RN掃碼用react-native-camera媒佣,界面可以自己發(fā)揮定制匕累。生成二維碼用react-native-qrcode-svg和react-native-svg更可靠。