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

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

分析下gif所展示的功能點:
1,通過點擊操作選項來彈出指紋識別界面,點擊取消/上方空白處取消指紋識別
2,切換到其他登錄方式時,仍然可以調(diào)用"更多操作方式"來喚起指紋識別
經(jīng)過功能點分析,我們可以看出,現(xiàn)在需要一個指紋識別的組件,通過操作彈出項來喚起/切換指紋識別的組件。操作項組件我們可以選擇antd-mobile-rn的ActionSheet組件,指紋識別組件使用react-native-fingerprint-scanner,在github上有642個star,想必是值得信任的,附上組件地址https://github.com/hieuvp/react-native-fingerprint-scanner。(多句嘴,模擬器是沒有指紋識別的功能的,請使用真機(jī)調(diào)試)。
接下來按照文檔一通操作,下載,跑demo,不出所料有問題出現(xiàn)了。
官方demo使用的是react16之前的class寫法,并且對于喚起/隱藏指紋識別的地方寫的有些模糊,所以我們需要仔細(xì)梳理并用新的函數(shù)式組件寫法來重寫一次。
指紋識別的過程應(yīng)該如下:
1,判斷設(shè)備是否支持指紋識別
2,判斷android API是否低于23,因為android 6.0之后官方才支持了指紋識別的api接口,所以如果android API<23我們需要對低版本手機(jī)做適配
3,從指紋組件react-native-fingerprint-scanner引入FingerprintScanner,調(diào)用FingerprintScanner.authenticate方法來喚起指紋組件
4,點擊取消/上方空白處隱藏指紋組件
5,指紋識別成功寫對應(yīng)的事件,如登錄事件
按照指紋識別的流程,我們在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è)備是否支持指紋識別
detectFingerprintAvailable();
//判斷Android API是不是<23,高于此版本使用標(biāo)準(zhǔn)指紋解鎖api;低于此版本使用兼容適配版本
if (requiresLegacyAuthentication()) {
authLegacy();
} else {
authCurrent();
}
return () => {
console.log("離開指紋組件");
//組件卸載,停止指紋監(jiān)聽指紋掃描器并釋放內(nèi)部緩存
FingerprintScanner.release();
}
}, [])
)
//判斷安卓版本
function requiresLegacyAuthentication() {
return Platform.Version < 23;
}
//控制指紋組件消失
const handleFingerprintDismissed = () => {
setFingerPrint({
...fingerPrint,
popupShowed: false
});
};
//檢測手機(jī)是否支持指紋識別
const detectFingerprintAvailable = () => {
FingerprintScanner
.isSensorAvailable()
.catch(error => {
Alert.alert("您的設(shè)備不支持指紋識別,請選擇其他方式登錄")
setFingerPrint({
...fingerPrint,
errorMessage: error.message,
biometric: error.biometric,
popupShowed: false,
})
});
}
//android API>23時,調(diào)用authCurrent
const authCurrent = () => {
FingerprintScanner
.authenticate({title: '指紋登錄', cancelButton: '取消'})
.then(() => {
//離開頁面時將popupShowed置為false
handleFingerprintDismissed();
//指紋驗證成功后的事件,比如登錄
successVerify();
})
.catch(() => {
//點擊取消或上方空白區(qū)隱藏組件后,將popupShowed置為false
//這里是控制指紋組件切換顯示/隱藏的關(guān)鍵!
handleFingerprintDismissed();
})
}
//指紋驗證成功后的事件,比如登錄
const successVerify = () => {
dispatch({
type: 'user/login',
payload: {
username: "張三",
password: '123456',
}
});
}
//android API<23時調(diào)用指紋組件的兼容寫法
const authLegacy = () => {
FingerprintScanner
.authenticate({onAttempt: handleAuthenticationAttemptedLegacy})
.then(() => {
//指紋驗證成功
handleFingerprintDismissed();
Alert.alert('指紋身份驗證', '身份驗證成功');
successVerify();
})
.catch((error) => {
//指紋驗證失敗
setLegacyInfo({errorMessageLegacy: error.message, biometricLegacy: error.biometric});
description.shake();
handleFingerprintDismissed();
});
}
//當(dāng)用戶嘗試掃描指紋但失敗時的回調(diào)函數(shù)
const handleAuthenticationAttemptedLegacy = (error) => {
setLegacyInfo({
...LegacyInfo,
errorMessageLegacy: error.message
});
description.shake();
};
//手動寫一個指紋驗證的組件
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}>
生物識別{'\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時,不需要渲染;否則渲染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',
},
});
可以看出來,android API在23以上版本是不需要渲染指紋識別組件的,23以下版本需要自己手動寫一個渲染的組件,引用了一個ShakingText組件,這個組件官網(wǎng)有給,我們直接復(fù)制過來就可以,在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;
寫好了指紋組件,接下來我們需要使用ActionSheet組件來切換和控制指紋組件的顯示隱藏??刂浦讣y組件的顯示隱藏我們使用popupShowed這個變量來控制,將它放在state中。我們在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,
})
//點擊指紋登錄選項時,將popupShowed置為true
const handleFingerprintShowed = () => {
setFingerPrint({
...fingerPrint,
popupShowed: true
});
}
const showActionSheet = () =>{
const BUTTONS = [
'賬號 / 短信登錄',
'手勢登錄',
'指紋登錄',
'人臉識別登錄',
'取消',
];
ActionSheet.showActionSheetWithOptions(
{
options: BUTTONS,
cancelButtonIndex: 4,
},
buttonIndex => {
const clickOption = BUTTONS[buttonIndex];
console.log('clicked: ',clickOption);
switch (clickOption){
case '賬號 / 短信登錄':
navigateReplace("Login");
return;
case '手勢登錄':
navigateReplace("GestureUnlock");
return;
case '指紋登錄':
//顯示指紋登錄
handleFingerprintShowed();
return;
case '人臉識別登錄':
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)鍵點在于:
切換指紋組件顯示隱藏在于控制popupShowed的true/false狀態(tài)來切換FingerprintPopup組件的展示與否每次喚醒組件都要通過顯示FingerprintPopup組件,在初始化期間進(jìn)行判斷可用、版本然后調(diào)用組件展示每次隱藏組件都要通過隱藏FingerprintPopup組件,在組件卸載階段釋放指紋組件監(jiān)聽器FingerprintScanner.release();操作指紋組件時不管是指紋識別成功還是點擊取消,都一定要將popupShowed置為false;指紋識別失敗不做操作。
總結(jié)
到此這篇關(guān)于React Native登錄之指紋登錄篇的文章就介紹到這了,更多相關(guān)React Native指紋登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS中的算法與數(shù)據(jù)結(jié)構(gòu)之字典(Dictionary)實例詳解
這篇文章主要介紹了JS中的算法與數(shù)據(jù)結(jié)構(gòu)之字典(Dictionary),結(jié)合實例形式詳細(xì)分析了javascript數(shù)據(jù)結(jié)構(gòu)中字典的概念、原理、定義與常見使用方法,需要的朋友可以參考下2019-08-08
微信小程序?qū)崿F(xiàn)根據(jù)日期和時間排序功能
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)根據(jù)日期和時間排序功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08
關(guān)于二級域名下使用一級域名下的COOKIE的問題
我們通常在使用cookie的時候一般都只是局限在本站內(nèi)使用,也就是只在一個域名下使用2011-11-11

