React Native login fingerprint login

Recently, I am working on the React-Native APP. The project login uses five login methods, including ordinary account password login, SMS login, gesture login, fingerprint login and face recognition login. Therefore, I plan to make a collection of login methods. This is a fingerprint login, through the mobile phone to call the fingerprint sensor to obtain the user’s fingerprint and verify, verify successful automatic login.

First show us the results we finally achieved, after all, there is no picture, there is no truth, below is the real machine record screen GIF:

Analyze the function points shown in GIF:

1. Click the operation option to pop up the fingerprint recognition interface, and click Cancel/cancel fingerprint recognition in the upper blank area

2. When switching to other login methods, you can still call “More operations” to evoke fingerprint recognition

After analyzing the function points, we can see that we now need a fingerprint recognition component that can be invoked/toggle by manipulating pop-up items. For the operation item component, we can choose antD-Mobile-Rn’s “ActionSheet” component, and the fingerprint recognition component uses “React-native fingerprint-scanner”. There are 642 stars on Github, which must be trustworthy. Attach a component address https://github.com/hieuvp/react-native-fingerprint-scanner. (Many words, the simulator does not have the function of fingerprint recognition, please use the real machine to debug).

Then follow the document operation, download, run demo, as expected, there are problems.

The official demo uses the pre-Act16 class notation and is a bit vague about where the fingerprint recognition is invoked/hidden, so we need to comb it out and rewrite it with the new functional component notation.

The process of fingerprint identification should be as follows:

1. Check whether the device supports fingerprint identification

2. Determine whether the Android API is lower than 23, because Android 6.0 officially supports the API interface of fingerprint recognition, so if the Android API is <23, we need to adapt the phones of earlier versions

3, components from fingerprint “react – native – fingerprint – scanner” into “FingerprintScanner”, call FingerprintScanner. Authenticate method to arouse the fingerprint module

4. Click Cancel/hide the fingerprint component in the upper space

5. The fingerprint identification succeeds in writing corresponding events, such as login events

According to the FingerPrint identification process, we wrote the FingerPrint component under FingerPrint/index. TSX and annotated the key codes:

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("Access fingerprint component"); // Check whether the device supports fingerprint identification detectFingerprintAvailable(); // Check whether the Android API is <23, and use the standard fingerprint unlock API later than this version; Use a compatible version later than this version if (requiresLegacyAuthentication()) {  authLegacy();  } else {  authCurrent();  }   return() = > { console.log("Leave fingerprint component"); // Component uninstalls, stops fingerprint listening fingerprint scanner and releases internal cache FingerprintScanner.release();  }  }, [])  )  // Check the Android version function requiresLegacyAuthentication() {  return Platform.Version < 23;  }  // The control fingerprint component disappears const handleFingerprintDismissed = () => {  setFingerPrint({ . fingerPrint, popupShowed: false  });  }; // Check whether the phone supports fingerprint recognition const detectFingerprintAvailable = () => {  FingerprintScanner  .isSensorAvailable()  .catch(error => {  Alert.alert("Your device does not support fingerprint identification, please choose another login method.")  setFingerPrint({ . fingerPrint, errorMessage: error.message,  biometric: error.biometric,  popupShowed: false. })  });  } // Call authCurrent when Android API>23 const authCurrent = () => {  FingerprintScanner  .authenticate({title: 'Fingerprint Login', cancelButton: 'cancel'})  .then(() = > {// Leave the page popupShowed asfalse  handleFingerprintDismissed(); // Events after successful fingerprint verification, such as login successVerify();  })  .catch(() => { // Set popupShowed as after clicking Cancel or the upper blank area to hide componentsfalse // Here is the key to control the fingerprint component switch show/hide! handleFingerprintDismissed();  })  }  // Events after successful fingerprint verification, such as login const successVerify = () => {  dispatch({  type: 'user/login'. payload: {  username: "Zhang". password: '123456'. }  });   } // Android API<23 to call the fingerprint component compatible writing const authLegacy = () => {  FingerprintScanner  .authenticate({onAttempt: handleAuthenticationAttemptedLegacy})  .then(() = > {// The fingerprint verification succeeded handleFingerprintDismissed();  Alert.alert('Fingerprint Authentication'.'Authentication successful');  successVerify();  })  .catch((error) => { // Fingerprint verification failed setLegacyInfo({errorMessageLegacy: error.message, biometricLegacy: error.biometric});  description.shake();  handleFingerprintDismissed();  });  }  // Callback function when the user tries to scan the fingerprint and fails const handleAuthenticationAttemptedLegacy = (error) => {  setLegacyInfo({ . LegacyInfo, errorMessageLegacy: error.message  });  description.shake();  };  // Manually write a fingerprint validation component 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}> Biometric {'\n'} Authentication </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}> return </Text>  </TouchableOpacity>   </View>  </View>  );   return() = > {// Android API>23, no need to render; Otherwise render renderLegacy components 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'. }, }); Copy the code

As you can see, android API version 23 and above does not need to render fingerprint recognition component, version 23 and below need to write a rendering component, reference a “ShakingText” component, the official website of this component, we can directly copy it. The ShakingText.com ponent. Js wrote:

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;  Copy the code

With the fingerprint component written, we need to use the “ActionSheet” component to toggle and control the display and hide of the fingerprint component. To control the display hiding of the fingerprint component we use the variable “popupShowed” to control and place it in state. We wrote under 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. })  // Set popupShowed to when clicking the fingerprint login optiontrue  const handleFingerprintShowed = () => {  setFingerPrint({ . fingerPrint, popupShowed: true  });  }   const showActionSheet = () =>{  const BUTTONS = [  'Account/SMS Login'. 'Gesture Login'. 'Fingerprint Login'. 'Face Recognition Login'. 'cancel'. ];  ActionSheet.showActionSheetWithOptions(  {  options: BUTTONS,  cancelButtonIndex: 4,  },  buttonIndex => {  const clickOption = BUTTONS[buttonIndex];  console.log('clicked: ',clickOption);  switch (clickOption){  case 'Account/SMS Login':  navigateReplace("Login");  return;  case 'Gesture Login':  navigateReplace("GestureUnlock");  return;  case 'Fingerprint Login': // Display fingerprint login handleFingerprintShowed();  return;  case 'Face Recognition Login':  navigateReplace("Login");  return;  }  }  );  }   return (  <View style={styles.container}>  <View style={styles.more}> <Text style={styles.moreText} onPress={showActionSheet}> </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'  } }); Copy the code

This completes the React-Native fingerprint login feature. In summary, the key points are:

  • Toggle fingerprint component display hiding toggles FingerprintPopup component display by controlling the true/false state of popupShowed
  • Each time the component is woken up, it determines availability and version during initialization by displaying the “FingerprintPopup” component and then invokes the component display
  • Every time a component is hidden, it goes through hidingFingerprintPopupComponent that releases the fingerprint component listener during component uninstallationFingerprintScanner.release();
  • When working with a fingerprint component, be sure to set “popupShowed” to false, whether the fingerprint is successful or the cancel button is clicked. If fingerprint identification fails, no operation is performed.