├── .gitattributes
├── .gitignore
├── README.md
├── android
├── build.gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── toyberman
│ └── fingerprintChange
│ ├── RNFingerprintChangeModule.java
│ └── RNFingerprintChangePackage.java
├── index.js
├── ios
├── RNFingerprintChange.podspec
├── RNFingerprintChange.xcodeproj
│ └── project.pbxproj
├── RNFingerprintChange.xcworkspace
│ └── contents.xcworkspacedata
└── RNFingerprintChange
│ ├── RNFingerprintChange.h
│ └── RNFingerprintChange.m
└── package.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 | # node.js
7 | #
8 | node_modules/
9 | npm-debug.log
10 | yarn-error.log
11 |
12 |
13 | # Xcode
14 | #
15 | build/
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 | xcuserdata
25 | *.xccheckout
26 | *.moved-aside
27 | DerivedData
28 | *.hmap
29 | *.ipa
30 | *.xcuserstate
31 | project.xcworkspace
32 |
33 |
34 | # Android/IntelliJ
35 | #
36 | build/
37 | .idea
38 | .gradle
39 | local.properties
40 | *.iml
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # react-native-fingerprint-change
3 |
4 | ## Getting started
5 |
6 | `$ npm install react-native-fingerprint-change --save`
7 |
8 | ### Mostly automatic installation
9 |
10 | `$ react-native link react-native-fingerprint-change`
11 |
12 | ### Manual installation
13 |
14 |
15 | #### iOS
16 |
17 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]`
18 | 2. Go to `node_modules` ➜ `react-native-fingerprint-change` and add `RNFingerprintChange.xcodeproj`
19 | 3. In XCode, in the project navigator, select your project. Add `libRNFingerprintChange.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
20 | 4. Run your project (`Cmd+R`)<
21 |
22 | #### Android
23 |
24 | 1. Open up `android/app/src/main/java/[...]/MainApplication.java`
25 | - Add `import com.toyberman.fingerprintChange.RNFingerprintChangePackage;` to the imports at the top of the file
26 | - Add `new RNReactNativeAccessibilityPackage()` to the list returned by the `getPackages()` method
27 | 2. Append the following lines to `android/settings.gradle`:
28 | ```
29 | include ':react-native-fingerprint-change'
30 | project(':react-native-fingerprint-change').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fingerprint-change/android')
31 | ```
32 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
33 | ```
34 | compile project(':react-native-fingerprint-change')
35 | ```
36 |
37 |
38 | ## Usage
39 | ```javascript
40 | import RNFingerprintChange from 'react-native-fingerprint-change';
41 |
42 | // How to use the module
43 | RNFingerprintChange.hasFingerPrintChanged((error, fingerprintHasChanged)=>{
44 | if(fingerprintHasChanged) {
45 | // do what you need when fingerprint change has been detected
46 | }
47 | })
48 |
49 |
50 | example:
51 |
52 | import {
53 | AppState,
54 | } from 'react-native';
55 |
56 | import RNFingerprintChange from 'react-native-fingerprint-change';
57 |
58 |
59 | class example extends Component {
60 |
61 | constructor(props) {
62 | super(props)
63 | this.state = {
64 | appState: AppState.currentState,
65 | }
66 | }
67 |
68 | componentDidMount() {
69 | AppState.addEventListener('change', this._handleAppStateChange);
70 | }
71 |
72 | componentWillUnmount() {
73 | AppState.removeEventListener('change', this._handleAppStateChange);
74 | }
75 |
76 | _handleAppStateChange = (nextAppState) => {
77 | if (this.state.appState.match(/inactive|background/) && nextAppState === 'active') {
78 | //App has come to the foreground!
79 | RNFingerprintChange.hasFingerPrintChanged((error) => {},(fingerprintHasChanged)=>{
80 | if(fingerprintHasChanged) {
81 | // do what you need
82 | }
83 | })
84 | }
85 | this.setState({appState: nextAppState});
86 | }
87 | }
88 | ```
89 |
90 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.1'
9 | }
10 | }
11 |
12 | apply plugin: 'com.android.library'
13 |
14 | android {
15 | compileSdkVersion 24
16 | buildToolsVersion "25.0.0"
17 |
18 | defaultConfig {
19 | minSdkVersion 16
20 | targetSdkVersion 22
21 | versionCode 1
22 | versionName "1.0"
23 | }
24 | lintOptions {
25 | abortOnError false
26 | }
27 | }
28 |
29 | repositories {
30 | mavenCentral()
31 | }
32 |
33 | dependencies {
34 | compile 'com.facebook.react:react-native:+'
35 | }
36 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaxToyberman/react-native-fingerprint-change/273e37fb314616e2cc65d22d64ddca08a8271aaf/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Apr 15 12:18:53 IDT 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/android/src/main/java/com/toyberman/fingerprintChange/RNFingerprintChangeModule.java:
--------------------------------------------------------------------------------
1 | package com.toyberman.fingerprintChange;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.hardware.fingerprint.FingerprintManager;
6 | import android.os.Build;
7 | import android.preference.PreferenceManager;
8 | import android.support.annotation.RequiresApi;
9 | import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;
10 |
11 | import com.facebook.react.bridge.Callback;
12 | import com.facebook.react.bridge.ReactApplicationContext;
13 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
14 | import com.facebook.react.bridge.ReactMethod;
15 |
16 | import java.lang.reflect.InvocationTargetException;
17 | import java.lang.reflect.Method;
18 | import java.util.List;
19 |
20 | public class RNFingerprintChangeModule extends ReactContextBaseJavaModule {
21 |
22 | private final ReactApplicationContext reactContext;
23 | private final String LAST_KEY_ID = "LAST_KEY_ID";
24 | private SharedPreferences spref;
25 |
26 | public RNFingerprintChangeModule(ReactApplicationContext reactContext) {
27 | super(reactContext);
28 | this.reactContext = reactContext;
29 |
30 | spref = PreferenceManager.getDefaultSharedPreferences(reactContext);
31 | }
32 |
33 | /**
34 | * Using reflection to access the fingerprint internal api.
35 | *
36 | * @param context
37 | * @return
38 | * @throws NoSuchMethodException
39 | * @throws IllegalAccessException
40 | * @throws InvocationTargetException
41 | * @throws ClassNotFoundException
42 | */
43 | @RequiresApi(api = Build.VERSION_CODES.M)
44 | private int getFingerprintInfo(Context context) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
45 | FingerprintManager fingerprintManager = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
46 | Method method = FingerprintManager.class.getDeclaredMethod("getEnrolledFingerprints");
47 | Object obj = method.invoke(fingerprintManager);
48 |
49 | int fingerprintsIdSum = 0;
50 | if (obj != null) {
51 | Class> clazz = Class.forName("android.hardware.fingerprint.Fingerprint");
52 | Method getFingerId = clazz.getDeclaredMethod("getFingerId");
53 |
54 | for (int i = 0; i < ((List) obj).size(); i++) {
55 | Object item = ((List) obj).get(i);
56 | if (item != null) {
57 | fingerprintsIdSum += (int) getFingerId.invoke(item);
58 | }
59 | }
60 |
61 | }
62 |
63 | return fingerprintsIdSum;
64 |
65 | }
66 |
67 | @RequiresApi(api = Build.VERSION_CODES.M)
68 | @ReactMethod
69 | public void hasFingerPrintChanged(Callback errorCallback, Callback successCallback) {
70 |
71 | // if no fingerprint hardware return false
72 | if (!hasFingerprintHardware(this.reactContext)) {
73 | successCallback.invoke(false);
74 | return;
75 | }
76 |
77 | try {
78 | // get current fingers id sum
79 | int fingersId = getFingerprintInfo(this.reactContext);
80 | // last saved key
81 | int lastKeyId = spref.getInt(LAST_KEY_ID, -1);
82 | if (lastKeyId != fingersId && lastKeyId!= -1) {
83 | spref.edit().putInt(LAST_KEY_ID, fingersId).apply();
84 | successCallback.invoke(true);
85 |
86 | } else {
87 | successCallback.invoke(false);
88 | }
89 | } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) {
90 | successCallback.invoke(false);
91 | }
92 | }
93 |
94 | private boolean hasFingerprintHardware(Context mContext) {
95 |
96 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
97 | //Fingerprint API only available on from Android 6.0 (M)
98 | FingerprintManager fingerprintManager = (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE);
99 |
100 | if (fingerprintManager == null) {
101 | return false;
102 | }
103 |
104 | return fingerprintManager.isHardwareDetected();
105 | } else {
106 | // Supporting devices with SDK < 23
107 | FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(getReactApplicationContext());
108 |
109 | if (fingerprintManager == null) {
110 | return false;
111 | }
112 |
113 | return fingerprintManager.isHardwareDetected();
114 | }
115 |
116 | }
117 |
118 | @Override
119 | public String getName() {
120 | return "RNFingerprintChange";
121 | }
122 |
123 | }
--------------------------------------------------------------------------------
/android/src/main/java/com/toyberman/fingerprintChange/RNFingerprintChangePackage.java:
--------------------------------------------------------------------------------
1 |
2 | package com.toyberman.fingerprintChange;
3 |
4 | import java.util.Arrays;
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.ViewManager;
12 | import com.facebook.react.bridge.JavaScriptModule;
13 | public class RNFingerprintChangePackage implements ReactPackage {
14 | @Override
15 | public List createNativeModules(ReactApplicationContext reactContext) {
16 | return Arrays.asList(new RNFingerprintChangeModule(reactContext));
17 | }
18 |
19 | // Deprecated from RN 0.47
20 | public List> createJSModules() {
21 | return Collections.emptyList();
22 | }
23 |
24 | @Override
25 | public List createViewManagers(ReactApplicationContext reactContext) {
26 | return Collections.emptyList();
27 | }
28 | }
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 |
2 | import { NativeModules } from 'react-native';
3 |
4 | const { RNFingerprintChange } = NativeModules;
5 |
6 | export default RNFingerprintChange;
7 |
--------------------------------------------------------------------------------
/ios/RNFingerprintChange.podspec:
--------------------------------------------------------------------------------
1 | require 'json'
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, '../package.json')))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = "RNFingerprintChange"
7 | s.version = package['version']
8 | s.summary = package['description']
9 |
10 | s.homepage = package['homepage']
11 | s.license = package['license']
12 | s.author = package['author']
13 | s.platform = :ios, "7.0"
14 | s.source = { :git => "https://github.com/MaxToyberman/react-native-fingerprint-change", :tag => "master" }
15 | s.source_files = "RNFingerprintChange/**/*.{h,m}"
16 | s.requires_arc = true
17 |
18 |
19 | s.dependency "React"
20 | #s.dependency "others"
21 |
22 | end
23 |
24 |
--------------------------------------------------------------------------------
/ios/RNFingerprintChange.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B3E7B58A1CC2AC0600A0062D /* RNFingerprintChange.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNFingerprintChange.m */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = "include/$(PRODUCT_NAME)";
18 | dstSubfolderSpec = 16;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 0;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | 134814201AA4EA6300B7C361 /* libRNFingerprintChange.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFingerprintChange.a; sourceTree = BUILT_PRODUCTS_DIR; };
27 | B3E7B5881CC2AC0600A0062D /* RNFingerprintChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFingerprintChange.h; sourceTree = ""; };
28 | B3E7B5891CC2AC0600A0062D /* RNFingerprintChange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFingerprintChange.m; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 58B511D81A9E6C8500147676 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 134814211AA4EA7D00B7C361 /* Products */ = {
43 | isa = PBXGroup;
44 | children = (
45 | 134814201AA4EA6300B7C361 /* libRNFingerprintChange.a */,
46 | );
47 | name = Products;
48 | sourceTree = "";
49 | };
50 | 58B511D21A9E6C8500147676 = {
51 | isa = PBXGroup;
52 | children = (
53 | B3E7B5881CC2AC0600A0062D /* RNFingerprintChange.h */,
54 | B3E7B5891CC2AC0600A0062D /* RNFingerprintChange.m */,
55 | 134814211AA4EA7D00B7C361 /* Products */,
56 | );
57 | sourceTree = "";
58 | };
59 | /* End PBXGroup section */
60 |
61 | /* Begin PBXNativeTarget section */
62 | 58B511DA1A9E6C8500147676 /* RNFingerprintChange */ = {
63 | isa = PBXNativeTarget;
64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNFingerprintChange" */;
65 | buildPhases = (
66 | 58B511D71A9E6C8500147676 /* Sources */,
67 | 58B511D81A9E6C8500147676 /* Frameworks */,
68 | 58B511D91A9E6C8500147676 /* CopyFiles */,
69 | );
70 | buildRules = (
71 | );
72 | dependencies = (
73 | );
74 | name = RNFingerprintChange;
75 | productName = RCTDataManager;
76 | productReference = 134814201AA4EA6300B7C361 /* libRNFingerprintChange.a */;
77 | productType = "com.apple.product-type.library.static";
78 | };
79 | /* End PBXNativeTarget section */
80 |
81 | /* Begin PBXProject section */
82 | 58B511D31A9E6C8500147676 /* Project object */ = {
83 | isa = PBXProject;
84 | attributes = {
85 | LastUpgradeCheck = 0830;
86 | ORGANIZATIONNAME = Facebook;
87 | TargetAttributes = {
88 | 58B511DA1A9E6C8500147676 = {
89 | CreatedOnToolsVersion = 6.1.1;
90 | };
91 | };
92 | };
93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNFingerprintChange" */;
94 | compatibilityVersion = "Xcode 3.2";
95 | developmentRegion = English;
96 | hasScannedForEncodings = 0;
97 | knownRegions = (
98 | en,
99 | );
100 | mainGroup = 58B511D21A9E6C8500147676;
101 | productRefGroup = 58B511D21A9E6C8500147676;
102 | projectDirPath = "";
103 | projectRoot = "";
104 | targets = (
105 | 58B511DA1A9E6C8500147676 /* RNFingerprintChange */,
106 | );
107 | };
108 | /* End PBXProject section */
109 |
110 | /* Begin PBXSourcesBuildPhase section */
111 | 58B511D71A9E6C8500147676 /* Sources */ = {
112 | isa = PBXSourcesBuildPhase;
113 | buildActionMask = 2147483647;
114 | files = (
115 | B3E7B58A1CC2AC0600A0062D /* RNFingerprintChange.m in Sources */,
116 | );
117 | runOnlyForDeploymentPostprocessing = 0;
118 | };
119 | /* End PBXSourcesBuildPhase section */
120 |
121 | /* Begin XCBuildConfiguration section */
122 | 58B511ED1A9E6C8500147676 /* Debug */ = {
123 | isa = XCBuildConfiguration;
124 | buildSettings = {
125 | ALWAYS_SEARCH_USER_PATHS = NO;
126 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
127 | CLANG_CXX_LIBRARY = "libc++";
128 | CLANG_ENABLE_MODULES = YES;
129 | CLANG_ENABLE_OBJC_ARC = YES;
130 | CLANG_WARN_BOOL_CONVERSION = YES;
131 | CLANG_WARN_CONSTANT_CONVERSION = YES;
132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
133 | CLANG_WARN_EMPTY_BODY = YES;
134 | CLANG_WARN_ENUM_CONVERSION = YES;
135 | CLANG_WARN_INFINITE_RECURSION = YES;
136 | CLANG_WARN_INT_CONVERSION = YES;
137 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
138 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
139 | CLANG_WARN_UNREACHABLE_CODE = YES;
140 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
141 | COPY_PHASE_STRIP = NO;
142 | ENABLE_STRICT_OBJC_MSGSEND = YES;
143 | ENABLE_TESTABILITY = YES;
144 | GCC_C_LANGUAGE_STANDARD = gnu99;
145 | GCC_DYNAMIC_NO_PIC = NO;
146 | GCC_NO_COMMON_BLOCKS = YES;
147 | GCC_OPTIMIZATION_LEVEL = 0;
148 | GCC_PREPROCESSOR_DEFINITIONS = (
149 | "DEBUG=1",
150 | "$(inherited)",
151 | );
152 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
153 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
154 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
155 | GCC_WARN_UNDECLARED_SELECTOR = YES;
156 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
157 | GCC_WARN_UNUSED_FUNCTION = YES;
158 | GCC_WARN_UNUSED_VARIABLE = YES;
159 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
160 | MTL_ENABLE_DEBUG_INFO = YES;
161 | ONLY_ACTIVE_ARCH = YES;
162 | SDKROOT = iphoneos;
163 | };
164 | name = Debug;
165 | };
166 | 58B511EE1A9E6C8500147676 /* Release */ = {
167 | isa = XCBuildConfiguration;
168 | buildSettings = {
169 | ALWAYS_SEARCH_USER_PATHS = NO;
170 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
171 | CLANG_CXX_LIBRARY = "libc++";
172 | CLANG_ENABLE_MODULES = YES;
173 | CLANG_ENABLE_OBJC_ARC = YES;
174 | CLANG_WARN_BOOL_CONVERSION = YES;
175 | CLANG_WARN_CONSTANT_CONVERSION = YES;
176 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
177 | CLANG_WARN_EMPTY_BODY = YES;
178 | CLANG_WARN_ENUM_CONVERSION = YES;
179 | CLANG_WARN_INFINITE_RECURSION = YES;
180 | CLANG_WARN_INT_CONVERSION = YES;
181 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
182 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
183 | CLANG_WARN_UNREACHABLE_CODE = YES;
184 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
185 | COPY_PHASE_STRIP = YES;
186 | ENABLE_NS_ASSERTIONS = NO;
187 | ENABLE_STRICT_OBJC_MSGSEND = YES;
188 | GCC_C_LANGUAGE_STANDARD = gnu99;
189 | GCC_NO_COMMON_BLOCKS = YES;
190 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
191 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
192 | GCC_WARN_UNDECLARED_SELECTOR = YES;
193 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
194 | GCC_WARN_UNUSED_FUNCTION = YES;
195 | GCC_WARN_UNUSED_VARIABLE = YES;
196 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
197 | MTL_ENABLE_DEBUG_INFO = NO;
198 | SDKROOT = iphoneos;
199 | VALIDATE_PRODUCT = YES;
200 | };
201 | name = Release;
202 | };
203 | 58B511F01A9E6C8500147676 /* Debug */ = {
204 | isa = XCBuildConfiguration;
205 | buildSettings = {
206 | HEADER_SEARCH_PATHS = (
207 | "$(inherited)",
208 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
209 | "$(SRCROOT)/../../../React/**",
210 | "$(SRCROOT)/../../react-native/React/**",
211 | );
212 | LIBRARY_SEARCH_PATHS = "$(inherited)";
213 | OTHER_LDFLAGS = "-ObjC";
214 | PRODUCT_NAME = RNFingerprintChange;
215 | SKIP_INSTALL = YES;
216 | };
217 | name = Debug;
218 | };
219 | 58B511F11A9E6C8500147676 /* Release */ = {
220 | isa = XCBuildConfiguration;
221 | buildSettings = {
222 | HEADER_SEARCH_PATHS = (
223 | "$(inherited)",
224 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
225 | "$(SRCROOT)/../../../React/**",
226 | "$(SRCROOT)/../../react-native/React/**",
227 | );
228 | LIBRARY_SEARCH_PATHS = "$(inherited)";
229 | OTHER_LDFLAGS = "-ObjC";
230 | PRODUCT_NAME = RNFingerprintChange;
231 | SKIP_INSTALL = YES;
232 | };
233 | name = Release;
234 | };
235 | /* End XCBuildConfiguration section */
236 |
237 | /* Begin XCConfigurationList section */
238 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNFingerprintChange" */ = {
239 | isa = XCConfigurationList;
240 | buildConfigurations = (
241 | 58B511ED1A9E6C8500147676 /* Debug */,
242 | 58B511EE1A9E6C8500147676 /* Release */,
243 | );
244 | defaultConfigurationIsVisible = 0;
245 | defaultConfigurationName = Release;
246 | };
247 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNFingerprintChange" */ = {
248 | isa = XCConfigurationList;
249 | buildConfigurations = (
250 | 58B511F01A9E6C8500147676 /* Debug */,
251 | 58B511F11A9E6C8500147676 /* Release */,
252 | );
253 | defaultConfigurationIsVisible = 0;
254 | defaultConfigurationName = Release;
255 | };
256 | /* End XCConfigurationList section */
257 | };
258 | rootObject = 58B511D31A9E6C8500147676 /* Project object */;
259 | }
260 |
--------------------------------------------------------------------------------
/ios/RNFingerprintChange.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 |
3 |
5 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/RNFingerprintChange/RNFingerprintChange.h:
--------------------------------------------------------------------------------
1 |
2 | #if __has_include("RCTBridgeModule.h")
3 | #import "RCTBridgeModule.h"
4 | #else
5 | #import
6 | #endif
7 |
8 | @interface RNFingerprintChange : NSObject
9 |
10 | @end
11 |
12 |
--------------------------------------------------------------------------------
/ios/RNFingerprintChange/RNFingerprintChange.m:
--------------------------------------------------------------------------------
1 |
2 | #import "RNFingerprintChange.h"
3 | #import
4 |
5 | @implementation RNFingerprintChange
6 |
7 | - (dispatch_queue_t)methodQueue
8 | {
9 | return dispatch_get_main_queue();
10 | }
11 | RCT_EXPORT_MODULE()
12 |
13 |
14 | RCT_EXPORT_METHOD(hasFingerPrintChanged:(RCTResponseSenderBlock)errorCallback successCallback:(RCTResponseSenderBlock)successCallback)
15 | {
16 | BOOL changed = NO;
17 |
18 | LAContext *context = [[LAContext alloc] init];
19 | NSError *error = nil;
20 |
21 |
22 | if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
23 |
24 | [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:nil];
25 | NSData *domainState = [context evaluatedPolicyDomainState];
26 |
27 | // load the last domain state from touch id
28 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
29 | NSData *oldDomainState = [defaults objectForKey:@"domainTouchID"];
30 |
31 | if (oldDomainState)
32 | {
33 | // check for domain state changes
34 |
35 | if ([oldDomainState isEqual:domainState])
36 | {
37 | NSLog(@"nothing changed.");
38 | }
39 | else
40 | {
41 | changed = YES;
42 | NSLog(@"domain state was changed!");
43 | }
44 | }
45 |
46 | // save the domain state that will be loaded next time
47 | [defaults setObject:domainState forKey:@"domainTouchID"];
48 | [defaults synchronize];
49 |
50 | successCallback(@[[NSNumber numberWithBool:changed]]);
51 | }
52 | }
53 |
54 |
55 | @end
56 |
57 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-fingerprint-change",
3 | "version": "1.2.5",
4 | "description": "Detect fingerprint change (Addition or Removal of a fingerprint)",
5 | "homepage": "https://github.com/MaxToyberman/react-native-fingerprint-change#readme",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/MaxToyberman/react-native-fingerprint-change"
13 | },
14 | "keywords": [
15 | "react-native"
16 | ],
17 | "author": "Max Toyberman ",
18 | "license": "MIT",
19 | "peerDependencies": {
20 | "react-native": "^0.41.2"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------