@capgo/capacitor-native-biometric 7.5.4 → 8.0.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.
@@ -8,6 +8,6 @@
8
8
  s.author = 'Martin Donadieu'
9
9
  s.source = { :git => 'https://github.com/Cap-go/capacitor-native-biometric', :tag => s.version.to_s }
10
10
  s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
11
- s.ios.deployment_target = '14.0'
11
+ s.ios.deployment_target = '15.0'
12
12
  s.dependency 'Capacitor'
13
13
  end
package/Package.swift CHANGED
@@ -3,14 +3,14 @@ import PackageDescription
3
3
 
4
4
  let package = Package(
5
5
  name: "CapgoCapacitorNativeBiometric",
6
- platforms: [.iOS(.v14)],
6
+ platforms: [.iOS(.v15)],
7
7
  products: [
8
8
  .library(
9
9
  name: "CapgoCapacitorNativeBiometric",
10
10
  targets: ["NativeBiometricPlugin"])
11
11
  ],
12
12
  dependencies: [
13
- .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")
14
14
  ],
15
15
  targets: [
16
16
  .target(
package/README.md CHANGED
@@ -18,6 +18,7 @@ A **free**, **comprehensive** biometric authentication plugin with secure creden
18
18
  - **Flexible fallback** - Optional passcode fallback when biometrics unavailable
19
19
  - **Customizable UI** - Full control over prompts, titles, descriptions, button text
20
20
  - **Detailed error codes** - Unified error handling across iOS and Android
21
+ - **Resume listener** - Detect biometry availability changes when app returns from background
21
22
  - **Modern package management** - Supports both Swift Package Manager (SPM) and CocoaPods (SPM-ready for Capacitor 8)
22
23
 
23
24
  Perfect for banking apps, password managers, authentication flows, and any app requiring secure user verification.
@@ -40,8 +41,16 @@ async performBiometricVerification(){
40
41
 
41
42
  if(!result.isAvailable) return;
42
43
 
44
+ // Check the biometry type for display purposes
45
+ // IMPORTANT: Always use isAvailable for logic decisions, not biometryType
43
46
  const isFaceID = result.biometryType == BiometryType.FACE_ID;
44
47
 
48
+ // Check if device has PIN/pattern/password set
49
+ console.log('Device is secure:', result.deviceIsSecure);
50
+
51
+ // Check if strong biometry (Face ID, Touch ID, fingerprint) is available
52
+ console.log('Strong biometry available:', result.strongBiometryIsAvailable);
53
+
45
54
  const verified = await NativeBiometric.verifyIdentity({
46
55
  reason: "For easy log in",
47
56
  title: "Log in",
@@ -69,6 +78,15 @@ NativeBiometric.setCredentials({
69
78
  NativeBiometric.deleteCredentials({
70
79
  server: "www.example.com",
71
80
  }).then();
81
+
82
+ // Listen for biometry availability changes when app resumes from background
83
+ const handle = await NativeBiometric.addListener('biometryChange', (result) => {
84
+ console.log('Biometry availability changed:', result.isAvailable);
85
+ console.log('Biometry type:', result.biometryType);
86
+ });
87
+
88
+ // To remove the listener when no longer needed:
89
+ // await handle.remove();
72
90
  ```
73
91
 
74
92
  ### Biometric Auth Errors
@@ -94,6 +112,7 @@ This is a plugin specific list of error codes that can be thrown on verifyIdenti
94
112
  <docgen-index>
95
113
 
96
114
  * [`isAvailable(...)`](#isavailable)
115
+ * [`addListener('biometryChange', ...)`](#addlistenerbiometrychange-)
97
116
  * [`verifyIdentity(...)`](#verifyidentity)
98
117
  * [`getCredentials(...)`](#getcredentials)
99
118
  * [`setCredentials(...)`](#setcredentials)
@@ -101,6 +120,7 @@ This is a plugin specific list of error codes that can be thrown on verifyIdenti
101
120
  * [`isCredentialsSaved(...)`](#iscredentialssaved)
102
121
  * [`getPluginVersion()`](#getpluginversion)
103
122
  * [Interfaces](#interfaces)
123
+ * [Type Aliases](#type-aliases)
104
124
  * [Enums](#enums)
105
125
 
106
126
  </docgen-index>
@@ -127,6 +147,28 @@ Checks if biometric authentication hardware is available.
127
147
  --------------------
128
148
 
129
149
 
150
+ ### addListener('biometryChange', ...)
151
+
152
+ ```typescript
153
+ addListener(eventName: 'biometryChange', listener: BiometryChangeListener) => Promise<PluginListenerHandle>
154
+ ```
155
+
156
+ Adds a listener that is called when the app resumes from background.
157
+ This is useful to detect if biometry availability has changed while
158
+ the app was in the background (e.g., user enrolled/unenrolled biometrics).
159
+
160
+ | Param | Type | Description |
161
+ | --------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
162
+ | **`eventName`** | <code>'biometryChange'</code> | - Must be 'biometryChange' |
163
+ | **`listener`** | <code><a href="#biometrychangelistener">BiometryChangeListener</a></code> | - Callback function that receives the updated <a href="#availableresult">AvailableResult</a> |
164
+
165
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>
166
+
167
+ **Since:** 7.6.0
168
+
169
+ --------------------
170
+
171
+
130
172
  ### verifyIdentity(...)
131
173
 
132
174
  ```typescript
@@ -238,11 +280,14 @@ Get the native Capacitor plugin version.
238
280
 
239
281
  Result from isAvailable() method indicating biometric authentication availability.
240
282
 
241
- | Prop | Type | Description |
242
- | ---------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
243
- | **`isAvailable`** | <code>boolean</code> | Whether authentication is available (biometric or fallback if useFallback is true) |
244
- | **`authenticationStrength`** | <code><a href="#authenticationstrength">AuthenticationStrength</a></code> | The strength of available authentication method (STRONG, WEAK, or NONE) |
245
- | **`errorCode`** | <code><a href="#biometricautherror">BiometricAuthError</a></code> | Error code from <a href="#biometricautherror">BiometricAuthError</a> enum. Only present when isAvailable is false. Indicates why biometric authentication is not available. |
283
+ | Prop | Type | Description |
284
+ | ------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
285
+ | **`isAvailable`** | <code>boolean</code> | Whether authentication is available (biometric or fallback if useFallback is true) |
286
+ | **`authenticationStrength`** | <code><a href="#authenticationstrength">AuthenticationStrength</a></code> | The strength of available authentication method (STRONG, WEAK, or NONE) |
287
+ | **`biometryType`** | <code><a href="#biometrytype">BiometryType</a></code> | The primary biometry type available on the device. On Android devices with multiple biometry types, this returns MULTIPLE. Use this for display purposes only - always use isAvailable for logic decisions. |
288
+ | **`deviceIsSecure`** | <code>boolean</code> | Whether the device has a secure lock screen (PIN, pattern, or password). This is independent of biometric enrollment. |
289
+ | **`strongBiometryIsAvailable`** | <code>boolean</code> | Whether strong biometry (Face ID, Touch ID, or fingerprint on devices that consider it strong) is specifically available, separate from weak biometry or device credentials. |
290
+ | **`errorCode`** | <code><a href="#biometricautherror">BiometricAuthError</a></code> | Error code from <a href="#biometricautherror">BiometricAuthError</a> enum. Only present when isAvailable is false. Indicates why biometric authentication is not available. |
246
291
 
247
292
 
248
293
  #### IsAvailableOptions
@@ -252,6 +297,13 @@ Result from isAvailable() method indicating biometric authentication availabilit
252
297
  | **`useFallback`** | <code>boolean</code> | Specifies if should fallback to passcode authentication if biometric authentication is not available. |
253
298
 
254
299
 
300
+ #### PluginListenerHandle
301
+
302
+ | Prop | Type |
303
+ | ------------ | ----------------------------------------- |
304
+ | **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |
305
+
306
+
255
307
  #### BiometricOptions
256
308
 
257
309
  | Prop | Type | Description | Default |
@@ -312,6 +364,16 @@ Result from isAvailable() method indicating biometric authentication availabilit
312
364
  | **`server`** | <code>string</code> |
313
365
 
314
366
 
367
+ ### Type Aliases
368
+
369
+
370
+ #### BiometryChangeListener
371
+
372
+ Callback type for biometry change listener
373
+
374
+ <code>(result: <a href="#availableresult">AvailableResult</a>): void</code>
375
+
376
+
315
377
  ### Enums
316
378
 
317
379
 
@@ -324,6 +386,19 @@ Result from isAvailable() method indicating biometric authentication availabilit
324
386
  | **`WEAK`** | <code>2</code> | Weak authentication: Face authentication on Android devices that consider face weak, or PIN/pattern/password if useFallback = true (PIN is always WEAK, never STRONG). |
325
387
 
326
388
 
389
+ #### BiometryType
390
+
391
+ | Members | Value |
392
+ | ------------------------- | -------------- |
393
+ | **`NONE`** | <code>0</code> |
394
+ | **`TOUCH_ID`** | <code>1</code> |
395
+ | **`FACE_ID`** | <code>2</code> |
396
+ | **`FINGERPRINT`** | <code>3</code> |
397
+ | **`FACE_AUTHENTICATION`** | <code>4</code> |
398
+ | **`IRIS_AUTHENTICATION`** | <code>5</code> |
399
+ | **`MULTIPLE`** | <code>6</code> |
400
+
401
+
327
402
  #### BiometricAuthError
328
403
 
329
404
  | Members | Value | Description |
@@ -342,19 +417,6 @@ Result from isAvailable() method indicating biometric authentication availabilit
342
417
  | **`USER_CANCEL`** | <code>16</code> | User canceled the authentication Platform: Android, iOS |
343
418
  | **`USER_FALLBACK`** | <code>17</code> | User chose to use fallback authentication method Platform: Android, iOS |
344
419
 
345
-
346
- #### BiometryType
347
-
348
- | Members | Value |
349
- | ------------------------- | -------------- |
350
- | **`NONE`** | <code>0</code> |
351
- | **`TOUCH_ID`** | <code>1</code> |
352
- | **`FACE_ID`** | <code>2</code> |
353
- | **`FINGERPRINT`** | <code>3</code> |
354
- | **`FACE_AUTHENTICATION`** | <code>4</code> |
355
- | **`IRIS_AUTHENTICATION`** | <code>5</code> |
356
- | **`MULTIPLE`** | <code>6</code> |
357
-
358
420
  </docgen-api>
359
421
  ## Face ID (iOS)
360
422
 
@@ -375,6 +437,22 @@ To use android's BiometricPrompt api you must add the following permission to yo
375
437
  <uses-permission android:name="android.permission.USE_BIOMETRIC">
376
438
  ```
377
439
 
440
+ ### Important Note About biometryType on Android
441
+
442
+ The `biometryType` field indicates what biometric hardware is present, but **hardware presence does not guarantee availability**. Some Android devices report face authentication hardware but don't make it available to apps.
443
+
444
+ **Always use `isAvailable` for logic decisions**, not `biometryType`. The `biometryType` field should only be used for display purposes (e.g., showing "Use Face ID" vs "Use Fingerprint" in your UI).
445
+
446
+ ## Web Platform
447
+
448
+ This plugin does not support web browsers. On web:
449
+ - `isAvailable()` returns `{ isAvailable: false, ... }` (no error thrown)
450
+ - `addListener()` returns a no-op handle
451
+ - `verifyIdentity()` throws an error
452
+ - Credential methods throw errors
453
+
454
+ This allows you to safely check availability on web without try/catch, but authentication features are only available on iOS and Android.
455
+
378
456
  ## Contributors
379
457
 
380
458
  [Jonthia](https://github.com/jonthia)
@@ -1,8 +1,8 @@
1
1
  ext {
2
2
  junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
- androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
4
- androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
5
- androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
3
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
4
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
5
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
6
6
  }
7
7
 
8
8
  buildscript {
@@ -11,18 +11,18 @@ buildscript {
11
11
  mavenCentral()
12
12
  }
13
13
  dependencies {
14
- classpath 'com.android.tools.build:gradle:8.7.2'
14
+ classpath 'com.android.tools.build:gradle:8.13.0'
15
15
  }
16
16
  }
17
17
 
18
18
  apply plugin: 'com.android.library'
19
19
 
20
20
  android {
21
- namespace "ee.forgr.biometric.capacitornativebiometric"
22
- compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
21
+ namespace = "ee.forgr.biometric.capacitornativebiometric"
22
+ compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
23
23
  defaultConfig {
24
- minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
25
- targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
24
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
25
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
26
26
  versionCode 1
27
27
  versionName "1.0"
28
28
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -34,7 +34,7 @@ android {
34
34
  }
35
35
  }
36
36
  lintOptions {
37
- abortOnError false
37
+ abortOnError = false
38
38
  }
39
39
  }
40
40
 
@@ -23,7 +23,9 @@ public class AuthActivity extends AppCompatActivity {
23
23
  super.onCreate(savedInstanceState);
24
24
  setContentView(R.layout.activity_auth_acitivy);
25
25
 
26
- maxAttempts = getIntent().getIntExtra("maxAttempts", 1);
26
+ // Get maxAttempts with validation: must be between 1 and 5, default to 1
27
+ int rawMaxAttempts = getIntent().getIntExtra("maxAttempts", 1);
28
+ maxAttempts = Math.max(1, Math.min(5, rawMaxAttempts));
27
29
 
28
30
  Executor executor;
29
31
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@@ -51,7 +51,7 @@ import org.json.JSONException;
51
51
  @CapacitorPlugin(name = "NativeBiometric")
52
52
  public class NativeBiometric extends Plugin {
53
53
 
54
- private final String pluginVersion = "7.3.2";
54
+ private final String pluginVersion = "7.5.4";
55
55
 
56
56
  //protected final static int AUTH_CODE = 0102;
57
57
 
@@ -77,11 +77,20 @@ public class NativeBiometric extends Plugin {
77
77
 
78
78
  private SharedPreferences encryptedSharedPreferences;
79
79
 
80
- @PluginMethod
81
- public void isAvailable(PluginCall call) {
82
- JSObject ret = new JSObject();
80
+ @Override
81
+ protected void handleOnResume() {
82
+ super.handleOnResume();
83
+ // Notify listeners when app resumes from background
84
+ JSObject result = checkBiometryAvailability(false);
85
+ notifyListeners("biometryChange", result);
86
+ }
83
87
 
84
- boolean useFallback = Boolean.TRUE.equals(call.getBoolean("useFallback", false));
88
+ /**
89
+ * Check biometry availability and return result as JSObject.
90
+ * This is a helper method used by both isAvailable() and handleOnResume().
91
+ */
92
+ private JSObject checkBiometryAvailability(boolean useFallback) {
93
+ JSObject ret = new JSObject();
85
94
 
86
95
  BiometricManager biometricManager = BiometricManager.from(getContext());
87
96
 
@@ -96,23 +105,30 @@ public class NativeBiometric extends Plugin {
96
105
  boolean hasWeakBiometric = (weakResult == BiometricManager.BIOMETRIC_SUCCESS);
97
106
 
98
107
  // Check if device has credentials (PIN/pattern/password)
99
- boolean fallbackAvailable = useFallback && this.deviceHasCredentials();
108
+ boolean deviceIsSecure = this.deviceHasCredentials();
109
+ boolean fallbackAvailable = useFallback && deviceIsSecure;
110
+
111
+ // Determine biometry type
112
+ int biometryType = detectBiometryType(biometricManager);
113
+ ret.put("biometryType", biometryType);
114
+
115
+ // Device is secure if it has PIN/pattern/password
116
+ ret.put("deviceIsSecure", deviceIsSecure);
117
+
118
+ // Strong biometry is available only if strong biometric check passes
119
+ ret.put("strongBiometryIsAvailable", hasStrongBiometric);
100
120
 
101
121
  // Determine authentication strength
102
122
  int authenticationStrength = AUTH_STRENGTH_NONE;
103
123
  boolean isAvailable = false;
104
124
 
105
125
  if (hasStrongBiometric) {
106
- // Strong biometric available (fingerprints on devices that consider them strong)
107
126
  authenticationStrength = AUTH_STRENGTH_STRONG;
108
127
  isAvailable = true;
109
128
  } else if (hasWeakBiometric) {
110
- // Only weak biometric available (face on devices that consider it weak)
111
129
  authenticationStrength = AUTH_STRENGTH_WEAK;
112
130
  isAvailable = true;
113
131
  } else if (fallbackAvailable) {
114
- // No biometrics but fallback (PIN/pattern/password) is available
115
- // PIN/pattern/password is ALWAYS considered WEAK, never STRONG
116
132
  authenticationStrength = AUTH_STRENGTH_WEAK;
117
133
  isAvailable = true;
118
134
  }
@@ -120,29 +136,58 @@ public class NativeBiometric extends Plugin {
120
136
  // Handle error codes when authentication is not available
121
137
  if (!isAvailable) {
122
138
  int biometricManagerErrorCode;
123
-
124
- // Prefer the error from strong biometric check if it failed
125
139
  if (strongResult != BiometricManager.BIOMETRIC_SUCCESS) {
126
140
  biometricManagerErrorCode = strongResult;
127
141
  } else if (weakResult != BiometricManager.BIOMETRIC_SUCCESS) {
128
- // Otherwise use error from weak biometric check if it failed
129
142
  biometricManagerErrorCode = weakResult;
130
143
  } else {
131
- // No biometrics available at all
132
- // BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE indicates that biometric hardware is unavailable
133
- // or cannot be accessed. This constant value may vary across Android versions, so we explicitly
134
- // use the constant rather than assuming its numeric value.
135
144
  biometricManagerErrorCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
136
145
  }
137
-
138
- // Convert BiometricManager error codes to plugin error codes
139
146
  int pluginErrorCode = convertBiometricManagerErrorToPluginError(biometricManagerErrorCode);
140
147
  ret.put("errorCode", pluginErrorCode);
141
148
  }
142
149
 
143
150
  ret.put("isAvailable", isAvailable);
144
151
  ret.put("authenticationStrength", authenticationStrength);
145
- call.resolve(ret);
152
+ return ret;
153
+ }
154
+
155
+ @PluginMethod
156
+ public void isAvailable(PluginCall call) {
157
+ boolean useFallback = Boolean.TRUE.equals(call.getBoolean("useFallback", false));
158
+ JSObject result = checkBiometryAvailability(useFallback);
159
+ call.resolve(result);
160
+ }
161
+
162
+ /**
163
+ * Detect the primary biometry type available on the device.
164
+ * Note: Android doesn't provide a direct API to query specific biometry types,
165
+ * so we check for hardware features. This is informational only - always use
166
+ * isAvailable for logic decisions as hardware presence doesn't guarantee availability.
167
+ */
168
+ private int detectBiometryType(BiometricManager biometricManager) {
169
+ PackageManager pm = getContext().getPackageManager();
170
+
171
+ boolean hasFingerprint = pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
172
+ boolean hasFace = pm.hasSystemFeature(PackageManager.FEATURE_FACE);
173
+ boolean hasIris = pm.hasSystemFeature(PackageManager.FEATURE_IRIS);
174
+
175
+ int typeCount = 0;
176
+ if (hasFingerprint) typeCount++;
177
+ if (hasFace) typeCount++;
178
+ if (hasIris) typeCount++;
179
+
180
+ if (typeCount > 1) {
181
+ return MULTIPLE; // Multiple biometry types available
182
+ } else if (hasFingerprint) {
183
+ return FINGERPRINT;
184
+ } else if (hasFace) {
185
+ return FACE_AUTHENTICATION;
186
+ } else if (hasIris) {
187
+ return IRIS_AUTHENTICATION;
188
+ }
189
+
190
+ return NONE;
146
191
  }
147
192
 
148
193
  @PluginMethod
@@ -292,8 +337,10 @@ public class NativeBiometric extends Plugin {
292
337
  String KEY_ALIAS = call.getString("server", null);
293
338
 
294
339
  if (KEY_ALIAS != null) {
295
- SharedPreferences sharedPreferences = getContext()
296
- .getSharedPreferences(NATIVE_BIOMETRIC_SHARED_PREFERENCES, Context.MODE_PRIVATE);
340
+ SharedPreferences sharedPreferences = getContext().getSharedPreferences(
341
+ NATIVE_BIOMETRIC_SHARED_PREFERENCES,
342
+ Context.MODE_PRIVATE
343
+ );
297
344
  String username = sharedPreferences.getString(KEY_ALIAS + "-username", null);
298
345
  String password = sharedPreferences.getString(KEY_ALIAS + "-password", null);
299
346
 
package/dist/docs.json CHANGED
@@ -40,6 +40,51 @@
40
40
  ],
41
41
  "slug": "isavailable"
42
42
  },
43
+ {
44
+ "name": "addListener",
45
+ "signature": "(eventName: 'biometryChange', listener: BiometryChangeListener) => Promise<PluginListenerHandle>",
46
+ "parameters": [
47
+ {
48
+ "name": "eventName",
49
+ "docs": "- Must be 'biometryChange'",
50
+ "type": "'biometryChange'"
51
+ },
52
+ {
53
+ "name": "listener",
54
+ "docs": "- Callback function that receives the updated AvailableResult",
55
+ "type": "BiometryChangeListener"
56
+ }
57
+ ],
58
+ "returns": "Promise<PluginListenerHandle>",
59
+ "tags": [
60
+ {
61
+ "name": "param",
62
+ "text": "eventName - Must be 'biometryChange'"
63
+ },
64
+ {
65
+ "name": "param",
66
+ "text": "listener - Callback function that receives the updated AvailableResult"
67
+ },
68
+ {
69
+ "name": "returns",
70
+ "text": "Handle to remove the listener"
71
+ },
72
+ {
73
+ "name": "since",
74
+ "text": "7.6.0"
75
+ },
76
+ {
77
+ "name": "example",
78
+ "text": "```typescript\nconst handle = await NativeBiometric.addListener('biometryChange', (result) => {\n console.log('Biometry availability changed:', result.isAvailable);\n});\n\n// To remove the listener:\nawait handle.remove();\n```"
79
+ }
80
+ ],
81
+ "docs": "Adds a listener that is called when the app resumes from background.\nThis is useful to detect if biometry availability has changed while\nthe app was in the background (e.g., user enrolled/unenrolled biometrics).",
82
+ "complexTypes": [
83
+ "PluginListenerHandle",
84
+ "BiometryChangeListener"
85
+ ],
86
+ "slug": "addlistenerbiometrychange-"
87
+ },
43
88
  {
44
89
  "name": "verifyIdentity",
45
90
  "signature": "(options?: BiometricOptions | undefined) => Promise<void>",
@@ -258,6 +303,29 @@
258
303
  ],
259
304
  "type": "AuthenticationStrength"
260
305
  },
306
+ {
307
+ "name": "biometryType",
308
+ "tags": [],
309
+ "docs": "The primary biometry type available on the device.\nOn Android devices with multiple biometry types, this returns MULTIPLE.\nUse this for display purposes only - always use isAvailable for logic decisions.",
310
+ "complexTypes": [
311
+ "BiometryType"
312
+ ],
313
+ "type": "BiometryType"
314
+ },
315
+ {
316
+ "name": "deviceIsSecure",
317
+ "tags": [],
318
+ "docs": "Whether the device has a secure lock screen (PIN, pattern, or password).\nThis is independent of biometric enrollment.",
319
+ "complexTypes": [],
320
+ "type": "boolean"
321
+ },
322
+ {
323
+ "name": "strongBiometryIsAvailable",
324
+ "tags": [],
325
+ "docs": "Whether strong biometry (Face ID, Touch ID, or fingerprint on devices that consider it strong)\nis specifically available, separate from weak biometry or device credentials.",
326
+ "complexTypes": [],
327
+ "type": "boolean"
328
+ },
261
329
  {
262
330
  "name": "errorCode",
263
331
  "tags": [
@@ -290,6 +358,22 @@
290
358
  }
291
359
  ]
292
360
  },
361
+ {
362
+ "name": "PluginListenerHandle",
363
+ "slug": "pluginlistenerhandle",
364
+ "docs": "",
365
+ "tags": [],
366
+ "methods": [],
367
+ "properties": [
368
+ {
369
+ "name": "remove",
370
+ "tags": [],
371
+ "docs": "",
372
+ "complexTypes": [],
373
+ "type": "() => Promise<void>"
374
+ }
375
+ ]
376
+ },
293
377
  {
294
378
  "name": "BiometricOptions",
295
379
  "slug": "biometricoptions",
@@ -517,6 +601,54 @@
517
601
  }
518
602
  ]
519
603
  },
604
+ {
605
+ "name": "BiometryType",
606
+ "slug": "biometrytype",
607
+ "members": [
608
+ {
609
+ "name": "NONE",
610
+ "value": "0",
611
+ "tags": [],
612
+ "docs": ""
613
+ },
614
+ {
615
+ "name": "TOUCH_ID",
616
+ "value": "1",
617
+ "tags": [],
618
+ "docs": ""
619
+ },
620
+ {
621
+ "name": "FACE_ID",
622
+ "value": "2",
623
+ "tags": [],
624
+ "docs": ""
625
+ },
626
+ {
627
+ "name": "FINGERPRINT",
628
+ "value": "3",
629
+ "tags": [],
630
+ "docs": ""
631
+ },
632
+ {
633
+ "name": "FACE_AUTHENTICATION",
634
+ "value": "4",
635
+ "tags": [],
636
+ "docs": ""
637
+ },
638
+ {
639
+ "name": "IRIS_AUTHENTICATION",
640
+ "value": "5",
641
+ "tags": [],
642
+ "docs": ""
643
+ },
644
+ {
645
+ "name": "MULTIPLE",
646
+ "value": "6",
647
+ "tags": [],
648
+ "docs": ""
649
+ }
650
+ ]
651
+ },
520
652
  {
521
653
  "name": "BiometricAuthError",
522
654
  "slug": "biometricautherror",
@@ -600,56 +732,22 @@
600
732
  "docs": "User chose to use fallback authentication method\nPlatform: Android, iOS"
601
733
  }
602
734
  ]
603
- },
735
+ }
736
+ ],
737
+ "typeAliases": [
604
738
  {
605
- "name": "BiometryType",
606
- "slug": "biometrytype",
607
- "members": [
608
- {
609
- "name": "NONE",
610
- "value": "0",
611
- "tags": [],
612
- "docs": ""
613
- },
614
- {
615
- "name": "TOUCH_ID",
616
- "value": "1",
617
- "tags": [],
618
- "docs": ""
619
- },
739
+ "name": "BiometryChangeListener",
740
+ "slug": "biometrychangelistener",
741
+ "docs": "Callback type for biometry change listener",
742
+ "types": [
620
743
  {
621
- "name": "FACE_ID",
622
- "value": "2",
623
- "tags": [],
624
- "docs": ""
625
- },
626
- {
627
- "name": "FINGERPRINT",
628
- "value": "3",
629
- "tags": [],
630
- "docs": ""
631
- },
632
- {
633
- "name": "FACE_AUTHENTICATION",
634
- "value": "4",
635
- "tags": [],
636
- "docs": ""
637
- },
638
- {
639
- "name": "IRIS_AUTHENTICATION",
640
- "value": "5",
641
- "tags": [],
642
- "docs": ""
643
- },
644
- {
645
- "name": "MULTIPLE",
646
- "value": "6",
647
- "tags": [],
648
- "docs": ""
744
+ "text": "(result: AvailableResult): void",
745
+ "complexTypes": [
746
+ "AvailableResult"
747
+ ]
649
748
  }
650
749
  ]
651
750
  }
652
751
  ],
653
- "typeAliases": [],
654
752
  "pluginConfigs": []
655
753
  }