@exodus/react-native-biometrics 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -2,3 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this projected will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://www.conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## 0.4.1 (2026-09-11)
|
|
7
|
+
|
|
8
|
+
- Fix authentication failing before the prompt appears on Android 9–10 when device passcode fallback is enabled ([#9](https://github.com/ExodusMovement/react-native-biometrics/pull/9)).
|
package/README.md
CHANGED
|
@@ -30,7 +30,24 @@ const valid = await Biometrics.authenticate(
|
|
|
30
30
|
| title | string | The title of the biometric prompt |
|
|
31
31
|
| subtitle | string | The subtitle of the biometric prompt |
|
|
32
32
|
| cancelButtonText | string | The text of the cancel button |
|
|
33
|
+
| fallbackToPasscode | boolean | Allow the device PIN, pattern, or password as an alternative to biometrics (default: `false`) |
|
|
33
34
|
|
|
35
|
+
With passcode fallback enabled, Android 9–10 (API 28–29) accepts Class 2 (weak) or
|
|
36
|
+
Class 3 (strong) biometrics alongside device credentials. AndroidX does not support
|
|
37
|
+
`BIOMETRIC_STRONG | DEVICE_CREDENTIAL` on these versions. Other Android versions,
|
|
38
|
+
and biometric-only authentication on all versions, continue to require Class 3
|
|
39
|
+
biometrics. Authentication does not use a `CryptoObject`.
|
|
40
|
+
|
|
41
|
+
## Android tests
|
|
42
|
+
|
|
43
|
+
With JDK 17, Gradle 8.12, Android SDK 36, and build tools 36.0.0 installed:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
gradle -p test/android :biometrics:testDebugUnitTest
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The tests use the library's AndroidX dependency and Robolectric to validate prompt
|
|
50
|
+
creation on API 27, 28, 29, and 30, including the previously rejected combination.
|
|
34
51
|
|
|
35
52
|
## License
|
|
36
53
|
|
|
@@ -3,6 +3,7 @@ package org.exodusmovement.rn.biometrics;
|
|
|
3
3
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
4
4
|
|
|
5
5
|
import android.app.Activity;
|
|
6
|
+
import android.os.Build;
|
|
6
7
|
import android.os.Handler;
|
|
7
8
|
import android.os.Looper;
|
|
8
9
|
|
|
@@ -38,6 +39,28 @@ public final class RNBiometricsModule extends ReactContextBaseJavaModule {
|
|
|
38
39
|
return NAME;
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
static BiometricPrompt.PromptInfo createPromptInfo(String title, String subtitle, String cancelButtonText, boolean fallbackToPasscode) {
|
|
43
|
+
int authenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG;
|
|
44
|
+
if (fallbackToPasscode) {
|
|
45
|
+
// AndroidX cannot combine strong biometrics with device credentials on API 28-29.
|
|
46
|
+
if (Build.VERSION.SDK_INT >= 28 && Build.VERSION.SDK_INT <= 29) {
|
|
47
|
+
authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK;
|
|
48
|
+
}
|
|
49
|
+
authenticators |= BiometricManager.Authenticators.DEVICE_CREDENTIAL;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
BiometricPrompt.PromptInfo.Builder builder = new BiometricPrompt.PromptInfo.Builder()
|
|
53
|
+
.setAllowedAuthenticators(authenticators)
|
|
54
|
+
.setTitle(title)
|
|
55
|
+
.setSubtitle(subtitle);
|
|
56
|
+
|
|
57
|
+
if (!fallbackToPasscode) {
|
|
58
|
+
builder.setNegativeButtonText(cancelButtonText);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return builder.build();
|
|
62
|
+
}
|
|
63
|
+
|
|
41
64
|
@ReactMethod
|
|
42
65
|
public void isSupported(Promise promise) {
|
|
43
66
|
try {
|
|
@@ -87,19 +110,6 @@ public final class RNBiometricsModule extends ReactContextBaseJavaModule {
|
|
|
87
110
|
};
|
|
88
111
|
|
|
89
112
|
try {
|
|
90
|
-
int authenticators = fallbackToPasscode
|
|
91
|
-
? BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
|
92
|
-
: BiometricManager.Authenticators.BIOMETRIC_STRONG;
|
|
93
|
-
|
|
94
|
-
BiometricPrompt.PromptInfo.Builder promptInfoBuilder = new BiometricPrompt.PromptInfo.Builder()
|
|
95
|
-
.setAllowedAuthenticators(authenticators)
|
|
96
|
-
.setTitle(title)
|
|
97
|
-
.setSubtitle(subtitle);
|
|
98
|
-
|
|
99
|
-
if (!fallbackToPasscode) {
|
|
100
|
-
promptInfoBuilder.setNegativeButtonText(cancelButtonText);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
113
|
BiometricPrompt prompt = new BiometricPrompt(
|
|
104
114
|
fragmentActivity,
|
|
105
115
|
ContextCompat.getMainExecutor(context),
|
|
@@ -110,7 +120,7 @@ public final class RNBiometricsModule extends ReactContextBaseJavaModule {
|
|
|
110
120
|
activePromise = promise;
|
|
111
121
|
activeSettled = settled;
|
|
112
122
|
|
|
113
|
-
prompt.authenticate(
|
|
123
|
+
prompt.authenticate(createPromptInfo(title, subtitle, cancelButtonText, fallbackToPasscode));
|
|
114
124
|
} catch (Exception e) {
|
|
115
125
|
if (settled.compareAndSet(false, true)) {
|
|
116
126
|
clearSlotIfMatches(promise);
|