From 13296cfab1a0052261da5fb272fd1e7a1a7ab521 Mon Sep 17 00:00:00 2001 From: Brandon Hines Date: Tue, 5 Nov 2019 16:18:30 -0600 Subject: [PATCH 01/19] updated gradle and android sdk versions --- android/build.gradle | 8 ++++---- android/gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index eb9f92d..83a5189 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,10 +2,10 @@ apply plugin: 'com.android.library' description = 'react-native-biometrics' -def DEFAULT_COMPILE_SDK_VERSION = 28 -def DEFAULT_BUILD_TOOLS_VERSION = "28.0.3" +def DEFAULT_COMPILE_SDK_VERSION = 29 +def DEFAULT_BUILD_TOOLS_VERSION = "29.0.2" def DEFAULT_MIN_SDK_VERSION = 16 -def DEFAULT_TARGET_SDK_VERSION = 28 +def DEFAULT_TARGET_SDK_VERSION = 29 buildscript { repositories { @@ -14,7 +14,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.4.2' } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index bf3de21..e0c4de3 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From e8c443f160e1ea3380fe5281e7162364c9ea4e25 Mon Sep 17 00:00:00 2001 From: Brandon Hines Date: Tue, 12 Nov 2019 22:32:20 -0600 Subject: [PATCH 02/19] refactored simple prompt to use androix biometric prompt api --- android/build.gradle | 1 + android/src/main/AndroidManifest.xml | 1 + .../rnbiometrics/ReactNativeBiometrics.java | 54 ++++++++++--------- .../rnbiometrics/SimplePromptCallback.java | 27 ++++++++++ 4 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 android/src/main/java/com/rnbiometrics/SimplePromptCallback.java diff --git a/android/build.gradle b/android/build.gradle index 83a5189..db47a99 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -37,5 +37,6 @@ repositories { } dependencies { + implementation 'androidx.biometric:biometric:1.0.0' implementation 'com.facebook.react:react-native:+' } diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 519e387..4c3f8b2 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + diff --git a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java index 8810a0b..6b8cdb7 100644 --- a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java +++ b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java @@ -6,15 +6,24 @@ import android.content.Context; import android.hardware.fingerprint.FingerprintManager; import android.os.Build; +import android.os.Handler; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.text.TextUtils; import android.util.Base64; +import androidx.annotation.NonNull; +import androidx.biometric.BiometricManager; +import androidx.biometric.BiometricPrompt; +import androidx.biometric.BiometricPrompt.AuthenticationCallback; +import androidx.biometric.BiometricPrompt.PromptInfo; +import androidx.fragment.app.FragmentActivity; + import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.UiThreadUtil; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -23,6 +32,9 @@ import java.security.PublicKey; import java.security.Signature; import java.security.spec.RSAKeyGenParameterSpec; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * Created by brandon on 4/5/18. @@ -131,13 +143,26 @@ public void createSignature(String title, String payload, Promise promise) { } @ReactMethod - public void simplePrompt(String title, Promise promise) { + public void simplePrompt(final String title, final Promise promise) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - ReactNativeBiometricsDialog dialog = new ReactNativeBiometricsDialog(); - dialog.init(title, null, getSimplePromptCallback(promise)); - Activity activity = getCurrentActivity(); - dialog.show(activity.getFragmentManager(), "fingerprint_dialog"); + UiThreadUtil.runOnUiThread( + new Runnable() { + @Override + public void run() { + AuthenticationCallback authCallback = new SimplePromptCallback(promise); + FragmentActivity fragmentActivity = (FragmentActivity) getCurrentActivity(); + Executor executor = Executors.newSingleThreadExecutor(); + BiometricPrompt biometricPrompt = new BiometricPrompt(fragmentActivity, executor, authCallback); + + PromptInfo promptInfo = new PromptInfo.Builder() + .setDeviceCredentialAllowed(false) + .setNegativeButtonText("Cancel") + .setTitle(title) + .build(); + biometricPrompt.authenticate(promptInfo); + } + }); } else { promise.reject("Cannot display biometric prompt on android versions below 6.0", "Cannot display biometric prompt on android versions below 6.0"); } @@ -236,23 +261,4 @@ public void onError() { } }; } - - protected ReactNativeBiometricsCallback getSimplePromptCallback(final Promise promise) { - return new ReactNativeBiometricsCallback() { - @Override - public void onAuthenticated(FingerprintManager.CryptoObject cryptoObject) { - promise.resolve(true); - } - - @Override - public void onCancel() { - promise.reject("User cancelled fingerprint authorization", "User cancelled fingerprint authorization"); - } - - @Override - public void onError() { - promise.reject("Error generating public private keys" , "Error generating public private keys"); - } - }; - } } diff --git a/android/src/main/java/com/rnbiometrics/SimplePromptCallback.java b/android/src/main/java/com/rnbiometrics/SimplePromptCallback.java new file mode 100644 index 0000000..a7ed20a --- /dev/null +++ b/android/src/main/java/com/rnbiometrics/SimplePromptCallback.java @@ -0,0 +1,27 @@ +package com.rnbiometrics; + +import androidx.annotation.NonNull; +import androidx.biometric.BiometricPrompt; + +import com.facebook.react.bridge.Promise; + +public class SimplePromptCallback extends BiometricPrompt.AuthenticationCallback { + private Promise promise; + + public SimplePromptCallback(Promise promise) { + super(); + this.promise = promise; + } + + @Override + public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { + super.onAuthenticationError(errorCode, errString); + this.promise.reject("Error authenticating biometrics" , "Error authenticating biometrics"); + } + + @Override + public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { + super.onAuthenticationSucceeded(result); + this.promise.resolve(true); + } +} From 1b4eb0ac88b28215a818a7f341748d8144bff990 Mon Sep 17 00:00:00 2001 From: Brandon Hines Date: Tue, 12 Nov 2019 22:56:56 -0600 Subject: [PATCH 03/19] refactored isSensorAvailable to use androix biometric manager --- .../rnbiometrics/ReactNativeBiometrics.java | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java index 6b8cdb7..e1f64d4 100644 --- a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java +++ b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java @@ -6,24 +6,24 @@ import android.content.Context; import android.hardware.fingerprint.FingerprintManager; import android.os.Build; -import android.os.Handler; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.text.TextUtils; import android.util.Base64; -import androidx.annotation.NonNull; import androidx.biometric.BiometricManager; import androidx.biometric.BiometricPrompt; import androidx.biometric.BiometricPrompt.AuthenticationCallback; import androidx.biometric.BiometricPrompt.PromptInfo; import androidx.fragment.app.FragmentActivity; +import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.bridge.WritableMap; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -33,7 +33,6 @@ import java.security.Signature; import java.security.spec.RSAKeyGenParameterSpec; import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** @@ -58,23 +57,40 @@ public void isSensorAvailable(Promise promise) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ReactApplicationContext reactApplicationContext = getReactApplicationContext(); - FingerprintManager fingerprintManager = reactApplicationContext.getSystemService(FingerprintManager.class); - Boolean isHardwareDetected = fingerprintManager.isHardwareDetected(); - Boolean hasFingerprints = fingerprintManager.hasEnrolledFingerprints(); - - KeyguardManager keyguardManager = (KeyguardManager) reactApplicationContext.getSystemService(Context.KEYGUARD_SERVICE); - Boolean hasProtectedLockscreen = keyguardManager.isKeyguardSecure(); - - if (isHardwareDetected && hasFingerprints && hasProtectedLockscreen) { - promise.resolve("TouchID"); + BiometricManager biometricManager = BiometricManager.from(reactApplicationContext); + int canAuthenticate = biometricManager.canAuthenticate(); + + if (canAuthenticate == BiometricManager.BIOMETRIC_SUCCESS) { + WritableMap resultMap = Arguments.createMap(); + resultMap.putBoolean("available", true); + resultMap.putString("biometryType", "biometrics"); + promise.resolve(resultMap); } else { - promise.resolve(null); + WritableMap resultMap = Arguments.createMap(); + resultMap.putBoolean("available", false); + + switch (canAuthenticate) { + case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE: + resultMap.putString("error", "BIOMETRIC_ERROR_NO_HARDWARE"); + break; + case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE: + resultMap.putString("error", "BIOMETRIC_ERROR_HW_UNAVAILABLE"); + break; + case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED: + resultMap.putString("error", "BIOMETRIC_ERROR_NONE_ENROLLED"); + break; + } + + promise.resolve(resultMap); } } else { - promise.resolve(null); + WritableMap resultMap = Arguments.createMap(); + resultMap.putBoolean("available", false); + resultMap.putString("error", "UNSUPPORTED_ANDROID_VERSION"); + promise.resolve(resultMap); } } catch (Exception e) { - promise.reject("Error detecting fingerprint availability: " + e.getMessage(), "Error detecting fingerprint availability"); + promise.reject("Error detecting biometrics availability: " + e.getMessage(), "Error detecting biometrics availability"); } } From 2d45e79d15968b8335169f05644840975bfd6615 Mon Sep 17 00:00:00 2001 From: Brandon Hines Date: Tue, 12 Nov 2019 23:26:31 -0600 Subject: [PATCH 04/19] refactored create keys to always create keys without prompting for biometrics --- .../rnbiometrics/ReactNativeBiometrics.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java index e1f64d4..d9d9dab 100644 --- a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java +++ b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java @@ -98,17 +98,22 @@ public void isSensorAvailable(Promise promise) { public void createKeys(String title, Promise promise) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (TextUtils.isEmpty(title)) { - // if no title is provided for the create keys prompt, treat the action as - // authenticated and create keys - ReactNativeBiometricsCallback createKeysCallback = getCreationCallback(promise); - createKeysCallback.onAuthenticated(null); - } else { - ReactNativeBiometricsDialog dialog = new ReactNativeBiometricsDialog(); - dialog.init(title, null, getCreationCallback(promise)); - Activity activity = getCurrentActivity(); - dialog.show(activity.getFragmentManager(), "fingerprint_dialog"); - } + deleteBiometricKey(); + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); + KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(biometricKeyAlias, KeyProperties.PURPOSE_SIGN) + .setDigests(KeyProperties.DIGEST_SHA256) + .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) + .setAlgorithmParameterSpec(new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4)) + .setUserAuthenticationRequired(true) + .build(); + keyPairGenerator.initialize(keyGenParameterSpec); + + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + PublicKey publicKey = keyPair.getPublic(); + byte[] encodedPublicKey = publicKey.getEncoded(); + String publicKeyString = Base64.encodeToString(encodedPublicKey, Base64.DEFAULT); + publicKeyString = publicKeyString.replaceAll("\r", "").replaceAll("\n", ""); + promise.resolve(publicKeyString); } else { promise.reject("Cannot generate keys on android versions below 6.0", "Cannot generate keys on android versions below 6.0"); } From b77d5179d1facf13bdd46f48836428c388912d37 Mon Sep 17 00:00:00 2001 From: Brandon Hines Date: Tue, 12 Nov 2019 23:29:24 -0600 Subject: [PATCH 05/19] refactored createSignature to use the androidx biometric prompt api --- .../rnbiometrics/CreateSignatureCallback.java | 44 +++++ .../rnbiometrics/ReactNativeBiometrics.java | 152 ++++++------------ 2 files changed, 89 insertions(+), 107 deletions(-) create mode 100644 android/src/main/java/com/rnbiometrics/CreateSignatureCallback.java diff --git a/android/src/main/java/com/rnbiometrics/CreateSignatureCallback.java b/android/src/main/java/com/rnbiometrics/CreateSignatureCallback.java new file mode 100644 index 0000000..18a08c0 --- /dev/null +++ b/android/src/main/java/com/rnbiometrics/CreateSignatureCallback.java @@ -0,0 +1,44 @@ +package com.rnbiometrics; + +import android.util.Base64; + +import androidx.annotation.NonNull; +import androidx.biometric.BiometricPrompt; + +import com.facebook.react.bridge.Promise; + +import java.security.Signature; + +public class CreateSignatureCallback extends BiometricPrompt.AuthenticationCallback { + private Promise promise; + private String payload; + + public CreateSignatureCallback(Promise promise, String payload) { + super(); + this.promise = promise; + this.payload = payload; + } + + @Override + public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { + super.onAuthenticationError(errorCode, errString); + this.promise.reject("Error authenticating biometrics" , "Error authenticating biometrics"); + } + + @Override + public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { + super.onAuthenticationSucceeded(result); + + try { + BiometricPrompt.CryptoObject cryptoObject = result.getCryptoObject(); + Signature cryptoSignature = cryptoObject.getSignature(); + cryptoSignature.update(this.payload.getBytes()); + byte[] signed = cryptoSignature.sign(); + String signedString = Base64.encodeToString(signed, Base64.DEFAULT); + signedString = signedString.replaceAll("\r", "").replaceAll("\n", ""); + promise.resolve(signedString); + } catch (Exception e) { + promise.reject("Error creating signature: " + e.getMessage(), "Error creating signature"); + } + } +} diff --git a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java index d9d9dab..879b40d 100644 --- a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java +++ b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java @@ -1,14 +1,8 @@ package com.rnbiometrics; -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.KeyguardManager; -import android.content.Context; -import android.hardware.fingerprint.FingerprintManager; import android.os.Build; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; -import android.text.TextUtils; import android.util.Base64; import androidx.biometric.BiometricManager; @@ -138,39 +132,51 @@ public void deleteKeys(Promise promise) { } @ReactMethod - public void createSignature(String title, String payload, Promise promise) { - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - Signature signature = Signature.getInstance("SHA256withRSA"); - KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); - keyStore.load(null); - - PrivateKey privateKey = (PrivateKey) keyStore.getKey(biometricKeyAlias, null); - signature.initSign(privateKey); - - FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(signature); - - ReactNativeBiometricsDialog dialog = new ReactNativeBiometricsDialog(); - dialog.init(title, cryptoObject, getSignatureCallback(payload, promise)); + public void createSignature(final String title, final String payload, final Promise promise) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + UiThreadUtil.runOnUiThread( + new Runnable() { + @Override + public void run() { + try { + Signature signature = Signature.getInstance("SHA256withRSA"); + KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + + PrivateKey privateKey = (PrivateKey) keyStore.getKey(biometricKeyAlias, null); + signature.initSign(privateKey); + + BiometricPrompt.CryptoObject cryptoObject = new BiometricPrompt.CryptoObject(signature); + + AuthenticationCallback authCallback = new CreateSignatureCallback(promise, payload); + FragmentActivity fragmentActivity = (FragmentActivity) getCurrentActivity(); + Executor executor = Executors.newSingleThreadExecutor(); + BiometricPrompt biometricPrompt = new BiometricPrompt(fragmentActivity, executor, authCallback); - Activity activity = getCurrentActivity(); - dialog.show(activity.getFragmentManager(), "fingerprint_dialog"); - } else { - promise.reject("Cannot generate keys on android versions below 6.0", "Cannot generate keys on android versions below 6.0"); - } - } catch (Exception e) { - promise.reject("Error signing payload: " + e.getMessage(), "Error generating signature"); + PromptInfo promptInfo = new PromptInfo.Builder() + .setDeviceCredentialAllowed(false) + .setNegativeButtonText("Cancel") + .setTitle(title) + .build(); + biometricPrompt.authenticate(promptInfo, cryptoObject); + } catch (Exception e) { + promise.reject("Error signing payload: " + e.getMessage(), "Error generating signature"); + } + } + }); + } else { + promise.reject("Cannot generate keys on android versions below 6.0", "Cannot generate keys on android versions below 6.0"); } } @ReactMethod public void simplePrompt(final String title, final Promise promise) { - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + UiThreadUtil.runOnUiThread( + new Runnable() { + @Override + public void run() { + try { AuthenticationCallback authCallback = new SimplePromptCallback(promise); FragmentActivity fragmentActivity = (FragmentActivity) getCurrentActivity(); Executor executor = Executors.newSingleThreadExecutor(); @@ -182,13 +188,13 @@ public void run() { .setTitle(title) .build(); biometricPrompt.authenticate(promptInfo); + } catch (Exception e) { + promise.reject("Error displaying local biometric prompt: " + e.getMessage(), "Error displaying local biometric prompt"); } - }); - } else { - promise.reject("Cannot display biometric prompt on android versions below 6.0", "Cannot display biometric prompt on android versions below 6.0"); - } - } catch (Exception e) { - promise.reject("Error displaying local biometric prompt: " + e.getMessage(), "Error displaying local biometric prompt"); + } + }); + } else { + promise.reject("Cannot display biometric prompt on android versions below 6.0", "Cannot display biometric prompt on android versions below 6.0"); } } @@ -214,72 +220,4 @@ protected boolean deleteBiometricKey() { return false; } } - - protected ReactNativeBiometricsCallback getSignatureCallback(final String payload, final Promise promise) { - return new ReactNativeBiometricsCallback() { - @Override - @TargetApi(Build.VERSION_CODES.M) - public void onAuthenticated(FingerprintManager.CryptoObject cryptoObject) { - try { - Signature cryptoSignature = cryptoObject.getSignature(); - cryptoSignature.update(payload.getBytes()); - byte[] signed = cryptoSignature.sign(); - String signedString = Base64.encodeToString(signed, Base64.DEFAULT); - signedString = signedString.replaceAll("\r", "").replaceAll("\n", ""); - promise.resolve(signedString); - } catch (Exception e) { - promise.reject("Error creating signature: " + e.getMessage(), "Error creating signature"); - } - } - - @Override - public void onCancel() { - promise.reject("User cancelled fingerprint authorization", "User cancelled fingerprint authorization"); - } - - @Override - public void onError() { - promise.reject("Error detecting fingerprint", "Error detecting fingerprint"); - } - }; - } - - protected ReactNativeBiometricsCallback getCreationCallback(final Promise promise) { - return new ReactNativeBiometricsCallback() { - @Override - @TargetApi(Build.VERSION_CODES.M) - public void onAuthenticated(FingerprintManager.CryptoObject cryptoObject) { - try { - deleteBiometricKey(); - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); - KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(biometricKeyAlias, KeyProperties.PURPOSE_SIGN) - .setDigests(KeyProperties.DIGEST_SHA256) - .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) - .setAlgorithmParameterSpec(new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4)) - .setUserAuthenticationRequired(true) - .build(); - keyPairGenerator.initialize(keyGenParameterSpec); - - KeyPair keyPair = keyPairGenerator.generateKeyPair(); - PublicKey publicKey = keyPair.getPublic(); - byte[] encodedPublicKey = publicKey.getEncoded(); - String publicKeyString = Base64.encodeToString(encodedPublicKey, Base64.DEFAULT); - publicKeyString = publicKeyString.replaceAll("\r", "").replaceAll("\n", ""); - promise.resolve(publicKeyString); - } catch (Exception e) { - promise.reject("Error generating public private keys: " + e.getMessage(), "Error generating public private keys"); - } - } - - @Override - public void onCancel() { - promise.reject("User cancelled fingerprint authorization", "User cancelled fingerprint authorization"); - } - - @Override - public void onError() { - promise.reject("Error generating public private keys" , "Error generating public private keys"); - } - }; - } } From 980d028d769a8a4fe879cb422a4bf79e9fa89671 Mon Sep 17 00:00:00 2001 From: Brandon Hines Date: Tue, 12 Nov 2019 23:57:47 -0600 Subject: [PATCH 06/19] deleted old UI code that is no longer used --- android/src/main/AndroidManifest.xml | 2 - .../ReactNativeBiometricsCallback.java | 16 --- .../ReactNativeBiometricsDialog.java | 117 ------------------ .../ReactNativeBiometricsHelper.java | 108 ---------------- .../src/main/res/drawable-hdpi/ic_fp_40px.png | Bin 7011 -> 0 bytes .../src/main/res/drawable-mdpi/ic_fp_40px.png | Bin 4001 -> 0 bytes .../main/res/drawable-xhdpi/ic_fp_40px.png | Bin 10524 -> 0 bytes .../main/res/drawable-xxhdpi/ic_fp_40px.png | Bin 18565 -> 0 bytes .../main/res/drawable-xxxhdpi/ic_fp_40px.png | Bin 16535 -> 0 bytes .../res/drawable/ic_fingerprint_error.xml | 28 ----- .../res/drawable/ic_fingerprint_success.xml | 28 ----- .../layout/fingerprint_dialog_container.xml | 57 --------- .../res/layout/fingerprint_dialog_content.xml | 60 --------- android/src/main/res/values/colors.xml | 6 - android/src/main/res/values/strings.xml | 7 -- android/src/main/res/values/styles.xml | 5 - 16 files changed, 434 deletions(-) delete mode 100644 android/src/main/java/com/rnbiometrics/ReactNativeBiometricsCallback.java delete mode 100644 android/src/main/java/com/rnbiometrics/ReactNativeBiometricsDialog.java delete mode 100644 android/src/main/java/com/rnbiometrics/ReactNativeBiometricsHelper.java delete mode 100644 android/src/main/res/drawable-hdpi/ic_fp_40px.png delete mode 100644 android/src/main/res/drawable-mdpi/ic_fp_40px.png delete mode 100644 android/src/main/res/drawable-xhdpi/ic_fp_40px.png delete mode 100644 android/src/main/res/drawable-xxhdpi/ic_fp_40px.png delete mode 100644 android/src/main/res/drawable-xxxhdpi/ic_fp_40px.png delete mode 100644 android/src/main/res/drawable/ic_fingerprint_error.xml delete mode 100644 android/src/main/res/drawable/ic_fingerprint_success.xml delete mode 100644 android/src/main/res/layout/fingerprint_dialog_container.xml delete mode 100644 android/src/main/res/layout/fingerprint_dialog_content.xml delete mode 100644 android/src/main/res/values/colors.xml delete mode 100644 android/src/main/res/values/strings.xml delete mode 100644 android/src/main/res/values/styles.xml diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 4c3f8b2..ed3936c 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -3,6 +3,4 @@ package="com.rnbiometrics"> - - diff --git a/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsCallback.java b/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsCallback.java deleted file mode 100644 index df01f24..0000000 --- a/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsCallback.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.rnbiometrics; - -import android.hardware.fingerprint.FingerprintManager; - -/** - * Created by brandon on 4/9/18. - */ - -public interface ReactNativeBiometricsCallback { - - void onAuthenticated(FingerprintManager.CryptoObject cryptoObject); - - void onCancel(); - - void onError(); -} diff --git a/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsDialog.java b/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsDialog.java deleted file mode 100644 index 2d161e4..0000000 --- a/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsDialog.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.rnbiometrics; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.DialogFragment; -import android.content.Context; -import android.content.DialogInterface; -import android.hardware.fingerprint.FingerprintManager; -import android.os.Build; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; - -/** - * Created by brandon on 4/6/18. - */ - -@TargetApi(Build.VERSION_CODES.M) -public class ReactNativeBiometricsDialog extends DialogFragment implements ReactNativeBiometricsCallback { - - protected String title; - protected FingerprintManager.CryptoObject cryptoObject; - protected ReactNativeBiometricsCallback biometricAuthCallback; - - protected ReactNativeBiometricsHelper biometricAuthenticationHelper; - protected Activity activity; - protected Button cancelButton; - - public void init(String title, FingerprintManager.CryptoObject cryptoObject, ReactNativeBiometricsCallback callback) { - this.title = title; - this.cryptoObject = cryptoObject; - this.biometricAuthCallback = callback; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setStyle(DialogFragment.STYLE_NORMAL, R.style.BiometricsDialog); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - getDialog().setTitle(title); - View view = inflater.inflate(R.layout.fingerprint_dialog_container, container, false); - cancelButton = (Button) view.findViewById(R.id.cancel_button); - cancelButton.setText(R.string.fingerprint_cancel); - cancelButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - dismissAllowingStateLoss(); - onCancel(); - } - }); - - biometricAuthenticationHelper = new ReactNativeBiometricsHelper( - activity.getSystemService(FingerprintManager.class), - (ImageView) view.findViewById(R.id.fingerprint_icon), - (TextView) view.findViewById(R.id.fingerprint_status), - this - ); - - return view; - } - - // DialogFragment lifecycle methods - @Override - public void onAttach(Context context) { - super.onAttach(context); - activity = getActivity(); - } - - @Override - public void onPause() { - super.onPause(); - biometricAuthenticationHelper.stopListening(); - } - - @Override - public void onResume() { - super.onResume(); - biometricAuthenticationHelper.startListening(cryptoObject); - } - - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - onCancel(); - } - - // ReactNativeBiometricsCallback methods - @Override - public void onAuthenticated(FingerprintManager.CryptoObject cryptoObject) { - dismissAllowingStateLoss(); - if (biometricAuthCallback != null) { - biometricAuthCallback.onAuthenticated(cryptoObject); - } - } - - @Override - public void onCancel() { - if (biometricAuthCallback != null) { - biometricAuthCallback.onCancel(); - } - } - - @Override - public void onError() { - dismissAllowingStateLoss(); - if (biometricAuthCallback != null) { - biometricAuthCallback.onError(); - } - } -} diff --git a/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsHelper.java b/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsHelper.java deleted file mode 100644 index d964381..0000000 --- a/android/src/main/java/com/rnbiometrics/ReactNativeBiometricsHelper.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.rnbiometrics; - -import android.annotation.TargetApi; -import android.hardware.fingerprint.FingerprintManager; -import android.os.Build; -import android.os.CancellationSignal; -import android.widget.ImageView; -import android.widget.TextView; -import com.rnbiometrics.R; - -/** - * Created by brandon on 4/5/18. - */ - -@TargetApi(Build.VERSION_CODES.M) -public class ReactNativeBiometricsHelper extends FingerprintManager.AuthenticationCallback { - - private static final long ERROR_TIMEOUT_MILLIS = 1600; - private static final long SUCCESS_DELAY_MILLIS = 1300; - - private final FingerprintManager fingerprintManager; - private final ImageView icon; - private final TextView errorTextView; - private final ReactNativeBiometricsCallback callback; - private CancellationSignal cancellationSignal; - - private boolean selfCancelled; - - ReactNativeBiometricsHelper(FingerprintManager fingerprintManager, ImageView icon, - TextView errorTextView, ReactNativeBiometricsCallback callback) { - this.fingerprintManager = fingerprintManager; - this.icon = icon; - this.errorTextView = errorTextView; - this.callback = callback; - } - - public void startListening(FingerprintManager.CryptoObject cryptoObject) { - selfCancelled = false; - - cancellationSignal = new CancellationSignal(); - fingerprintManager - .authenticate(cryptoObject, cancellationSignal, 0 /* flags */, this, null); - icon.setImageResource(R.drawable.ic_fp_40px); - } - - public void stopListening() { - if (cancellationSignal != null) { - selfCancelled = true; - cancellationSignal.cancel(); - cancellationSignal = null; - } - } - - @Override - public void onAuthenticationError(int errMsgId, CharSequence errString) { - if (!selfCancelled) { - showError(errString); - icon.postDelayed(new Runnable() { - @Override - public void run() { - callback.onError(); - } - }, ERROR_TIMEOUT_MILLIS); - } - } - - @Override - public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { - showError(helpString); - } - - @Override - public void onAuthenticationFailed() { - showError(errorTextView.getResources().getString(R.string.fingerprint_not_recognized)); - } - - @Override - public void onAuthenticationSucceeded(final FingerprintManager.AuthenticationResult result) { - errorTextView.removeCallbacks(resetErrorTextRunnable); - icon.setImageResource(R.drawable.ic_fingerprint_success); - errorTextView.setTextColor(errorTextView.getResources().getColor(R.color.success_color, null)); - errorTextView.setText(errorTextView.getResources().getString(R.string.fingerprint_recognized)); - icon.postDelayed(new Runnable() { - @Override - public void run() { - callback.onAuthenticated(result.getCryptoObject()); - } - }, SUCCESS_DELAY_MILLIS); - } - - private void showError(CharSequence error) { - icon.setImageResource(R.drawable.ic_fingerprint_error); - errorTextView.setText(error); - errorTextView.setTextColor(errorTextView.getResources().getColor(R.color.warning_color, null)); - errorTextView.removeCallbacks(resetErrorTextRunnable); - errorTextView.postDelayed(resetErrorTextRunnable, ERROR_TIMEOUT_MILLIS); - } - - private Runnable resetErrorTextRunnable = new Runnable() { - @Override - public void run() { - errorTextView.setTextColor( - errorTextView.getResources().getColor(R.color.hint_color, null)); - errorTextView.setText(errorTextView.getResources().getString(R.string.fingerprint_hint)); - icon.setImageResource(R.drawable.ic_fp_40px); - } - }; -} diff --git a/android/src/main/res/drawable-hdpi/ic_fp_40px.png b/android/src/main/res/drawable-hdpi/ic_fp_40px.png deleted file mode 100644 index 48ebd8ad737272d78d0ab9141c47c84f463fa3bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7011 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 diff --git a/android/src/main/res/drawable-mdpi/ic_fp_40px.png b/android/src/main/res/drawable-mdpi/ic_fp_40px.png deleted file mode 100644 index 122f44257b1aa188955ab01e5bf71a5f079b1da5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4001 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 diff --git a/android/src/main/res/drawable-xhdpi/ic_fp_40px.png b/android/src/main/res/drawable-xhdpi/ic_fp_40px.png deleted file mode 100644 index e1c9590bbfbcf220b08879f2f9e560a4f285f4ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10524 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 O0000 - - - - - diff --git a/android/src/main/res/drawable/ic_fingerprint_success.xml b/android/src/main/res/drawable/ic_fingerprint_success.xml deleted file mode 100644 index 261f3e7..0000000 --- a/android/src/main/res/drawable/ic_fingerprint_success.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - diff --git a/android/src/main/res/layout/fingerprint_dialog_container.xml b/android/src/main/res/layout/fingerprint_dialog_container.xml deleted file mode 100644 index bded592..0000000 --- a/android/src/main/res/layout/fingerprint_dialog_container.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - -