React Native登錄之指紋登錄篇的示例代碼

React Native登錄之指紋登錄篇,具體內(nèi)容如下所示:
最近在做react-native的APP,項(xiàng)目登錄使用了普通賬號(hào)密碼登錄、短信登錄、手勢(shì)登陸、指紋登錄和人臉識(shí)別登錄五種方式,所以準(zhǔn)備做一個(gè)登錄方式的合集。本篇是指紋登錄篇,通過(guò)手機(jī)調(diào)用指紋傳感器來(lái)獲取用戶指紋并做校驗(yàn),校驗(yàn)成功則自動(dòng)登錄。
首先展示我們最后達(dá)成的成果,畢竟無(wú)圖無(wú)真相,下方是真機(jī)錄屏gif:

分析下gif所展示的功能點(diǎn):
1,通過(guò)點(diǎn)擊操作選項(xiàng)來(lái)彈出指紋識(shí)別界面,點(diǎn)擊取消/上方空白處取消指紋識(shí)別
2,切換到其他登錄方式時(shí),仍然可以調(diào)用"更多操作方式"來(lái)喚起指紋識(shí)別
經(jīng)過(guò)功能點(diǎn)分析,我們可以看出,現(xiàn)在需要一個(gè)指紋識(shí)別的組件,通過(guò)操作彈出項(xiàng)來(lái)喚起/切換指紋識(shí)別的組件。操作項(xiàng)組件我們可以選擇antd-mobile-rn的ActionSheet組件,指紋識(shí)別組件使用react-native-fingerprint-scanner,在github上有642個(gè)star,想必是值得信任的,附上組件地址https://github.com/hieuvp/react-native-fingerprint-scanner。(多句嘴,模擬器是沒(méi)有指紋識(shí)別的功能的,請(qǐng)使用真機(jī)調(diào)試)。
接下來(lái)按照文檔一通操作,下載,跑demo,不出所料有問(wèn)題出現(xiàn)了。
官方demo使用的是react16之前的class寫法,并且對(duì)于喚起/隱藏指紋識(shí)別的地方寫的有些模糊,所以我們需要仔細(xì)梳理并用新的函數(shù)式組件寫法來(lái)重寫一次。
指紋識(shí)別的過(guò)程應(yīng)該如下:
1,判斷設(shè)備是否支持指紋識(shí)別
2,判斷android API是否低于23,因?yàn)閍ndroid 6.0之后官方才支持了指紋識(shí)別的api接口,所以如果android API<23我們需要對(duì)低版本手機(jī)做適配
3,從指紋組件react-native-fingerprint-scanner引入FingerprintScanner,調(diào)用FingerprintScanner.authenticate方法來(lái)喚起指紋組件
4,點(diǎn)擊取消/上方空白處隱藏指紋組件
5,指紋識(shí)別成功寫對(duì)應(yīng)的事件,如登錄事件
按照指紋識(shí)別的流程,我們?cè)?em>FingerPrint/index.tsx下寫指紋組件,關(guān)鍵代碼都寫了注釋:
import React, {Component, useState, useCallback} from 'react';
import {
Alert,
Image,
Text,
TouchableOpacity,
View,
ViewPropTypes,
Platform,
StyleSheet,
} from 'react-native';
import FingerprintScanner from 'react-native-fingerprint-scanner';
import ShakingText from './ShakingText.component';
import {connector, ModelState} from '@/models/connect';
import {useFocusEffect} from "@react-navigation/native";
interface Props extends ModelState{
fingerPrint,
setFingerPrint,
}
const FingerPrintPopup: React.FC<Props> = React.memo(props => {
let {fingerPrint, setFingerPrint,dispatch} = props;
const description = null;
const [LegacyInfo, setLegacyInfo] = useState({
errorMessageLegacy: undefined,
biometricLegacy: undefined
})
useFocusEffect(
React.useCallback(() => {
console.log("進(jìn)入指紋組件");
//判斷設(shè)備是否支持指紋識(shí)別
detectFingerprintAvailable();
//判斷Android API是不是<23,高于此版本使用標(biāo)準(zhǔn)指紋解鎖api;低于此版本使用兼容適配版本
if (requiresLegacyAuthentication()) {
authLegacy();
} else {
authCurrent();
}
return () => {
console.log("離開(kāi)指紋組件");
//組件卸載,停止指紋監(jiān)聽(tīng)指紋掃描器并釋放內(nèi)部緩存
FingerprintScanner.release();
}
}, [])
)
//判斷安卓版本
function requiresLegacyAuthentication() {
return Platform.Version < 23;
}
//控制指紋組件消失
const handleFingerprintDismissed = () => {
setFingerPrint({
...fingerPrint,
popupShowed: false
});
};
//檢測(cè)手機(jī)是否支持指紋識(shí)別
const detectFingerprintAvailable = () => {
FingerprintScanner
.isSensorAvailable()
.catch(error => {
Alert.alert("您的設(shè)備不支持指紋識(shí)別,請(qǐng)選擇其他方式登錄")
setFingerPrint({
...fingerPrint,
errorMessage: error.message,
biometric: error.biometric,
popupShowed: false,
})
});
}
//android API>23時(shí),調(diào)用authCurrent
const authCurrent = () => {
FingerprintScanner
.authenticate({title: '指紋登錄', cancelButton: '取消'})
.then(() => {
//離開(kāi)頁(yè)面時(shí)將popupShowed置為false
handleFingerprintDismissed();
//指紋驗(yàn)證成功后的事件,比如登錄
successVerify();
})
.catch(() => {
//點(diǎn)擊取消或上方空白區(qū)隱藏組件后,將popupShowed置為false
//這里是控制指紋組件切換顯示/隱藏的關(guān)鍵!
handleFingerprintDismissed();
})
}
//指紋驗(yàn)證成功后的事件,比如登錄
const successVerify = () => {
dispatch({
type: 'user/login',
payload: {
username: "張三",
password: '123456',
}
});
}
//android API<23時(shí)調(diào)用指紋組件的兼容寫法
const authLegacy = () => {
FingerprintScanner
.authenticate({onAttempt: handleAuthenticationAttemptedLegacy})
.then(() => {
//指紋驗(yàn)證成功
handleFingerprintDismissed();
Alert.alert('指紋身份驗(yàn)證', '身份驗(yàn)證成功');
successVerify();
})
.catch((error) => {
//指紋驗(yàn)證失敗
setLegacyInfo({errorMessageLegacy: error.message, biometricLegacy: error.biometric});
description.shake();
handleFingerprintDismissed();
});
}
//當(dāng)用戶嘗試掃描指紋但失敗時(shí)的回調(diào)函數(shù)
const handleAuthenticationAttemptedLegacy = (error) => {
setLegacyInfo({
...LegacyInfo,
errorMessageLegacy: error.message
});
description.shake();
};
//手動(dòng)寫一個(gè)指紋驗(yàn)證的組件
const renderLegacy = (
<View style={styles.container}>
<View style={styles.contentContainer}>
<Image
style={styles.logo}
source={require('../../../assets/login/finger_print.png')}
/>
<Text style={styles.heading}>
生物識(shí)別{'\n'}身份驗(yàn)證
</Text>
<ShakingText
ref={(instance) => {
description = instance;
}}
style={styles.description(!!LegacyInfo.errorMessageLegacy)}>
{LegacyInfo.errorMessageLegacy || `Scan your ${LegacyInfo.biometricLegacy} on the\ndevice scanner to continue`}
</ShakingText>
<TouchableOpacity
style={styles.buttonContainer}
onPress={handleFingerprintDismissed}
>
<Text style={styles.buttonText}>
返回
</Text>
</TouchableOpacity>
</View>
</View>
);
return () => {
//android API>23時(shí),不需要渲染;否則渲染renderLegacy的組件
if (requiresLegacyAuthentication()) {
return renderLegacy
}
return null;
}
})
export default connector(FingerPrintPopup);
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0, 164, 222, 0.9)',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
contentContainer: {
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#ffffff',
},
logo: {
marginVertical: 45,
},
heading: {
textAlign: 'center',
color: '#00a4de',
fontSize: 21,
},
description: (error) => {
return {
textAlign: 'center',
color: error ? '#ea3d13' : '#a5a5a5',
height: 65,
fontSize: 18,
marginVertical: 10,
marginHorizontal: 20,
}
},
buttonContainer: {
padding: 20,
},
buttonText: {
color: '#8fbc5a',
fontSize: 15,
fontWeight: 'bold',
},
});
可以看出來(lái),android API在23以上版本是不需要渲染指紋識(shí)別組件的,23以下版本需要自己手動(dòng)寫一個(gè)渲染的組件,引用了一個(gè)ShakingText組件,這個(gè)組件官網(wǎng)有給,我們直接復(fù)制過(guò)來(lái)就可以,在ShakingText.component.js寫:
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import {
Animated,
Text,
} from 'react-native';
class ShakingText extends Component {
componentWillMount() {
this.shakedValue = new Animated.Value(0);
}
get animatedStyle() {
return {
transform: [
{
translateY: this.shakedValue.interpolate({
inputRange: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
outputRange: [0, 10, -15, 12, -9, 18, -7, 10, -11, 5, 0],
}),
},
{
translateX: this.shakedValue.interpolate({
inputRange: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
outputRange: [0, 2, -3, 4, -4, 3, -3, 4, -5, 2, 0],
}),
},
],
};
}
shake = () => {
this.shakedValue.setValue(0);
Animated.spring(this.shakedValue, {
toValue: 1,
friction: 3,
tension: 10,
}).start(() => this.shakedValue.setValue(0));
};
render() {
return (
<Animated.Text
{...this.props}
style={[this.animatedStyle, this.props.style]}
/>
);
}
}
ShakingText.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
style:Text.propTypes.style,
};
export default ShakingText;
寫好了指紋組件,接下來(lái)我們需要使用ActionSheet組件來(lái)切換和控制指紋組件的顯示隱藏??刂浦讣y組件的顯示隱藏我們使用popupShowed這個(gè)變量來(lái)控制,將它放在state中。我們?cè)?code>LoginSheet/index.tsx下寫:
import React,{useState} from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {px2rem} from "@/utils/px2rem";
import {ActionSheet} from "@ant-design/react-native";
import {navigateReplace} from "@/utils/navigation";
import FingerprintPopup from "@/pages/Account/FingerPrint";
import {connector,ModelState} from '@/models/connect';
interface Props {
}
const LoginSheet: React.FC<Props> = React.memo(props => {
const {dispatch} = props;
const [fingerPrint,setFingerPrint] = useState({
errorMessage: undefined,
biometric: undefined,
popupShowed: false,
})
//點(diǎn)擊指紋登錄選項(xiàng)時(shí),將popupShowed置為true
const handleFingerprintShowed = () => {
setFingerPrint({
...fingerPrint,
popupShowed: true
});
}
const showActionSheet = () =>{
const BUTTONS = [
'賬號(hào) / 短信登錄',
'手勢(shì)登錄',
'指紋登錄',
'人臉識(shí)別登錄',
'取消',
];
ActionSheet.showActionSheetWithOptions(
{
options: BUTTONS,
cancelButtonIndex: 4,
},
buttonIndex => {
const clickOption = BUTTONS[buttonIndex];
console.log('clicked: ',clickOption);
switch (clickOption){
case '賬號(hào) / 短信登錄':
navigateReplace("Login");
return;
case '手勢(shì)登錄':
navigateReplace("GestureUnlock");
return;
case '指紋登錄':
//顯示指紋登錄
handleFingerprintShowed();
return;
case '人臉識(shí)別登錄':
navigateReplace("Login");
return;
}
}
);
}
return (
<View style={styles.container}>
<View style={styles.more}>
<Text style={styles.moreText} onPress={showActionSheet}>更多登錄方式</Text>
</View>
{fingerPrint.popupShowed ? (
<FingerprintPopup
fingerPrint={fingerPrint}
setFingerPrint={setFingerPrint}
/>
) : null}
</View>
);
})
export default connector(LoginSheet);
const styles = StyleSheet.create({
container:{
},
more:{
width:'100%',
alignItems:'center',
height:px2rem(50),
marginBottom:px2rem(30),
},
moreText:{
// color:'#a1a1a1'
}
});
這樣就完成了react-native 的指紋登錄功能,總結(jié)一下,關(guān)鍵點(diǎn)在于:
切換指紋組件顯示隱藏在于控制popupShowed的true/false狀態(tài)來(lái)切換FingerprintPopup組件的展示與否每次喚醒組件都要通過(guò)顯示FingerprintPopup組件,在初始化期間進(jìn)行判斷可用、版本然后調(diào)用組件展示每次隱藏組件都要通過(guò)隱藏FingerprintPopup組件,在組件卸載階段釋放指紋組件監(jiān)聽(tīng)器FingerprintScanner.release();操作指紋組件時(shí)不管是指紋識(shí)別成功還是點(diǎn)擊取消,都一定要將popupShowed置為false;指紋識(shí)別失敗不做操作。
總結(jié)
到此這篇關(guān)于React Native登錄之指紋登錄篇的文章就介紹到這了,更多相關(guān)React Native指紋登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- react使用mobx封裝管理用戶登錄的store示例詳解
- 淺談React-router v6 實(shí)現(xiàn)登錄驗(yàn)證流程
- 詳解對(duì)于React結(jié)合Antd的Form組件實(shí)現(xiàn)登錄功能
- React利用路由實(shí)現(xiàn)登錄界面的跳轉(zhuǎn)
- React實(shí)現(xiàn)登錄表單的示例代碼
- react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁(yè)的方法
- react-native 完整實(shí)現(xiàn)登錄功能的示例代碼
- React Native實(shí)現(xiàn)簡(jiǎn)單的登錄功能(推薦)
- 工程級(jí)?React?注冊(cè)登錄全棧級(jí)流程分析
相關(guān)文章
JS中的算法與數(shù)據(jù)結(jié)構(gòu)之字典(Dictionary)實(shí)例詳解
這篇文章主要介紹了JS中的算法與數(shù)據(jù)結(jié)構(gòu)之字典(Dictionary),結(jié)合實(shí)例形式詳細(xì)分析了javascript數(shù)據(jù)結(jié)構(gòu)中字典的概念、原理、定義與常見(jiàn)使用方法,需要的朋友可以參考下2019-08-08
微信小程序?qū)崿F(xiàn)根據(jù)日期和時(shí)間排序功能
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)根據(jù)日期和時(shí)間排序功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
關(guān)于二級(jí)域名下使用一級(jí)域名下的COOKIE的問(wèn)題
我們通常在使用cookie的時(shí)候一般都只是局限在本站內(nèi)使用,也就是只在一個(gè)域名下使用2011-11-11
用JavaScript實(shí)現(xiàn)動(dòng)畫(huà)效果的方法
大家在使用Dreamweaver中的時(shí)間線功能或以做出很有趣的動(dòng)畫(huà)效果,Dreamweaver會(huì)自動(dòng)為用戶生成特定的程序代碼,大家有沒(méi)有想過(guò)動(dòng)畫(huà)的實(shí)現(xiàn)原理呢?2013-07-07
JavaScript之移動(dòng)端H5生成圖片解決方案講解
這篇文章主要介紹了JavaScript之移動(dòng)端H5生成圖片解決方案講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08

