@aparajita/capacitor-biometric-auth 1.0.7 โ 2.0.2
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/AparajitaCapacitorBiometricAuth.podspec +2 -2
- package/README.md +76 -62
- package/android/src/main/java/com/aparajita/capacitor/biometricauth/AuthActivity.java +123 -95
- package/android/src/main/java/com/aparajita/capacitor/biometricauth/BiometricAuth.java +262 -0
- package/android/src/main/java/com/aparajita/capacitor/biometricauth/BiometryResultType.java +3 -3
- package/dist/esm/definitions.d.ts +26 -33
- package/dist/esm/definitions.js +2 -2
- package/dist/esm/index.d.ts +4 -1
- package/dist/esm/index.js +17 -2
- package/dist/esm/package.json +113 -0
- package/dist/esm/web.d.ts +6 -6
- package/dist/esm/web.js +36 -29
- package/dist/plugin.cjs.js +172 -0
- package/dist/plugin.js +173 -0
- package/ios/Plugin/Plugin.m +3 -1
- package/ios/Plugin/Plugin.swift +6 -6
- package/package.json +76 -48
- package/CHANGELOG.md +0 -71
- package/android/gradle.properties +0 -21
- package/android/settings.gradle +0 -2
- package/android/src/main/java/com/aparajita/capacitor/biometricauth/WSBiometricAuth.java +0 -216
- package/ios/Podfile +0 -16
- package/ios/Podfile.lock +0 -22
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
s.author = package['author']
|
|
13
13
|
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
14
14
|
s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
15
|
-
s.ios.deployment_target = '
|
|
15
|
+
s.ios.deployment_target = '12.0'
|
|
16
16
|
s.dependency 'Capacitor'
|
|
17
|
-
s.swift_version = '5.
|
|
17
|
+
s.swift_version = '5.1'
|
|
18
18
|
end
|
package/README.md
CHANGED
|
@@ -1,48 +1,45 @@
|
|
|
1
|
+
<div class="markdown-body">
|
|
2
|
+
|
|
1
3
|
# capacitor-biometric-auth
|
|
2
4
|
|
|
3
|
-
This plugin for [Capacitor
|
|
5
|
+
This plugin for [Capacitor 3](https://capacitorjs.com) provides access to native biometry on iOS and Android. It supports every type of biometry and every configuration option on both platforms. In addition, biometry is simulated on the web so you can test your logic without making any changes to your code.
|
|
4
6
|
|
|
5
|
-
๐ **NOTE:** This plugin
|
|
7
|
+
๐ **NOTE:** This plugin only works with Capacitor 3. If you are upgrading from the Capacitor 2 version, note that the plugin name has changed to `BiometricAuth`.
|
|
6
8
|
|
|
7
9
|
## Installation
|
|
8
10
|
|
|
9
11
|
```sh
|
|
10
|
-
pnpm
|
|
11
|
-
npm install @aparajita/capacitor-biometric-auth
|
|
12
|
-
yarn add @aparajita/capacitor-biometric-auth
|
|
12
|
+
pnpm add @aparajita/capacitor-biometric-auth
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Not using [pnpm](https://pnpm.js.org/)? You owe it to yourself to give it a try. Itโs faster, better with monorepos, and uses *way, way* less disk space than the alternatives.
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
|
-
The API is documented [
|
|
19
|
+
The API is extensively documented in the [TypeScript definitions file](src/definitions.ts). There is also (somewhat incomplete auto-generated) documentation [below](#api). For a complete example of how to use this plugin in practice, see the [demo app](https://github.com/aparajita/capacitor-biometric-auth-demo).
|
|
20
20
|
|
|
21
21
|
### Checking availability
|
|
22
22
|
|
|
23
23
|
Before giving the user the option to use biometry (such as displaying a biometry icon), call [`checkBiometry`](#checkbiometry) and inspect the [`CheckBiometryResult`](#checkbiometryresult) to see what (if any) biometry is available on the device. Note that `isAvailable` may be `false` but `biometryType` may indicate the presence of biometry on the device. This occurs if the current user is not enrolled in biometry, or if biometry has been disabled for the current app. In such cases the `reason` will tell you why.
|
|
24
24
|
|
|
25
|
-
Because the availability of biometry can change while your app is in the background, itโs important to
|
|
25
|
+
Because the availability of biometry can change while your app is in the background, itโs important to check availability when your app resumes. By calling [`addResumeListener`](#addresumelistener) you can register a callback that is passed a [`CheckBiometryResult`](#checkbiometryresult) when your app resumes.
|
|
26
26
|
|
|
27
27
|
### Authenticating
|
|
28
28
|
|
|
29
|
-
Once you have determined that biometry is available, to initiate biometric authentication call [authenticate](#authenticate). `authenticate` takes an [AuthenticateOptions](#authenticateoptions) object which you will want to use in order to control the behavior and appearance of the biometric prompt.
|
|
29
|
+
Once you have determined that biometry is available, to initiate biometric authentication call [`authenticate`](#authenticate). `authenticate` takes an [`AuthenticateOptions`](#authenticateoptions) object which you will want to use in order to control the behavior and appearance of the biometric prompt.
|
|
30
30
|
|
|
31
31
|
If authentication succeeds, the Promise resolves. If authentication fails, the Promise is rejected with a `BiometryError`, which has two properties:
|
|
32
32
|
|
|
33
|
-
| Property | Type
|
|
34
|
-
| :----------
|
|
35
|
-
| message | string
|
|
36
|
-
| code | BiometryErrorType | What caused the error |
|
|
33
|
+
| Property | Type | Description |
|
|
34
|
+
| :---------- |:--------------------------------------------------------------------------------------------------------| :------------- |
|
|
35
|
+
| message | string | A description of the error suitable for debugging |
|
|
36
|
+
| code | [BiometryErrorType](https://github.com/aparajita/capacitor-biometric-auth/blob/main/src/definitions.ts) | What caused the error |
|
|
37
37
|
|
|
38
38
|
## Biometry support
|
|
39
39
|
|
|
40
40
|
### web
|
|
41
41
|
|
|
42
|
-
On the web, you can fake any of the supported biometry types by
|
|
43
|
-
|
|
44
|
-
- Set the environment variable `WS_BIOMETRY_TYPE` to one of the `BiometryType` enums. This value is case-sensitive; for example to simulate Touch ID on the web, set `WS_BIOMETRY_TYPE` to `touchId`.
|
|
45
|
-
- Call `setBiometryType()`.
|
|
42
|
+
On the web, you can fake any of the supported biometry types by calling [`setBiometryType()`](#setbiometrytype).
|
|
46
43
|
|
|
47
44
|
### iOS
|
|
48
45
|
|
|
@@ -53,18 +50,16 @@ On iOS, Touch ID and Face ID are supported.
|
|
|
53
50
|
On Android, fingerprint, face, and iris authentication are supported. Note that if a device supports more than one type of biometry, the plugin will only present the primary type, which is determined by the system.
|
|
54
51
|
|
|
55
52
|
## API
|
|
56
|
-
|
|
57
53
|
<docgen-index>
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
[
|
|
61
|
-
[
|
|
62
|
-
[authenticate(...)](#authenticate)<br>
|
|
55
|
+
[checkBiometry()](#checkbiometry)
|
|
56
|
+
[setBiometryType(...)](#setbiometrytype)
|
|
57
|
+
[authenticate(...)](#authenticate)
|
|
63
58
|
[addResumeListener(...)](#addresumelistener)
|
|
64
59
|
|
|
65
|
-
|
|
66
|
-
[
|
|
67
|
-
[Enums](#enums)
|
|
60
|
+
[Interfaces](#interfaces)
|
|
61
|
+
[Type Aliases](#type-aliases)
|
|
62
|
+
[Enums](#enums)
|
|
68
63
|
|
|
69
64
|
</docgen-index>
|
|
70
65
|
<docgen-api>
|
|
@@ -76,7 +71,7 @@ On Android, fingerprint, face, and iris authentication are supported. Note that
|
|
|
76
71
|
checkBiometry() => Promise<CheckBiometryResult>
|
|
77
72
|
```
|
|
78
73
|
|
|
79
|
-
Check to see what biometry type (if any) is available.
|
|
74
|
+
Check to see what biometry type (if any) is available.
|
|
80
75
|
|
|
81
76
|
**Returns:** Promise<<a href="#checkbiometryresult">CheckBiometryResult</a>>
|
|
82
77
|
|
|
@@ -89,11 +84,11 @@ Check to see what biometry type (if any) is available. For testing on the web, a
|
|
|
89
84
|
setBiometryType(type: BiometryType | string | undefined) => void
|
|
90
85
|
```
|
|
91
86
|
|
|
92
|
-
web only<br><br>On the web, this method allows you to dynamically simulate different types of biometry. You may either pass a <a href="#biometrytype"
|
|
87
|
+
web only<br><br>On the web, this method allows you to dynamically simulate different types of biometry. You may either pass a <a href="#biometrytype">`BiometryType`</a> enum or the string name of a <a href="#biometrytype">`BiometryType`</a>. If a string is passed and it isn't a valid value, nothing happens.
|
|
93
88
|
|
|
94
|
-
| Param
|
|
95
|
-
|
|
|
96
|
-
|
|
|
89
|
+
| Param | Type |
|
|
90
|
+
| :---------- | :--------------------------------------------------------------- |
|
|
91
|
+
|type|string \| <a href="#biometrytype">BiometryType</a>|
|
|
97
92
|
|
|
98
93
|
--------------------
|
|
99
94
|
|
|
@@ -101,14 +96,14 @@ web only<br><br>On the web, this method allows you to dynamically simulate diffe
|
|
|
101
96
|
### authenticate(...)
|
|
102
97
|
|
|
103
98
|
```typescript
|
|
104
|
-
authenticate(options?: AuthenticateOptions
|
|
99
|
+
authenticate(options?: AuthenticateOptions) => Promise<void>
|
|
105
100
|
```
|
|
106
101
|
|
|
107
|
-
Prompt the user for authentication. If authorization fails for any reason, the promise is rejected with a BiometryError
|
|
102
|
+
Prompt the user for authentication. If authorization fails for any reason, the promise is rejected with a `BiometryError`.
|
|
108
103
|
|
|
109
|
-
| Param
|
|
110
|
-
|
|
|
111
|
-
|
|
|
104
|
+
| Param | Type |
|
|
105
|
+
| :------------- | :------------------------------------------------------------------- |
|
|
106
|
+
|options|<a href="#authenticateoptions">AuthenticateOptions</a>|
|
|
112
107
|
|
|
113
108
|
--------------------
|
|
114
109
|
|
|
@@ -116,14 +111,16 @@ Prompt the user for authentication. If authorization fails for any reason, the p
|
|
|
116
111
|
### addResumeListener(...)
|
|
117
112
|
|
|
118
113
|
```typescript
|
|
119
|
-
addResumeListener(listener: ResumeListener) =>
|
|
114
|
+
addResumeListener(listener: ResumeListener) => Promise<PluginListenerHandle>
|
|
120
115
|
```
|
|
121
116
|
|
|
122
|
-
Register a function that will be called when the app resumes. The function will be passed the result of checkBiometry()
|
|
117
|
+
Register a function that will be called when the app resumes. The function will be passed the result of `checkBiometry()`.
|
|
123
118
|
|
|
124
|
-
| Param
|
|
125
|
-
|
|
|
126
|
-
|
|
|
119
|
+
| Param | Type |
|
|
120
|
+
| :-------------- | :--------------------------------------------------------- |
|
|
121
|
+
|listener|<a href="#resumelistener">ResumeListener</a>|
|
|
122
|
+
|
|
123
|
+
**Returns:** Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>>
|
|
127
124
|
|
|
128
125
|
--------------------
|
|
129
126
|
|
|
@@ -133,25 +130,41 @@ Register a function that will be called when the app resumes. The function will
|
|
|
133
130
|
|
|
134
131
|
#### CheckBiometryResult
|
|
135
132
|
|
|
136
|
-
| Prop
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
133
|
+
| Prop | Type | Description |
|
|
134
|
+
| :------------------ | :----------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------- |
|
|
135
|
+
|isAvailable|boolean| True if the device has biometric authentication capability and the current user has enrolled in biometry. |
|
|
136
|
+
|biometryType|<a href="#biometrytype">BiometryType</a>| The type of biometry available on the device. |
|
|
137
|
+
|reason|string| If biometry is not available and the system gives a reason why, it will be returned here. Otherwise it's an empty string. |
|
|
141
138
|
|
|
142
|
-
<br>
|
|
143
139
|
|
|
144
140
|
#### AuthenticateOptions
|
|
145
141
|
|
|
146
|
-
| Prop
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
|
|
|
150
|
-
|
|
|
151
|
-
|
|
|
152
|
-
|
|
|
153
|
-
|
|
|
154
|
-
|
|
|
142
|
+
| Prop | Type | Description |
|
|
143
|
+
| :--------------------------- | :-------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
144
|
+
|reason|string| The reason for requesting authentication. Displays in the authentication dialog presented to the user. If not supplied, a default message is displayed. |
|
|
145
|
+
|cancelTitle|string| iOS: The system presents a cancel button during biometric authentication to let the user abort the authentication attempt. The button appears every time the system asks the user to present a finger registered with Touch ID. For Face ID, the button only appears if authentication fails and the user is prompted to try again. Either way, the user can stop trying to authenticate by tapping the button.<br><br>Android: The text for the negative button. This would typically be used as a "Cancel" button, but may be also used to show an alternative method for authentication, such as a screen that asks for a backup password.<br><br>Default: "Cancel" |
|
|
146
|
+
|allowDeviceCredential|boolean| If true, allows for authentication using device unlock credentials. Default is false.<br><br>iOS: If biometry is available, enrolled, and not disabled, the system uses that first. After the first Touch ID failure or second Face ID failure, if `iosFallbackTitle` is not an empty string, a fallback button appears in the authentication dialog. If the user taps the fallback button, the system prompts the user for the device passcode or the userโs password. If `iosFallbackTitle` is an empty string, no fallback button will appear.<br><br>If biometry is not available, enrolled and enabled, and a passcode is set, the system immediately prompts the user for the device passcode or userโs password. Authentication fails with the error code `passcodeNotSet` if the device passcode isnโt enabled.<br><br>If a passcode is not set on the device, a `passcodeNotSet` error is returned.<br><br>The system disables passcode authentication after 6 unsuccessful attempts, with progressively increasing delays between attempts.<br><br>The title of the fallback button may be customized by setting `iosFallbackTitle` to a non-empty string.<br><br>Android: The user will first be prompted to authenticate with biometrics, but also given the option to authenticate with their device PIN, pattern, or password by tapping a button in the authentication dialog. The title of the button is supplied by the system. |
|
|
147
|
+
|iosFallbackTitle|string| The system presents a fallback button when biometric authentication fails โ for example, because the system doesnโt recognize the presented finger, or after several failed attempts to recognize the userโs face.<br><br>If `allowDeviceCredential` is false, tapping this button dismisses the authentication dialog and returns the error code userFallback. If undefined, the localized systetm default title is used. Passing an empty string hides the fallback button completely.<br><br>If `allowDeviceCredential` is true and this is undefined, the localized system default title is used. |
|
|
148
|
+
|androidTitle|string| Title for the Android dialog. If not supplied, the system default is used. |
|
|
149
|
+
|androidSubtitle|string| Subtitle for the Android dialog. If not supplied, the system default is used. |
|
|
150
|
+
|androidMaxAttempts|number| The maximum number of failed biometric verification attempts before returning `BiometryError.authenticationFailed`. The default is 3. |
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
#### PluginListenerHandle
|
|
154
|
+
|
|
155
|
+
| Method | Signature |
|
|
156
|
+
| :---------- | :---------------------------- |
|
|
157
|
+
| **remove** | () => Promise<void> |
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
### Type Aliases
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
#### ResumeListener
|
|
164
|
+
|
|
165
|
+
The signature of the callback passed to `addResumeListener()`.
|
|
166
|
+
|
|
167
|
+
<code>(info: <a href="#checkbiometryresult">CheckBiometryResult</a>): void</code>
|
|
155
168
|
|
|
156
169
|
|
|
157
170
|
### Enums
|
|
@@ -159,13 +172,14 @@ Register a function that will be called when the app resumes. The function will
|
|
|
159
172
|
|
|
160
173
|
#### BiometryType
|
|
161
174
|
|
|
162
|
-
| Members
|
|
163
|
-
|
|
|
164
|
-
|
|
|
165
|
-
|
|
|
166
|
-
|
|
|
167
|
-
|
|
|
168
|
-
|
|
|
169
|
-
|
|
|
175
|
+
| Members | Description |
|
|
176
|
+
| :------------------------------- | :----------------------------------------------- |
|
|
177
|
+
|none| No biometry is available |
|
|
178
|
+
|touchId| iOS Touch ID is available |
|
|
179
|
+
|faceId| iOS Face ID is available |
|
|
180
|
+
|fingerprintAuthentication| Android fingerprint authentication is available |
|
|
181
|
+
|faceAuthentication| Android face authentication is available |
|
|
182
|
+
|irisAuthentication| Android iris authentication is available |
|
|
170
183
|
|
|
171
184
|
</docgen-api>
|
|
185
|
+
</div>
|
|
@@ -13,110 +13,138 @@ import java.util.concurrent.Executor;
|
|
|
13
13
|
|
|
14
14
|
public class AuthActivity extends AppCompatActivity {
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
static int attemptCount;
|
|
17
|
+
static boolean allowDeviceCredential;
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
@Override
|
|
20
|
+
protected void onCreate(Bundle savedInstanceState) {
|
|
21
|
+
super.onCreate(savedInstanceState);
|
|
22
|
+
setContentView(R.layout.activity_auth_activity);
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Executor executor;
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
BiometricPrompt.PromptInfo.Builder builder = new BiometricPrompt.PromptInfo.Builder();
|
|
33
|
-
Intent intent = getIntent();
|
|
34
|
-
String title = intent.getStringExtra(WSBiometricAuth.TITLE);
|
|
35
|
-
String subtitle = intent.getStringExtra(WSBiometricAuth.SUBTITLE);
|
|
36
|
-
String description = intent.getStringExtra(WSBiometricAuth.REASON);
|
|
37
|
-
final int maxAttempts = intent.getIntExtra(WSBiometricAuth.MAX_ATTEMPTS, WSBiometricAuth.DEFAULT_MAX_ATTEMPTS);
|
|
38
|
-
allowDeviceCredential = false;
|
|
39
|
-
|
|
40
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
41
|
-
// Android docs say we should check if the device is secure before enabling device credential fallback
|
|
42
|
-
KeyguardManager manager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
|
|
43
|
-
|
|
44
|
-
if (manager.isDeviceSecure()) {
|
|
45
|
-
allowDeviceCredential = intent.getBooleanExtra(WSBiometricAuth.DEVICE_CREDENTIAL, false);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// The title must be non-null and non-empty
|
|
50
|
-
if (title == null || title.isEmpty()) {
|
|
51
|
-
title = "Authenticate";
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
builder.setTitle(title);
|
|
55
|
-
builder.setSubtitle(subtitle);
|
|
56
|
-
builder.setDescription(description);
|
|
57
|
-
builder.setDeviceCredentialAllowed(allowDeviceCredential);
|
|
26
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
27
|
+
executor = this.getMainExecutor();
|
|
28
|
+
} else {
|
|
29
|
+
executor = command -> new Handler(this.getMainLooper()).post(command);
|
|
30
|
+
}
|
|
58
31
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
32
|
+
BiometricPrompt.PromptInfo.Builder builder = new BiometricPrompt.PromptInfo.Builder();
|
|
33
|
+
Intent intent = getIntent();
|
|
34
|
+
String title = intent.getStringExtra(BiometricAuth.TITLE);
|
|
35
|
+
String subtitle = intent.getStringExtra(BiometricAuth.SUBTITLE);
|
|
36
|
+
String description = intent.getStringExtra(BiometricAuth.REASON);
|
|
37
|
+
final int maxAttempts = intent.getIntExtra(
|
|
38
|
+
BiometricAuth.MAX_ATTEMPTS,
|
|
39
|
+
BiometricAuth.DEFAULT_MAX_ATTEMPTS
|
|
40
|
+
);
|
|
41
|
+
allowDeviceCredential = false;
|
|
42
|
+
|
|
43
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
44
|
+
// Android docs say we should check if the device is secure before enabling device credential fallback
|
|
45
|
+
KeyguardManager manager = (KeyguardManager) getSystemService(
|
|
46
|
+
KEYGUARD_SERVICE
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (manager.isDeviceSecure()) {
|
|
50
|
+
allowDeviceCredential =
|
|
51
|
+
intent.getBooleanExtra(BiometricAuth.DEVICE_CREDENTIAL, false);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
BiometricPrompt prompt = new BiometricPrompt(
|
|
69
|
-
this,
|
|
70
|
-
executor,
|
|
71
|
-
new BiometricPrompt.AuthenticationCallback() {
|
|
72
|
-
@Override
|
|
73
|
-
public void onAuthenticationError(int errorCode, @NonNull CharSequence errorMessage) {
|
|
74
|
-
super.onAuthenticationError(errorCode, errorMessage);
|
|
75
|
-
finishActivity(BiometryResultType.ERROR, errorCode, (String) errorMessage);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
@Override
|
|
79
|
-
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
|
|
80
|
-
super.onAuthenticationSucceeded(result);
|
|
81
|
-
finishActivity();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
@SuppressLint("DefaultLocale")
|
|
85
|
-
@Override
|
|
86
|
-
public void onAuthenticationFailed() {
|
|
87
|
-
super.onAuthenticationFailed();
|
|
88
|
-
attemptCount += 1;
|
|
89
|
-
|
|
90
|
-
// When allowDeviceCredential is true, I can't seem to force the prompt
|
|
91
|
-
// to go away, so skip attempt counting.
|
|
92
|
-
if (!allowDeviceCredential && attemptCount > maxAttempts) {
|
|
93
|
-
finishActivity(
|
|
94
|
-
BiometryResultType.FAILURE,
|
|
95
|
-
0,
|
|
96
|
-
String.format("The user exceeded the maximum of %d attempt(s)", maxAttempts)
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
prompt.authenticate(promptInfo);
|
|
55
|
+
// The title must be non-null and non-empty
|
|
56
|
+
if (title == null || title.isEmpty()) {
|
|
57
|
+
title = "Authenticate";
|
|
104
58
|
}
|
|
105
59
|
|
|
106
|
-
|
|
107
|
-
|
|
60
|
+
builder.setTitle(title);
|
|
61
|
+
builder.setSubtitle(subtitle);
|
|
62
|
+
builder.setDescription(description);
|
|
63
|
+
builder.setDeviceCredentialAllowed(allowDeviceCredential);
|
|
64
|
+
|
|
65
|
+
// Android docs say that negative button text should not be set if device credential is allowed
|
|
66
|
+
if (!allowDeviceCredential) {
|
|
67
|
+
String negativeButtonText = intent.getStringExtra(
|
|
68
|
+
BiometricAuth.CANCEL_TITLE
|
|
69
|
+
);
|
|
70
|
+
builder.setNegativeButtonText(
|
|
71
|
+
negativeButtonText == null || negativeButtonText.isEmpty()
|
|
72
|
+
? "Cancel"
|
|
73
|
+
: negativeButtonText
|
|
74
|
+
);
|
|
108
75
|
}
|
|
109
76
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
77
|
+
BiometricPrompt.PromptInfo promptInfo = builder.build();
|
|
78
|
+
attemptCount = 0;
|
|
79
|
+
|
|
80
|
+
BiometricPrompt prompt = new BiometricPrompt(
|
|
81
|
+
this,
|
|
82
|
+
executor,
|
|
83
|
+
new BiometricPrompt.AuthenticationCallback() {
|
|
84
|
+
@Override
|
|
85
|
+
public void onAuthenticationError(
|
|
86
|
+
int errorCode,
|
|
87
|
+
@NonNull CharSequence errorMessage
|
|
88
|
+
) {
|
|
89
|
+
super.onAuthenticationError(errorCode, errorMessage);
|
|
90
|
+
finishActivity(
|
|
91
|
+
BiometryResultType.ERROR,
|
|
92
|
+
errorCode,
|
|
93
|
+
(String) errorMessage
|
|
94
|
+
);
|
|
95
|
+
}
|
|
113
96
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
97
|
+
@Override
|
|
98
|
+
public void onAuthenticationSucceeded(
|
|
99
|
+
@NonNull BiometricPrompt.AuthenticationResult result
|
|
100
|
+
) {
|
|
101
|
+
super.onAuthenticationSucceeded(result);
|
|
102
|
+
finishActivity();
|
|
103
|
+
}
|
|
118
104
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
105
|
+
@SuppressLint("DefaultLocale")
|
|
106
|
+
@Override
|
|
107
|
+
public void onAuthenticationFailed() {
|
|
108
|
+
super.onAuthenticationFailed();
|
|
109
|
+
attemptCount += 1;
|
|
110
|
+
|
|
111
|
+
// When allowDeviceCredential is true, I can't seem to force the prompt
|
|
112
|
+
// to go away, so skip attempt counting.
|
|
113
|
+
if (!allowDeviceCredential && attemptCount > maxAttempts) {
|
|
114
|
+
finishActivity(
|
|
115
|
+
BiometryResultType.FAILURE,
|
|
116
|
+
0,
|
|
117
|
+
String.format(
|
|
118
|
+
"The user exceeded the maximum of %d attempt(s)",
|
|
119
|
+
maxAttempts
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
prompt.authenticate(promptInfo);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
void finishActivity() {
|
|
131
|
+
finishActivity(BiometryResultType.SUCCESS, 0, "");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
void finishActivity(
|
|
135
|
+
BiometryResultType resultType,
|
|
136
|
+
int errorCode,
|
|
137
|
+
String errorMessage
|
|
138
|
+
) {
|
|
139
|
+
Intent intent = new Intent();
|
|
140
|
+
String prefix = BiometricAuth.RESULT_EXTRA_PREFIX;
|
|
141
|
+
|
|
142
|
+
intent
|
|
143
|
+
.putExtra(prefix + BiometricAuth.RESULT_TYPE, resultType.toString())
|
|
144
|
+
.putExtra(prefix + BiometricAuth.RESULT_ERROR_CODE, errorCode)
|
|
145
|
+
.putExtra(prefix + BiometricAuth.RESULT_ERROR_MESSAGE, errorMessage);
|
|
146
|
+
|
|
147
|
+
setResult(RESULT_OK, intent);
|
|
148
|
+
finish();
|
|
149
|
+
}
|
|
122
150
|
}
|