溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

使用React Native實現(xiàn)指紋登錄的方法

發(fā)布時間:2020-11-04 15:10:32 來源:億速云 閱讀:457 作者:Leah 欄目:開發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)使用React Native實現(xiàn)指紋登錄的方法,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

具體內(nèi)容如下所示:

最近在做react-native的APP,項目登錄使用了普通賬號密碼登錄、短信登錄、手勢登陸、指紋登錄和人臉識別登錄五種方式,所以準(zhǔn)備做一個登錄方式的合集。本篇是指紋登錄篇,通過手機(jī)調(diào)用指紋傳感器來獲取用戶指紋并做校驗,校驗成功則自動登錄。

首先展示我們最后達(dá)成的成果,畢竟無圖無真相,下方是真機(jī)錄屏gif:

使用React Native實現(xiàn)指紋登錄的方法

分析下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 &#63; '#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組件來切換和控制指紋組件的顯示隱藏。控制指紋組件的顯示隱藏我們使用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 &#63; (
    <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;指紋識別失敗不做操作。

關(guān)于使用React Native實現(xiàn)指紋登錄的方法就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI