diff --git a/.babelrc b/.babelrc
deleted file mode 100644
index d4b74b5..0000000
--- a/.babelrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "presets": ["module:metro-react-native-babel-preset"]
-}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb54f15..b6a034c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,19 @@
# Changelog
All notable changes to this project will be documented in this file.
+## [2.0.0] - 2019-11-19
+### Breaking
+- Requires React Native 0.60+ for androidx compatibility
+- All functions now take an options object and return a result object
+- `createSignature` no longer prompts user for biometrics, `simplePrompt` can be used in conjunction with it to achieve the same effect
+- `createSignature` and `simplePrompt` no longer reject on cancellation, they resolve with a success flag set to false when a user cancels a biometric prompt
+- Android no longer resolves to biometry type of `TouchID`, it only resolves to `Biometrics`
+### Changed
+- Used android BiometricPrompt API for biometrics
+- Changed library function API
+- Added better support for prompt cancellations
+- Started to return native error messages in promise rejections
+
## [1.7.0] - 2019-11-5
### Changed
- Removed dependency on android app compat library for compatibility with androidx
@@ -97,3 +110,4 @@ All notable changes to this project will be documented in this file.
[1.6.0]: https://github.com/SelfLender/react-native-biometrics/compare/1.5.2...1.6.0
[1.6.1]: https://github.com/SelfLender/react-native-biometrics/compare/1.6.0...1.6.1
[1.7.0]: https://github.com/SelfLender/react-native-biometrics/compare/1.6.1...1.7.0
+[2.0.0]: https://github.com/SelfLender/react-native-biometrics/compare/1.7.0...2.0.0
diff --git a/README.md b/README.md
index 76ecf65..d29edc6 100644
--- a/README.md
+++ b/README.md
@@ -3,50 +3,38 @@
React native biometrics is a simple bridge to native iOS and Android keystore management. It allows you to create public private key pairs that are stored in native keystores and protected by biometric authentication. Those keys can then be retrieved later, after proper authentication, and used to create a cryptographic signature.
-## Getting started
-
-`$ npm install react-native-biometrics --save`
+## React Native Compatibility
-### Automatic installation
+| `react-native-biometrics` version | Required React Native Version |
+|:---------------------------------:|:-----------------------------:|
+| `>= 2.0.0` | `>= 0.60` |
+| `<= 1.7.0` | `<= 0.59.x` |
-`$ react-native link react-native-biometrics`
+## Getting started
-### Manual installation
+using either Yarn:
+`yarn add react-native-biometrics`
-#### iOS
+or npm:
-1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]`
-2. Go to `node_modules` ➜ `react-native-biometrics` and add `ReactNativeBiometrics.xcodeproj`
-3. In XCode, in the project navigator, select your project. Add `libReactNativeBiometrics.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
-4. Run your project
+`$ npm install react-native-biometrics --save`
-#### Android
+### Link / Autolinking
-1. Open up `android/app/src/main/java/[...]/MainApplication.java`
- - Add `import com.rnbiometrics.ReactNativeBiometricsPackage;` to the imports at the top of the file
- - Add `new ReactNativeBiometricsPackage()` to the list returned by the `getPackages()` method
-2. Append the following lines to `android/settings.gradle`:
- ```
- include ':react-native-biometrics'
- project(':react-native-biometrics').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-biometrics/android')
- ```
-3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
- ```
- compile project(':react-native-biometrics')
- ```
+On React Native 0.60+ the [CLI autolink feature](https://github.com/react-native-community/cli/blob/master/docs/autolinking.md) links the module while building the app.
## Additional configuration
#### iOS
-This package requires an iOS target SDK verion of iOS 10 or higher
+This package requires an iOS target SDK version of iOS 10 or higher
-Ensure that you have the `NSFaceIDUsageDescription` entry set in your react native iOS project, or Face ID will not work properly. This description will be will be presented to the user the first time a biometrics action is taken, and the user will be asked if they want to allow the app to use Face ID. If the user declines the usage of face id for the app, the `isSensorAvailable` function will return `null` until the face id permission is specifically allowed for the app by the user.
+Ensure that you have the `NSFaceIDUsageDescription` entry set in your react native iOS project, or Face ID will not work properly. This description will be will be presented to the user the first time a biometrics action is taken, and the user will be asked if they want to allow the app to use Face ID. If the user declines the usage of face id for the app, the `isSensorAvailable` function will indicate biometrics is unavailable until the face id permission is specifically allowed for the app by the user.
#### Android
-This package requires a compiled SDK version of 23 (Android 6.0 Marshmallow) or higher
+This package requires a compiled SDK version of 29 (Android 10.0) or higher
## Usage
@@ -58,30 +46,50 @@ When a user enrolls in biometrics, a key pair is generated. The private key is
## Constants
-### TouchID
+### TouchID (iOS only)
A constant for the touch id sensor type, evaluates to `'TouchID'`
__Example__
```js
-import Biometrics from 'react-native-biometrics'
+import ReactNativeBiometrics from 'react-native-biometrics'
+
+const { biometryType } = await ReactNativeBiometrics.isSensorAvailable()
-if (biometryType === Biometrics.TouchID) {
+if (biometryType === ReactNativeBiometrics.TouchID) {
//do something fingerprint specific
}
```
-### FaceID
+### FaceID (iOS only)
A constant for the face id sensor type, evaluates to `'FaceID'`
__Example__
```js
-import Biometrics from 'react-native-biometrics'
+import ReactNativeBiometrics from 'react-native-biometrics'
-if (biometryType === Biometrics.FaceID) {
+const { biometryType } = await ReactNativeBiometrics.isSensorAvailable()
+
+if (biometryType === ReactNativeBiometrics.FaceID) {
+ //do something face id specific
+}
+```
+
+### Biometrics (Android only)
+
+A constant for generic Biometrics, evaluates to `'Biometrics'`
+
+__Example__
+
+```js
+import ReactNativeBiometrics from 'react-native-biometrics'
+
+const { biometryType } = await ReactNativeBiometrics.isSensorAvailable()
+
+if (biometryType === ReactNativeBiometrics.Biometrics) {
//do something face id specific
}
```
@@ -90,110 +98,209 @@ if (biometryType === Biometrics.FaceID) {
### isSensorAvailable()
-Detects what type of biometric sensor is available. Returns a `Promise` that resolves to a string representing the sensor type (`TouchID`, `FaceID`, `null`)
+Detects what type of biometric sensor is available. Returns a `Promise` that resolves to an object with details about biometrics availability
+
+__Result Object__
+
+| Property | Type | Description |
+| --- | --- | --- |
+| available | bool | A boolean indicating if biometrics is available or not |
+| biometryType | string | A string indicating what type of biometrics is available. `TouchID`, `FaceID`, `Biometrics`, or `undefined` if biometrics is not available. |
+| error | string | An error message indicating why biometrics may not be available. `undefined` if there is no error. |
__Example__
```js
-import Biometrics from 'react-native-biometrics'
+import ReactNativeBiometrics from 'react-native-biometrics'
-Biometrics.isSensorAvailable()
- .then((biometryType) => {
- if (biometryType === Biometrics.TouchID) {
+ReactNativeBiometrics.isSensorAvailable()
+ .then((resultObject) => {
+ const { available, biometryType } = resultObject
+
+ if (available && biometryType === ReactNativeBiometrics.TouchID) {
console.log('TouchID is supported')
- } else if (biometryType === Biometrics.FaceID) {
+ } else if (available && biometryType === ReactNativeBiometrics.FaceID) {
console.log('FaceID is supported')
+ } else if (available && biometryType === ReactNativeBiometrics.Biometrics) {
+ console.log('Biometrics is supported')
} else {
console.log('Biometrics not supported')
}
})
```
-### createKeys([promptMessage])
+### createKeys()
-Prompts the user for their fingerprint or face id, then generates a public private RSA 2048 key pair that will be stored in the device keystore. Returns a `Promise` that resolves to a base64 encoded string representing the public key.
+Generates a public private RSA 2048 key pair that will be stored in the device keystore. Returns a `Promise` that resolves to an object providing details about the keys.
-__Arguments__
+__Result Object__
-- `promptMessage` - optional string that will be displayed in the fingerprint or face id prompt, if no prompt message is provided, no prompt will be displayed.
+| Property | Type | Description |
+| --- | --- | --- |
+| publicKey | string | A base64 encoded string representing the public key |
__Example__
```js
-import Biometrics from 'react-native-biometrics'
+import ReactNativeBiometrics from 'react-native-biometrics'
-Biometrics.createKeys('Confirm fingerprint')
- .then((publicKey) => {
+ReactNativeBiometrics.createKeys('Confirm fingerprint')
+ .then((resultObject) => {
+ const { publicKey } = resultObject
console.log(publicKey)
sendPublicKeyToServer(publicKey)
})
```
+### biometricKeysExist()
+
+Detects if keys have already been generated and exist in the keystore. Returns a `Promise` that resolves to an object indicating details about the keys.
+
+__Result Object__
+
+| Property | Type | Description |
+| --- | --- | --- |
+| keysExist | bool | A boolean indicating if keys exist in the keystore |
+
+__Example__
+
+```js
+import ReactNativeBiometrics from 'react-native-biometrics'
+
+ReactNativeBiometrics.biometricKeysExist()
+ .then((resultObject) => {
+ const { keysExist } = resultObject
+
+ if (keysExist) {
+ console.log('Keys exist')
+ } else {
+ console.log('Keys do not exist or were deleted')
+ }
+ })
+```
+
### deleteKeys()
-Deletes the generated keys from the device keystore. Returns a `Promise` that resolves to `true` or `false` indicating if the deletion was successful
+Deletes the generated keys from the device keystore. Returns a `Promise` that resolves to an object indicating details about the deletion.
+
+__Result Object__
+
+| Property | Type | Description |
+| --- | --- | --- |
+| keysDeleted | bool | A boolean indicating if keys were deleted from the keystore |
__Example__
```js
-import Biometrics from 'react-native-biometrics'
+import ReactNativeBiometrics from 'react-native-biometrics'
-Biometrics.deleteKeys()
- .then((success) => {
- if (success) {
+ReactNativeBiometrics.deleteKeys()
+ .then((resultObject) => {
+ const { keysDeleted } = resultObject
+
+ if (keysDeleted) {
console.log('Successful deletion')
} else {
- console.log('Unsuccessful deletion')
+ console.log('Unsuccessful deletion because there were no keys to delete')
}
})
```
-### createSignature(promptMessage, payload)
+### createSignature(options)
-Prompts the user for their fingerprint or face id in order to retrieve the private key from the keystore, then uses the private key to generate a RSA PKCS#1v1.5 SHA 256 signature. Returns a `Promise` that resolves to a base64 encoded string representing the signature.
+Prompts the user for their fingerprint or face id in order to retrieve the private key from the keystore, then uses the private key to generate a RSA PKCS#1v1.5 SHA 256 signature. Returns a `Promise` that resolves to an object with details about the signature.
-NOTE: No biometric prompt is displayed in iOS simulators when attempting to retrieve keys for signature generation, it only occurs on actual devices.
+**NOTE: No biometric prompt is displayed in iOS simulators when attempting to retrieve keys for signature generation, it only occurs on actual devices.
-__Arguments__
+__Options Object__
-- `promptMessage` - string that will be displayed in the fingerprint or face id prompt
-- `payload` - string of data to be signed by the RSA signature
+| Parameter | Type | Description | iOS | Android |
+| --- | --- | --- | --- | --- |
+| promptMessage | string | Message that will be displayed in the fingerprint or face id prompt | ✔ | ✔ |
+| payload | string | String of data to be signed by the RSA signature | ✔ | ✔ |
+| cancelButtonText | string | Text to be displayed for the cancel button on biometric prompts, defaults to `Cancel` | ✖ | ✔ |
+
+__Result Object__
+
+| Property | Type | Description |
+| --- | --- | --- |
+| success | bool | A boolean indicating if the process was successful, `false` if the users cancels the biometrics prompt |
+| signature | string | A base64 encoded string representing the signature. `undefined` if the process was not successful. |
+| error | string | An error message indicating reasons why signature creation failed. `undefined` if there is no error. |
__Example__
```js
-import Biometrics from 'react-native-biometrics'
+import ReactNativeBiometrics from 'react-native-biometrics'
let epochTimeSeconds = Math.round((new Date()).getTime() / 1000).toString()
let payload = epochTimeSeconds + 'some message'
-Biometrics.createSignature('Sign in', payload)
- .then((signature) => {
- console.log(signature)
- verifySignatureWithServer(signature, payload)
+ReactNativeBiometrics.createSignature({
+ promptMessage: 'Sign in',
+ payload: payload
+ })
+ .then((resultObject) => {
+ const { success, signature } = resultObject
+
+ if (success) {
+ console.log(signature)
+ verifySignatureWithServer(signature, payload)
+ }
})
```
-### simplePrompt(promptMessage)
+### simplePrompt(options)
+
+Prompts the user for their fingerprint or face id. Returns a `Promise` that resolves if the user provides a valid biometrics or cancel the prompt, otherwise the promise rejects.
-Prompts the user for their fingerprint or face id. Returns a `Promise` that resolves if the user provides a valid fingerprint or face id, otherwise the promise rejects.
+**NOTE: This only validates a user's biometrics. This should not be used to log a user in or authenticate with a server, instead use `createSignature`. It should only be used to gate certain user actions within an app.
-NOTE: This only validates a user's biometrics. This should not be used to log a user in or authenticate with a server, instead use `createSignature`. It should only be used to gate certain user actions within an app.
+__Options Object__
-__Arguments__
+| Parameter | Type | Description | iOS | Android |
+| --- | --- | --- | --- | --- |
+| promptMessage | string | Message that will be displayed in the biometrics prompt | ✔ | ✔ |
+| cancelButtonText | string | Text to be displayed for the cancel button on biometric prompts, defaults to `Cancel` | ✖ | ✔ |
-- `promptMessage` - string that will be displayed in the fingerprint or face id prompt
+__Result Object__
+
+| Property | Type | Description |
+| --- | --- | --- |
+| success | bool | A boolean indicating if the biometric prompt succeeded, `false` if the users cancels the biometrics prompt |
+| error | string | An error message indicating why the biometric prompt failed. `undefined` if there is no error. |
__Example__
```js
-import Biometrics from 'react-native-biometrics'
+import ReactNativeBiometrics from 'react-native-biometrics'
+
+ReactNativeBiometrics.simplePrompt('Confirm fingerprint')
+ .then((resultObject) => {
+ const { success } = resultObject
-Biometrics.simplePrompt('Confirm fingerprint')
- .then(() => {
- console.log('successful fingerprint provided')
+ if (success) {
+ console.log('successful biometrics provided')
+ } else {
+ console.log('user cancelled biometric prompt')
+ }
})
.catch(() => {
- console.log('fingerprint failed or prompt was cancelled')
+ console.log('biometrics failed')
})
```
+
+### Troubleshooting
+
+- Because of this library's dependency on `androidx.biometric:biometric:1.0.0` it can cause transitive dependency resolution to change on certain version of React Native and `androidx.swiperefreshlayout` may no longer be able to be resolved. This can be fixed by adding an explicit dependency on the library in your `android/app/build.gradle`:
+
+ ```
+ dependencies {
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation "com.facebook.react:react-native:+" // From node_modules
+ implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" // temp fix
+ ...
+ }
+ ```
+
+- There is a [known issue](https://stackoverflow.com/questions/56700680/keychain-query-always-returns-errsecitemnotfound-after-upgrading-to-ios-13) on the iOS 13.x simulators where keys generated with access control flags cannot be queried and found properly. This results in key not found errors in `biometricKeysExist` and `createSignature` on those simulators. However, it works correctly on actual devices running iOS 13.
diff --git a/android/build.gradle b/android/build.gradle
index eb9f92d..db47a99 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'
}
}
@@ -37,5 +37,6 @@ repositories {
}
dependencies {
+ implementation 'androidx.biometric:biometric:1.0.0'
implementation 'com.facebook.react:react-native:+'
}
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
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 519e387..ed3936c 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -1,7 +1,6 @@
+
-
-
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..3e309f6
--- /dev/null
+++ b/android/src/main/java/com/rnbiometrics/CreateSignatureCallback.java
@@ -0,0 +1,58 @@
+package com.rnbiometrics;
+
+import android.util.Base64;
+
+import androidx.annotation.NonNull;
+import androidx.biometric.BiometricPrompt;
+
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.bridge.WritableNativeMap;
+
+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);
+ super.onAuthenticationError(errorCode, errString);
+ if (errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
+ WritableMap resultMap = new WritableNativeMap();
+ resultMap.putBoolean("success", false);
+ resultMap.putString("error", "User cancellation");
+ this.promise.resolve(resultMap);
+ } else {
+ this.promise.reject(errString.toString(), errString.toString());
+ }
+ }
+
+ @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", "");
+
+ WritableMap resultMap = new WritableNativeMap();
+ resultMap.putBoolean("success", true);
+ resultMap.putString("signature", signedString);
+ promise.resolve(resultMap);
+ } 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 8810a0b..790a373 100644
--- a/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java
+++ b/android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java
@@ -1,20 +1,24 @@
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;
+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.ReadableMap;
+import com.facebook.react.bridge.UiThreadUtil;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.bridge.WritableNativeMap;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -23,6 +27,8 @@
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.RSAKeyGenParameterSpec;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
/**
* Created by brandon on 4/5/18.
@@ -46,41 +52,66 @@ 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 = new WritableNativeMap();
+ resultMap.putBoolean("available", true);
+ resultMap.putString("biometryType", "Biometrics");
+ promise.resolve(resultMap);
} else {
- promise.resolve(null);
+ WritableMap resultMap = new WritableNativeMap();
+ 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 = new WritableNativeMap();
+ 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: " + e.getMessage());
}
}
@ReactMethod
- public void createKeys(String title, Promise promise) {
+ public void createKeys(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", "");
+
+ WritableMap resultMap = new WritableNativeMap();
+ resultMap.putString("publicKey", publicKeyString);
+ promise.resolve(resultMap);
} else {
promise.reject("Cannot generate keys on android versions below 6.0", "Cannot generate keys on android versions below 6.0");
}
@@ -91,62 +122,110 @@ public void createKeys(String title, Promise promise) {
@ReactMethod
public void deleteKeys(Promise promise) {
- if (biometricKeyExists()) {
+ if (doesBiometricKeyExist()) {
boolean deletionSuccessful = deleteBiometricKey();
if (deletionSuccessful) {
- promise.resolve(true);
+ WritableMap resultMap = new WritableNativeMap();
+ resultMap.putBoolean("keysDeleted", true);
+ promise.resolve(resultMap);
} else {
promise.reject("Error deleting biometric key from keystore", "Error deleting biometric key from keystore");
}
} else {
- promise.resolve(false);
+ WritableMap resultMap = new WritableNativeMap();
+ resultMap.putBoolean("keysDeleted", false);
+ promise.resolve(resultMap);
}
}
@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 ReadableMap params, final Promise promise) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ UiThreadUtil.runOnUiThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ String cancelButtomText = params.getString("cancelButtonText");
+ String promptMessage = params.getString("promptMessage");
+ String payload = params.getString("payload");
+
+ 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);
+
+ PromptInfo promptInfo = new PromptInfo.Builder()
+ .setDeviceCredentialAllowed(false)
+ .setNegativeButtonText(cancelButtomText)
+ .setTitle(promptMessage)
+ .build();
+ biometricPrompt.authenticate(promptInfo, cryptoObject);
+ } catch (Exception e) {
+ promise.reject("Error signing payload: " + e.getMessage(), "Error generating signature: " + e.getMessage());
+ }
+ }
+ });
+ } else {
+ promise.reject("Cannot generate keys on android versions below 6.0", "Cannot generate keys on android versions below 6.0");
+ }
+ }
- 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");
+ @ReactMethod
+ public void simplePrompt(final ReadableMap params, final Promise promise) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ UiThreadUtil.runOnUiThread(
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ String cancelButtomText = params.getString("cancelButtonText");
+ String promptMessage = params.getString("promptMessage");
+
+ 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(cancelButtomText)
+ .setTitle(promptMessage)
+ .build();
+ biometricPrompt.authenticate(promptInfo);
+ } catch (Exception e) {
+ promise.reject("Error displaying local biometric prompt: " + e.getMessage(), "Error displaying local biometric prompt: " + e.getMessage());
+ }
+ }
+ });
+ } else {
+ promise.reject("Cannot display biometric prompt on android versions below 6.0", "Cannot display biometric prompt on android versions below 6.0");
}
}
@ReactMethod
- public void simplePrompt(String title, Promise promise) {
+ public void biometricKeysExist(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");
- } else {
- promise.reject("Cannot display biometric prompt on android versions below 6.0", "Cannot display biometric prompt on android versions below 6.0");
- }
+ boolean doesBiometricKeyExist = doesBiometricKeyExist();
+ WritableMap resultMap = new WritableNativeMap();
+ resultMap.putBoolean("keysExist", doesBiometricKeyExist);
+ promise.resolve(resultMap);
} catch (Exception e) {
- promise.reject("Error displaying local biometric prompt: " + e.getMessage(), "Error displaying local biometric prompt");
+ promise.reject("Error checking if biometric key exists: " + e.getMessage(), "Error checking if biometric key exists: " + e.getMessage());
}
}
- protected boolean biometricKeyExists() {
+ protected boolean doesBiometricKeyExist() {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
@@ -168,91 +247,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");
- }
- };
- }
-
- 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/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/java/com/rnbiometrics/SimplePromptCallback.java b/android/src/main/java/com/rnbiometrics/SimplePromptCallback.java
new file mode 100644
index 0000000..64514bd
--- /dev/null
+++ b/android/src/main/java/com/rnbiometrics/SimplePromptCallback.java
@@ -0,0 +1,39 @@
+package com.rnbiometrics;
+
+import androidx.annotation.NonNull;
+import androidx.biometric.BiometricPrompt;
+
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.bridge.WritableNativeMap;
+
+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);
+ if (errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) {
+ WritableMap resultMap = new WritableNativeMap();
+ resultMap.putBoolean("success", false);
+ resultMap.putString("error", "User cancellation");
+ this.promise.resolve(resultMap);
+ } else {
+ this.promise.reject(errString.toString(), errString.toString());
+ }
+ }
+
+ @Override
+ public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
+ super.onAuthenticationSucceeded(result);
+
+ WritableMap resultMap = new WritableNativeMap();
+ resultMap.putBoolean("success", true);
+ this.promise.resolve(resultMap);
+ }
+}
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 48ebd8a..0000000
Binary files a/android/src/main/res/drawable-hdpi/ic_fp_40px.png and /dev/null differ
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 122f442..0000000
Binary files a/android/src/main/res/drawable-mdpi/ic_fp_40px.png and /dev/null differ
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 e1c9590..0000000
Binary files a/android/src/main/res/drawable-xhdpi/ic_fp_40px.png and /dev/null differ
diff --git a/android/src/main/res/drawable-xxhdpi/ic_fp_40px.png b/android/src/main/res/drawable-xxhdpi/ic_fp_40px.png
deleted file mode 100644
index f7e8724..0000000
Binary files a/android/src/main/res/drawable-xxhdpi/ic_fp_40px.png and /dev/null differ
diff --git a/android/src/main/res/drawable-xxxhdpi/ic_fp_40px.png b/android/src/main/res/drawable-xxxhdpi/ic_fp_40px.png
deleted file mode 100644
index 0fb8545..0000000
Binary files a/android/src/main/res/drawable-xxxhdpi/ic_fp_40px.png and /dev/null differ
diff --git a/android/src/main/res/drawable/ic_fingerprint_error.xml b/android/src/main/res/drawable/ic_fingerprint_error.xml
deleted file mode 100644
index be46116..0000000
--- a/android/src/main/res/drawable/ic_fingerprint_error.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
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 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/src/main/res/layout/fingerprint_dialog_content.xml b/android/src/main/res/layout/fingerprint_dialog_content.xml
deleted file mode 100644
index 007035e..0000000
--- a/android/src/main/res/layout/fingerprint_dialog_content.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/src/main/res/values/colors.xml b/android/src/main/res/values/colors.xml
deleted file mode 100644
index b051a41..0000000
--- a/android/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
- #f4511e
- #42000000
- #009688
-
diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml
deleted file mode 100644
index a7bce46..0000000
--- a/android/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
- Cancel
- Confirm fingerprint to continue
- Touch sensor
- Fingerprint recognized
- Fingerprint not recognized. Try again
-
diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml
deleted file mode 100644
index 7d9ce39..0000000
--- a/android/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/index.d.ts b/index.d.ts
index 340e5fd..a231969 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -1,49 +1,67 @@
-declare module 'react-native-biometrics' {
+export default interface ReactNativeBiometrics {
/**
* Enum for touch id sensor type
*/
- const TouchID: string;
+ TouchID: string;
+
/**
* Enum for face id sensor type
*/
- const FaceID: string;
+ FaceID: string;
+
/**
- * Returns promise that resolves to null, TouchID, or FaceID
- * @returns {Promise} Promise that resolves to null, TouchID, or FaceID
+ * Enum for generic biometrics (this is the only value available on android)
*/
- function isSensorAvailable(): Promise;
+ Biometrics: string;
+
/**
- * Prompts user with biometrics dialog using the passed in prompt message if
- * it is provided, returns promise that resolves to the public key of the
- * newly generated key pair
- * @param {string} promptMessage
- * @returns {Promise} Promise that resolves to newly generated public key
+ * Returns promise that resolves to an object with object.biometryType = Biometrics | TouchID | FaceID
+ * @returns {Promise