Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 7372170

Browse files
authored
[local_auth] The thread for executor needs to be UI thread. (#1672)
1 parent 0f80e73 commit 7372170

File tree

3 files changed

+40
-22
lines changed

3 files changed

+40
-22
lines changed

packages/local_auth/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 0.5.2
2+
* Executor thread needs to be UI thread.
3+
14
## 0.5.1
25
* Fix crash on Android versions earlier than 28.
36
* [`authenticateWithBiometrics`](https://pub.dev/documentation/local_auth/latest/local_auth/LocalAuthentication/authenticateWithBiometrics.html) will not return result unless Biometric Dialog is closed.

packages/local_auth/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import androidx.core.hardware.fingerprint.FingerprintManagerCompat;
2525
import androidx.fragment.app.FragmentActivity;
2626
import io.flutter.plugin.common.MethodCall;
27-
import java.util.concurrent.Executors;
27+
import java.util.concurrent.Executor;
2828

2929
/**
3030
* Authenticates the user with fingerprint and sends corresponding response back to Flutter.
@@ -65,6 +65,7 @@ interface AuthCompletionHandler {
6565
private final MethodCall call;
6666
private final BiometricPrompt.PromptInfo promptInfo;
6767
private final boolean isAuthSticky;
68+
private final UiThreadExecutor uiThreadExecutor;
6869
private boolean activityPaused = false;
6970

7071
public AuthenticationHelper(
@@ -75,6 +76,7 @@ public AuthenticationHelper(
7576
this.keyguardManager = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE);
7677
this.fingerprintManager = FingerprintManagerCompat.from(activity);
7778
this.isAuthSticky = call.argument("stickyAuth");
79+
this.uiThreadExecutor = new UiThreadExecutor();
7880
this.promptInfo =
7981
new BiometricPrompt.PromptInfo.Builder()
8082
.setDescription((String) call.argument("localizedReason"))
@@ -107,15 +109,12 @@ public void authenticate() {
107109
/** Start the fingerprint listener. */
108110
private void start() {
109111
activity.getApplication().registerActivityLifecycleCallbacks(this);
110-
new BiometricPrompt(activity, Executors.newSingleThreadExecutor(), this)
111-
.authenticate(promptInfo);
112+
new BiometricPrompt(activity, uiThreadExecutor, this).authenticate(promptInfo);
112113
}
113114

114115
/** Stops the fingerprint listener. */
115-
private void stop(Boolean success) {
116+
private void stop() {
116117
activity.getApplication().unregisterActivityLifecycleCallbacks(this);
117-
if (success) completionHandler.onSuccess();
118-
else completionHandler.onFailure();
119118
}
120119

121120
@SuppressLint("SwitchIntDef")
@@ -133,17 +132,24 @@ public void onAuthenticationError(int errorCode, CharSequence errString) {
133132
"The operation was canceled because ERROR_LOCKOUT occurred too many times. Biometric authentication is disabled until the user unlocks with strong authentication (PIN/Pattern/Password)");
134133
break;
135134
case BiometricPrompt.ERROR_CANCELED:
135+
// If we are doing sticky auth and the activity has been paused,
136+
// ignore this error. We will start listening again when resumed.
136137
if (activityPaused && isAuthSticky) {
137138
return;
139+
} else {
140+
completionHandler.onFailure();
138141
}
142+
break;
139143
default:
144+
completionHandler.onFailure();
140145
}
141-
stop(false);
146+
stop();
142147
}
143148

144149
@Override
145150
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
146-
stop(true);
151+
completionHandler.onSuccess();
152+
stop();
147153
}
148154

149155
@Override
@@ -164,19 +170,17 @@ public void onActivityPaused(Activity ignored) {
164170
public void onActivityResumed(Activity ignored) {
165171
if (isAuthSticky) {
166172
activityPaused = false;
167-
final BiometricPrompt prompt =
168-
new BiometricPrompt(activity, Executors.newSingleThreadExecutor(), this);
173+
final BiometricPrompt prompt = new BiometricPrompt(activity, uiThreadExecutor, this);
169174
// When activity is resuming, we cannot show the prompt right away. We need to post it to the
170175
// UI queue.
171-
new Handler(Looper.myLooper())
172-
.postDelayed(
173-
new Runnable() {
174-
@Override
175-
public void run() {
176-
prompt.authenticate(promptInfo);
177-
}
178-
},
179-
100);
176+
uiThreadExecutor.handler.postDelayed(
177+
new Runnable() {
178+
@Override
179+
public void run() {
180+
prompt.authenticate(promptInfo);
181+
}
182+
},
183+
100);
180184
}
181185
}
182186

@@ -193,15 +197,17 @@ private void showGoToSettingsDialog() {
193197
new OnClickListener() {
194198
@Override
195199
public void onClick(DialogInterface dialog, int which) {
196-
stop(false);
200+
completionHandler.onFailure();
201+
stop();
197202
activity.startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
198203
}
199204
};
200205
OnClickListener cancelHandler =
201206
new OnClickListener() {
202207
@Override
203208
public void onClick(DialogInterface dialog, int which) {
204-
stop(false);
209+
completionHandler.onFailure();
210+
stop();
205211
}
206212
};
207213
new AlertDialog.Builder(context)
@@ -228,4 +234,13 @@ public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {}
228234

229235
@Override
230236
public void onActivityDestroyed(Activity activity) {}
237+
238+
private static class UiThreadExecutor implements Executor {
239+
public final Handler handler = new Handler(Looper.getMainLooper());
240+
241+
@Override
242+
public void execute(Runnable command) {
243+
handler.post(command);
244+
}
245+
}
231246
}

packages/local_auth/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for Android and iOS device authentication sensors
33
such as Fingerprint Reader and Touch ID.
44
author: Flutter Team <flutter-dev@googlegroups.com>
55
homepage: https://github.com/flutter/plugins/tree/master/packages/local_auth
6-
version: 0.5.1
6+
version: 0.5.2
77

88
flutter:
99
plugin:

0 commit comments

Comments
 (0)