diff --git a/OAT.xml b/OAT.xml index b1eb90c1829bb8fd8b59934e7f374034fe3536f9..63424030b897949c473b49253c9bb17319a4b61e 100644 --- a/OAT.xml +++ b/OAT.xml @@ -207,6 +207,15 @@ + + + + + + + + + diff --git a/packages/local_auth/local_auth/CHANGELOG.md b/packages/local_auth/local_auth/CHANGELOG.md index d97973a32ca462485a2536a89fef14c01dbbe7d5..9a243e831048c1b8ac691c14c70abce3aa871dbf 100644 --- a/packages/local_auth/local_auth/CHANGELOG.md +++ b/packages/local_auth/local_auth/CHANGELOG.md @@ -1,11 +1,3 @@ -## 2.1.7 - -* Adds pub topics to package metadata. -* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. -* Aligns Dart and Flutter SDK constraints. -* Fixes stale ignore: prefer_const_constructors. -* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0. - ## 2.1.6 * Updates iOS minimum version in README. diff --git a/packages/local_auth/local_auth/README.md b/packages/local_auth/local_auth/README.md index 01355ef85200f7d23d5b57430efdd255e1d109e8..1fc9ce3f4f007a3c2037cd5e8cf4674e4937618a 100644 --- a/packages/local_auth/local_auth/README.md +++ b/packages/local_auth/local_auth/README.md @@ -1,6 +1,6 @@ # local_auth - + This Flutter plugin provides means to perform local, on-device authentication of the user. diff --git a/packages/local_auth/local_auth/example/.pluginToolsConfig.yaml b/packages/local_auth/local_auth/example/.pluginToolsConfig.yaml deleted file mode 100644 index 3b6017b7609aa71c5a9ca78ea1638964c6ca908f..0000000000000000000000000000000000000000 --- a/packages/local_auth/local_auth/example/.pluginToolsConfig.yaml +++ /dev/null @@ -1,4 +0,0 @@ -buildFlags: - _pluginToolsConfigGlobalKey: - - "--no-tree-shake-icons" - - "--dart-define=buildmode=testing" diff --git a/packages/local_auth/local_auth/example/android/app/build.gradle b/packages/local_auth/local_auth/example/android/app/build.gradle index 0520ad0e2b6e30165b20aa8a65ee75fec4323a20..751b11824ada05933a4a57f1e3d1f7a3bceb6d44 100644 --- a/packages/local_auth/local_auth/example/android/app/build.gradle +++ b/packages/local_auth/local_auth/example/android/app/build.gradle @@ -25,18 +25,19 @@ apply plugin: 'com.android.application' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - namespace 'io.flutter.plugins.localauthexample' compileSdkVersion flutter.compileSdkVersion + lintOptions { + disable 'InvalidPackage' + } defaultConfig { applicationId "io.flutter.plugins.localauthexample" - minSdkVersion flutter.minSdkVersion + minSdkVersion 16 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - multiDexEnabled true } buildTypes { @@ -44,9 +45,6 @@ android { signingConfig signingConfigs.debug } } - lint { - disable 'InvalidPackage' - } } flutter { diff --git a/packages/local_auth/local_auth/example/android/app/gradle/wrapper/gradle-wrapper.properties b/packages/local_auth/local_auth/example/android/app/gradle/wrapper/gradle-wrapper.properties index 31cca49130883015317c31b7d73e024d992422bf..29e41345763549986272da1c6e1dd4d6f97d21c1 100644 --- a/packages/local_auth/local_auth/example/android/app/gradle/wrapper/gradle-wrapper.properties +++ b/packages/local_auth/local_auth/example/android/app/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/local_auth/local_auth/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java b/packages/local_auth/local_auth/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java index 0f0c1464e0ee2e7fb6ebaaa28bacd872d3712865..0f4298dca155143f5a80759ab3614cde1a11662a 100644 --- a/packages/local_auth/local_auth/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java +++ b/packages/local_auth/local_auth/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java @@ -9,13 +9,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/* - * Annotation to aid repository tooling in determining if a test is - * a native java unit test or a java class with a dart integration. - * - * See: https://github.com/flutter/flutter/wiki/Plugin-Tests#enabling-android-ui-tests - * for more infomation. - */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface DartIntegrationTest {} diff --git a/packages/local_auth/local_auth/example/android/build.gradle b/packages/local_auth/local_auth/example/android/build.gradle index 6ae7ddc2ce54496a9b2b34652205e3e0c7ff0d14..3593d9636555a74219cb73e99b1b1140702674bb 100644 --- a/packages/local_auth/local_auth/example/android/build.gradle +++ b/packages/local_auth/local_auth/example/android/build.gradle @@ -5,18 +5,12 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.android.tools.build:gradle:7.3.1' } } allprojects { repositories { - // See https://github.com/flutter/flutter/wiki/Plugins-and-Packages-repository-structure#gradle-structure for more info. - def artifactRepoKey = 'ARTIFACT_HUB_REPOSITORY' - if (System.getenv().containsKey(artifactRepoKey)) { - println "Using artifact hub" - maven { url System.getenv(artifactRepoKey) } - } google() mavenCentral() } @@ -30,6 +24,6 @@ subprojects { project.evaluationDependsOn(':app') } -tasks.register("clean", Delete) { +task clean(type: Delete) { delete rootProject.buildDir } diff --git a/packages/local_auth/local_auth/example/android/gradle.properties b/packages/local_auth/local_auth/example/android/gradle.properties index 598d13fee446372f156ecc38527b54c7cdcc8e3b..e5611e4c7fa006777c9ce7be6dfc3e1cf180b12c 100644 --- a/packages/local_auth/local_auth/example/android/gradle.properties +++ b/packages/local_auth/local_auth/example/android/gradle.properties @@ -1,3 +1,4 @@ org.gradle.jvmargs=-Xmx4G android.useAndroidX=true android.enableJetifier=true +android.enableR8=true diff --git a/packages/local_auth/local_auth/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/local_auth/local_auth/example/android/gradle/wrapper/gradle-wrapper.properties index fe8a7a0dc9bddd03166bf71eec8db383133defab..f5c5c374a4b77820d29c6a077267f5105d54dcd4 100644 --- a/packages/local_auth/local_auth/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/local_auth/local_auth/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/packages/local_auth/local_auth/example/android/settings.gradle b/packages/local_auth/local_auth/example/android/settings.gradle index 0360c9f26f64805d2ee7e49c73625ce12253ad35..115da6cb4f4d8eb839315733fcdad2437c0c4af3 100644 --- a/packages/local_auth/local_auth/example/android/settings.gradle +++ b/packages/local_auth/local_auth/example/android/settings.gradle @@ -13,16 +13,3 @@ plugins.each { name, path -> include ":$name" project(":$name").projectDir = pluginDirectory } - -// See https://github.com/flutter/flutter/wiki/Plugins-and-Packages-repository-structure#gradle-structure for more info. -buildscript { - repositories { - maven { - url "https://plugins.gradle.org/m2/" - } - } - dependencies { - classpath "gradle.plugin.com.google.cloud.artifactregistry:artifactregistry-gradle-plugin:2.2.1" - } -} -apply plugin: "com.google.cloud.artifactregistry.gradle-plugin" diff --git a/packages/local_auth/local_auth/example/ios/Runner/Info.plist b/packages/local_auth/local_auth/example/ios/Runner/Info.plist index 2dc92f5dff1c51f424e7d4bb410624d85196e152..1af663b3f83c7ecbafda5c27b52d2593518e0bec 100644 --- a/packages/local_auth/local_auth/example/ios/Runner/Info.plist +++ b/packages/local_auth/local_auth/example/ios/Runner/Info.plist @@ -43,6 +43,8 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + UIViewControllerBasedStatusBarAppearance + NSFaceIDUsageDescription App needs to authenticate using faces. CADisableMinimumFrameDurationOnPhone diff --git a/packages/local_auth/local_auth/example/lib/main.dart b/packages/local_auth/local_auth/example/lib/main.dart index f8e08863b564c80467fafc6dcbc1c508a2d54f3f..146a5d92b29c7bd737994a412531b3747234a387 100644 --- a/packages/local_auth/local_auth/example/lib/main.dart +++ b/packages/local_auth/local_auth/example/lib/main.dart @@ -15,7 +15,7 @@ void main() { } class MyApp extends StatefulWidget { - const MyApp({super.key}); + const MyApp({Key? key}) : super(key: key); @override State createState() => _MyAppState(); @@ -183,9 +183,11 @@ class _MyAppState extends State { if (_isAuthenticating) ElevatedButton( onPressed: _cancelAuthentication, - child: const Row( + // TODO(goderbauer): Make this const when this package requires Flutter 3.8 or later. + // ignore: prefer_const_constructors + child: Row( mainAxisSize: MainAxisSize.min, - children: [ + children: const [ Text('Cancel Authentication'), Icon(Icons.cancel), ], @@ -196,9 +198,11 @@ class _MyAppState extends State { children: [ ElevatedButton( onPressed: _authenticate, - child: const Row( + // TODO(goderbauer): Make this const when this package requires Flutter 3.8 or later. + // ignore: prefer_const_constructors + child: Row( mainAxisSize: MainAxisSize.min, - children: [ + children: const [ Text('Authenticate'), Icon(Icons.perm_device_information), ], diff --git a/packages/local_auth/local_auth/example/lib/readme_excerpts.dart b/packages/local_auth/local_auth/example/lib/readme_excerpts.dart index 8ae4a3c34178fbea601bc39c37c41a4d87a1272f..ccccf5c50ae90a48c8d8adb9ab50046063c4187c 100644 --- a/packages/local_auth/local_auth/example/lib/readme_excerpts.dart +++ b/packages/local_auth/local_auth/example/lib/readme_excerpts.dart @@ -28,7 +28,7 @@ void main() { } class MyApp extends StatefulWidget { - const MyApp({super.key}); + const MyApp({Key? key}) : super(key: key); @override State createState() => _MyAppState(); diff --git a/packages/local_auth/local_auth/example/pubspec.yaml b/packages/local_auth/local_auth/example/pubspec.yaml index fed63a9c674b660c5f98ff22d95926afc7ed0946..e02065b6d16fa9c21d36c8c326a13a5d18c38e76 100644 --- a/packages/local_auth/local_auth/example/pubspec.yaml +++ b/packages/local_auth/local_auth/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use the local_auth plugin. publish_to: none environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.10.0" + sdk: ">=2.14.0 <3.0.0" + flutter: ">=3.0.0" dependencies: flutter: @@ -21,6 +21,8 @@ dependencies: dev_dependencies: build_runner: ^2.1.10 + flutter_driver: + sdk: flutter flutter_test: sdk: flutter integration_test: diff --git a/packages/local_auth/local_auth/lib/src/local_auth.dart b/packages/local_auth/local_auth/lib/src/local_auth.dart index e369f67187a5bbd1fd3a172062cf4fd6663fe9ac..9a984a2b88de754e4840078acff459bf5cbd6e2f 100644 --- a/packages/local_auth/local_auth/lib/src/local_auth.dart +++ b/packages/local_auth/local_auth/lib/src/local_auth.dart @@ -15,6 +15,7 @@ import 'package:local_auth_android/local_auth_android.dart'; import 'package:local_auth_ios/local_auth_ios.dart'; import 'package:local_auth_platform_interface/local_auth_platform_interface.dart'; import 'package:local_auth_windows/local_auth_windows.dart'; +import 'package:local_auth_ohos/local_auth_ohos.dart'; /// A Flutter plugin for authenticating the user identity locally. class LocalAuthentication { @@ -41,7 +42,8 @@ class LocalAuthentication { Iterable authMessages = const [ IOSAuthMessages(), AndroidAuthMessages(), - WindowsAuthMessages() + WindowsAuthMessages(), + OhosAuthMessages() ], AuthenticationOptions options = const AuthenticationOptions()}) { return LocalAuthPlatform.instance.authenticate( diff --git a/packages/local_auth/local_auth/pubspec.yaml b/packages/local_auth/local_auth/pubspec.yaml index a367c96ca56d0bf7234f3d71d8d245c167321ea5..0a393d6211e38bea4b3f75a908034d3def6d24c8 100644 --- a/packages/local_auth/local_auth/pubspec.yaml +++ b/packages/local_auth/local_auth/pubspec.yaml @@ -3,11 +3,11 @@ description: Flutter plugin for Android and iOS devices to allow local authentication via fingerprint, touch ID, face ID, passcode, pin, or pattern. repository: https://github.com/flutter/packages/tree/main/packages/local_auth/local_auth issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+local_auth%22 -version: 2.1.7 +version: 2.1.6 environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.10.0" + sdk: ">=2.14.0 <3.0.0" + flutter: ">=3.0.0" flutter: plugin: @@ -18,6 +18,8 @@ flutter: default_package: local_auth_ios windows: default_package: local_auth_windows + ohos: + default_package: local_auth_ohos dependencies: flutter: @@ -26,16 +28,15 @@ dependencies: local_auth_ios: ^1.0.1 local_auth_platform_interface: ^1.0.1 local_auth_windows: ^1.0.0 + local_auth_ohos: + path: ../local_auth_ohos dev_dependencies: + flutter_driver: + sdk: flutter flutter_test: sdk: flutter integration_test: sdk: flutter - mockito: 5.4.1 + mockito: ^5.1.0 plugin_platform_interface: ^2.1.2 - -topics: - - authentication - - biometrics - - local-auth diff --git a/packages/local_auth/local_auth_android/CHANGELOG.md b/packages/local_auth/local_auth_android/CHANGELOG.md index 9c62c872ca8a8507264284f6db87fc2c12dc8283..b74748c3f2e992990311f9c9577cb48b1e7135a2 100644 --- a/packages/local_auth/local_auth_android/CHANGELOG.md +++ b/packages/local_auth/local_auth_android/CHANGELOG.md @@ -1,68 +1,5 @@ -## 1.0.34 +## NEXT -* Updates pigeon to 11.0.0 and removes enum wrappers. - -## 1.0.33 - -* Adds pub topics to package metadata. -* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. - -## 1.0.32 - -* Fixes stale ignore: prefer_const_constructors. -* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0. -* Updates androidx.fragment version to 1.6.0. - -## 1.0.31 - -* Updates androidx.fragment version to 1.5.7. -* Updates androidx.core version to 1.10.1. - -## 1.0.30 - -* Updates androidx.fragment version to 1.5.6 - -## 1.0.29 - -* Fixes a regression in 1.0.23 that caused canceled auths to return success. -* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. - -## 1.0.28 - -* Removes unused resources as indicated by Android lint warnings. - -## 1.0.27 - -* Fixes compatibility with AGP versions older than 4.2. - -## 1.0.26 - -* Adds `targetCompatibilty` matching `sourceCompatibility` for older toolchains. - -## 1.0.25 - -* Adds a namespace for compatibility with AGP 8.0. - -## 1.0.24 - -* Fixes `getEnrolledBiometrics` return value handling. - -## 1.0.23 - -* Switches internals to Pigeon and fixes Java warnings. - -## 1.0.22 - -* Sets an explicit Java compatibility version. - -## 1.0.21 - -* Clarifies explanation of endorsement in README. -* Aligns Dart and Flutter SDK constraints. - -## 1.0.20 - -* Fixes compilation warnings. * Updates compileSdkVersion to 33. ## 1.0.19 diff --git a/packages/local_auth/local_auth_android/README.md b/packages/local_auth/local_auth_android/README.md index 047e82ef64b376c880adce9134baffe3b467a9bc..07244912f23100f3bcecc6c38ccfa4a7a1e86237 100644 --- a/packages/local_auth/local_auth_android/README.md +++ b/packages/local_auth/local_auth_android/README.md @@ -5,11 +5,7 @@ The Android implementation of [`local_auth`][1]. ## Usage This package is [endorsed][2], which means you can simply use `local_auth` -normally. This package will be automatically included in your app when you do, -so you do not need to add it to your `pubspec.yaml`. - -However, if you `import` this package to use any of its APIs directly, you -should add it to your `pubspec.yaml` as usual. +normally. This package will be automatically included in your app when you do. [1]: https://pub.dev/packages/local_auth -[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin +[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin \ No newline at end of file diff --git a/packages/local_auth/local_auth_android/android/build.gradle b/packages/local_auth/local_auth_android/android/build.gradle index b55df15f3c9bdd598a195793d2aafa60c3bfa2bd..8e116709d6cc19e4699ec93f9f4e2cee2b7fc3ec 100644 --- a/packages/local_auth/local_auth_android/android/build.gradle +++ b/packages/local_auth/local_auth_android/android/build.gradle @@ -22,26 +22,15 @@ rootProject.allprojects { apply plugin: 'com.android.library' android { - // Conditional for compatibility with AGP <4.2. - if (project.android.hasProperty("namespace")) { - namespace 'io.flutter.plugins.localauth' - } compileSdkVersion 33 defaultConfig { minSdkVersion 16 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - lintOptions { - checkAllWarnings true - warningsAsErrors true disable 'AndroidGradlePluginVersion', 'InvalidPackage', 'GradleDependency' + baseline file("lint-baseline.xml") } @@ -59,16 +48,13 @@ android { } dependencies { - api "androidx.core:core:1.10.1" + api "androidx.core:core:1.9.0" api "androidx.biometric:biometric:1.1.0" - api "androidx.fragment:fragment:1.6.0" + api "androidx.fragment:fragment:1.5.5" testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-inline:5.0.0' - testImplementation 'org.robolectric:robolectric:4.10.3' + testImplementation 'org.robolectric:robolectric:4.5' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:rules:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' - // TODO(camsim99): org.jetbrains.kotlin:kotlin-bom artifact purpose is to align kotlin stdlib and related code versions. - // This should be removed when https://github.com/flutter/flutter/issues/125062 is fixed. - implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.10")) } diff --git a/packages/local_auth/local_auth_android/android/src/main/AndroidManifest.xml b/packages/local_auth/local_auth_android/android/src/main/AndroidManifest.xml index ef323b4281c098896f18756d2a615f1ddcb0f0b2..63f75079e00da9da09a97fcdf9269b6ecd06a9a1 100644 --- a/packages/local_auth/local_auth_android/android/src/main/AndroidManifest.xml +++ b/packages/local_auth/local_auth_android/android/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ + diff --git a/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java b/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java index fcb32c546b19861f60940b798fbc2148547e18fd..c30f879d2c7f990c08128da0136d12ed99c7d738 100644 --- a/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java +++ b/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java @@ -8,6 +8,7 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.Application; import android.content.Context; +import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.os.Bundle; @@ -25,6 +26,7 @@ import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; +import io.flutter.plugin.common.MethodCall; import java.util.concurrent.Executor; /** @@ -33,20 +35,35 @@ import java.util.concurrent.Executor; *

One instance per call is generated to ensure readable separation of executable paths across * method calls. */ +@SuppressWarnings("deprecation") class AuthenticationHelper extends BiometricPrompt.AuthenticationCallback implements Application.ActivityLifecycleCallbacks, DefaultLifecycleObserver { /** The callback that handles the result of this authentication process. */ interface AuthCompletionHandler { - /** Called when authentication attempt is complete. */ - void complete(Messages.AuthResult authResult); + /** Called when authentication was successful. */ + void onSuccess(); + + /** + * Called when authentication failed due to user. For instance, when user cancels the auth or + * quits the app. + */ + void onFailure(); + + /** + * Called when authentication fails due to non-user related problems such as system errors, + * phone not having a FP reader etc. + * + * @param code The error code to be returned to Flutter app. + * @param error The description of the error. + */ + void onError(String code, String error); } // This is null when not using v2 embedding; private final Lifecycle lifecycle; private final FragmentActivity activity; private final AuthCompletionHandler completionHandler; - private final boolean useErrorDialogs; - private final Messages.AuthStrings strings; + private final MethodCall call; private final BiometricPrompt.PromptInfo promptInfo; private final boolean isAuthSticky; private final UiThreadExecutor uiThreadExecutor; @@ -56,24 +73,23 @@ class AuthenticationHelper extends BiometricPrompt.AuthenticationCallback AuthenticationHelper( Lifecycle lifecycle, FragmentActivity activity, - @NonNull Messages.AuthOptions options, - @NonNull Messages.AuthStrings strings, - @NonNull AuthCompletionHandler completionHandler, + MethodCall call, + AuthCompletionHandler completionHandler, boolean allowCredentials) { this.lifecycle = lifecycle; this.activity = activity; this.completionHandler = completionHandler; - this.strings = strings; - this.isAuthSticky = options.getSticky(); - this.useErrorDialogs = options.getUseErrorDialgs(); + this.call = call; + this.isAuthSticky = call.argument("stickyAuth"); this.uiThreadExecutor = new UiThreadExecutor(); BiometricPrompt.PromptInfo.Builder promptBuilder = new BiometricPrompt.PromptInfo.Builder() - .setDescription(strings.getReason()) - .setTitle(strings.getSignInTitle()) - .setSubtitle(strings.getBiometricHint()) - .setConfirmationRequired(options.getSensitiveTransaction()); + .setDescription((String) call.argument("localizedReason")) + .setTitle((String) call.argument("signInTitle")) + .setSubtitle((String) call.argument("biometricHint")) + .setConfirmationRequired((Boolean) call.argument("sensitiveTransaction")) + .setConfirmationRequired((Boolean) call.argument("sensitiveTransaction")); int allowedAuthenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK @@ -82,7 +98,7 @@ class AuthenticationHelper extends BiometricPrompt.AuthenticationCallback if (allowCredentials) { allowedAuthenticators |= BiometricManager.Authenticators.DEVICE_CREDENTIAL; } else { - promptBuilder.setNegativeButtonText(strings.getCancelButton()); + promptBuilder.setNegativeButtonText((String) call.argument("cancelButton")); } promptBuilder.setAllowedAuthenticators(allowedAuthenticators); @@ -119,35 +135,40 @@ class AuthenticationHelper extends BiometricPrompt.AuthenticationCallback @SuppressLint("SwitchIntDef") @Override - public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { + public void onAuthenticationError(int errorCode, CharSequence errString) { switch (errorCode) { case BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL: - if (useErrorDialogs) { + if (call.argument("useErrorDialogs")) { showGoToSettingsDialog( - strings.getDeviceCredentialsRequiredTitle(), - strings.getDeviceCredentialsSetupDescription()); + (String) call.argument("deviceCredentialsRequired"), + (String) call.argument("deviceCredentialsSetupDescription")); return; } - completionHandler.complete(Messages.AuthResult.ERROR_NOT_AVAILABLE); + completionHandler.onError("NotAvailable", "Security credentials not available."); break; case BiometricPrompt.ERROR_NO_SPACE: case BiometricPrompt.ERROR_NO_BIOMETRICS: - if (useErrorDialogs) { + if (call.argument("useErrorDialogs")) { showGoToSettingsDialog( - strings.getBiometricRequiredTitle(), strings.getGoToSettingsDescription()); + (String) call.argument("biometricRequired"), + (String) call.argument("goToSettingDescription")); return; } - completionHandler.complete(Messages.AuthResult.ERROR_NOT_ENROLLED); + completionHandler.onError("NotEnrolled", "No Biometrics enrolled on this device."); break; case BiometricPrompt.ERROR_HW_UNAVAILABLE: case BiometricPrompt.ERROR_HW_NOT_PRESENT: - completionHandler.complete(Messages.AuthResult.ERROR_NOT_AVAILABLE); + completionHandler.onError("NotAvailable", "Security credentials not available."); break; case BiometricPrompt.ERROR_LOCKOUT: - completionHandler.complete(Messages.AuthResult.ERROR_LOCKED_OUT_TEMPORARILY); + completionHandler.onError( + "LockedOut", + "The operation was canceled because the API is locked out due to too many attempts. This occurs after 5 failed attempts, and lasts for 30 seconds."); break; case BiometricPrompt.ERROR_LOCKOUT_PERMANENT: - completionHandler.complete(Messages.AuthResult.ERROR_LOCKED_OUT_PERMANENTLY); + completionHandler.onError( + "PermanentlyLockedOut", + "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)"); break; case BiometricPrompt.ERROR_CANCELED: // If we are doing sticky auth and the activity has been paused, @@ -155,18 +176,18 @@ class AuthenticationHelper extends BiometricPrompt.AuthenticationCallback if (activityPaused && isAuthSticky) { return; } else { - completionHandler.complete(Messages.AuthResult.FAILURE); + completionHandler.onFailure(); } break; default: - completionHandler.complete(Messages.AuthResult.FAILURE); + completionHandler.onFailure(); } stop(); } @Override - public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) { - completionHandler.complete(Messages.AuthResult.SUCCESS); + public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) { + completionHandler.onSuccess(); stop(); } @@ -191,7 +212,13 @@ class AuthenticationHelper extends BiometricPrompt.AuthenticationCallback final BiometricPrompt prompt = new BiometricPrompt(activity, uiThreadExecutor, this); // When activity is resuming, we cannot show the prompt right away. We need to post it to the // UI queue. - uiThreadExecutor.handler.post(() -> prompt.authenticate(promptInfo)); + uiThreadExecutor.handler.post( + new Runnable() { + @Override + public void run() { + prompt.authenticate(promptInfo); + } + }); } } @@ -209,26 +236,32 @@ class AuthenticationHelper extends BiometricPrompt.AuthenticationCallback @SuppressLint("InflateParams") private void showGoToSettingsDialog(String title, String descriptionText) { View view = LayoutInflater.from(activity).inflate(R.layout.go_to_setting, null, false); - TextView message = view.findViewById(R.id.fingerprint_required); - TextView description = view.findViewById(R.id.go_to_setting_description); + TextView message = (TextView) view.findViewById(R.id.fingerprint_required); + TextView description = (TextView) view.findViewById(R.id.go_to_setting_description); message.setText(title); description.setText(descriptionText); Context context = new ContextThemeWrapper(activity, R.style.AlertDialogCustom); OnClickListener goToSettingHandler = - (dialog, which) -> { - completionHandler.complete(Messages.AuthResult.FAILURE); - stop(); - activity.startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS)); + new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + completionHandler.onFailure(); + stop(); + activity.startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS)); + } }; OnClickListener cancelHandler = - (dialog, which) -> { - completionHandler.complete(Messages.AuthResult.FAILURE); - stop(); + new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + completionHandler.onFailure(); + stop(); + } }; new AlertDialog.Builder(context) .setView(view) - .setPositiveButton(strings.getGoToSettingsButton(), goToSettingHandler) - .setNegativeButton(strings.getCancelButton(), cancelHandler) + .setPositiveButton((String) call.argument("goToSetting"), goToSettingHandler) + .setNegativeButton((String) call.argument("cancelButton"), cancelHandler) .setCancelable(false) .show(); } @@ -262,7 +295,7 @@ class AuthenticationHelper extends BiometricPrompt.AuthenticationCallback @Override public void onCreate(@NonNull LifecycleOwner owner) {} - static class UiThreadExecutor implements Executor { + private static class UiThreadExecutor implements Executor { final Handler handler = new Handler(Looper.getMainLooper()); @Override diff --git a/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java b/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java index 7ed2c04a8f6ab8c4d3cc430773794c7f7843dae4..e545df01e7c0948feda76307f2e554add0633979 100644 --- a/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java +++ b/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java @@ -21,17 +21,14 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; import io.flutter.plugin.common.PluginRegistry; +import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.plugins.localauth.AuthenticationHelper.AuthCompletionHandler; -import io.flutter.plugins.localauth.Messages.AuthClassification; -import io.flutter.plugins.localauth.Messages.AuthClassificationWrapper; -import io.flutter.plugins.localauth.Messages.AuthOptions; -import io.flutter.plugins.localauth.Messages.AuthResult; -import io.flutter.plugins.localauth.Messages.AuthStrings; -import io.flutter.plugins.localauth.Messages.LocalAuthApi; -import io.flutter.plugins.localauth.Messages.Result; import java.util.ArrayList; -import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -39,7 +36,9 @@ import java.util.concurrent.atomic.AtomicBoolean; * *

Instantiate this in an add to app scenario to gracefully handle activity and context changes. */ -public class LocalAuthPlugin implements FlutterPlugin, ActivityAware, LocalAuthApi { +@SuppressWarnings("deprecation") +public class LocalAuthPlugin implements MethodCallHandler, FlutterPlugin, ActivityAware { + private static final String CHANNEL_NAME = "plugins.flutter.io/local_auth_android"; private static final int LOCK_REQUEST_CODE = 221; private Activity activity; private AuthenticationHelper authHelper; @@ -47,19 +46,20 @@ public class LocalAuthPlugin implements FlutterPlugin, ActivityAware, LocalAuthA @VisibleForTesting final AtomicBoolean authInProgress = new AtomicBoolean(false); // These are null when not using v2 embedding. + private MethodChannel channel; private Lifecycle lifecycle; private BiometricManager biometricManager; private KeyguardManager keyguardManager; - Result lockRequestResult; + private Result lockRequestResult; private final PluginRegistry.ActivityResultListener resultListener = new PluginRegistry.ActivityResultListener() { @Override public boolean onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == LOCK_REQUEST_CODE) { if (resultCode == RESULT_OK && lockRequestResult != null) { - onAuthenticationCompleted(lockRequestResult, AuthResult.SUCCESS); + authenticateSuccess(lockRequestResult); } else { - onAuthenticationCompleted(lockRequestResult, AuthResult.FAILURE); + authenticateFail(lockRequestResult); } lockRequestResult = null; } @@ -73,13 +73,16 @@ public class LocalAuthPlugin implements FlutterPlugin, ActivityAware, LocalAuthA *

Calling this will register the plugin with the passed registrar. However, plugins * initialized this way won't react to changes in activity or context. * - * @param registrar provides access to necessary plugin context. + * @param registrar attaches this plugin's {@link + * io.flutter.plugin.common.MethodChannel.MethodCallHandler} to the registrar's {@link + * io.flutter.plugin.common.BinaryMessenger}. */ @SuppressWarnings("deprecation") - public static void registerWith(@NonNull PluginRegistry.Registrar registrar) { + public static void registerWith(Registrar registrar) { + final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL_NAME); final LocalAuthPlugin plugin = new LocalAuthPlugin(); plugin.activity = registrar.activity(); - LocalAuthApi.setup(registrar.messenger(), plugin); + channel.setMethodCallHandler(plugin); registrar.addActivityResultListener(plugin.resultListener); } @@ -90,112 +93,176 @@ public class LocalAuthPlugin implements FlutterPlugin, ActivityAware, LocalAuthA */ public LocalAuthPlugin() {} - public @NonNull Boolean isDeviceSupported() { - return isDeviceSecure() || canAuthenticateWithBiometrics(); - } - - public @NonNull Boolean deviceCanSupportBiometrics() { - return hasBiometricHardware(); - } - - public @NonNull List getEnrolledBiometrics() { - ArrayList biometrics = new ArrayList<>(); - if (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) - == BiometricManager.BIOMETRIC_SUCCESS) { - biometrics.add(wrappedBiometric(AuthClassification.WEAK)); - } - if (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) - == BiometricManager.BIOMETRIC_SUCCESS) { - biometrics.add(wrappedBiometric(AuthClassification.STRONG)); - } - return biometrics; - } - - private @NonNull AuthClassificationWrapper wrappedBiometric(AuthClassification value) { - return new AuthClassificationWrapper.Builder().setValue(value).build(); - } - - public @NonNull Boolean stopAuthentication() { - try { - if (authHelper != null && authInProgress.get()) { - authHelper.stopAuthentication(); - authHelper = null; - } - authInProgress.set(false); - return true; - } catch (Exception e) { - return false; + @Override + public void onMethodCall(MethodCall call, @NonNull final Result result) { + switch (call.method) { + case "authenticate": + authenticate(call, result); + break; + case "getEnrolledBiometrics": + getEnrolledBiometrics(result); + break; + case "isDeviceSupported": + isDeviceSupported(result); + break; + case "stopAuthentication": + stopAuthentication(result); + break; + case "deviceSupportsBiometrics": + deviceSupportsBiometrics(result); + break; + default: + result.notImplemented(); + break; } } - public void authenticate( - @NonNull AuthOptions options, - @NonNull AuthStrings strings, - @NonNull Result result) { + /* + * Starts authentication process + */ + private void authenticate(MethodCall call, final Result result) { if (authInProgress.get()) { - result.success(AuthResult.ERROR_ALREADY_IN_PROGRESS); + result.error("auth_in_progress", "Authentication in progress", null); return; } if (activity == null || activity.isFinishing()) { - result.success(AuthResult.ERROR_NO_ACTIVITY); + result.error("no_activity", "local_auth plugin requires a foreground activity", null); return; } if (!(activity instanceof FragmentActivity)) { - result.success(AuthResult.ERROR_NOT_FRAGMENT_ACTIVITY); + result.error( + "no_fragment_activity", + "local_auth plugin requires activity to be a FragmentActivity.", + null); return; } if (!isDeviceSupported()) { - result.success(AuthResult.ERROR_NOT_AVAILABLE); + authInProgress.set(false); + result.error("NotAvailable", "Required security features not enabled", null); return; } authInProgress.set(true); AuthCompletionHandler completionHandler = createAuthCompletionHandler(result); - boolean allowCredentials = !options.getBiometricOnly() && canAuthenticateWithDeviceCredential(); + boolean isBiometricOnly = call.argument("biometricOnly"); + boolean allowCredentials = !isBiometricOnly && canAuthenticateWithDeviceCredential(); - sendAuthenticationRequest(options, strings, allowCredentials, completionHandler); + sendAuthenticationRequest(call, completionHandler, allowCredentials); + return; } @VisibleForTesting - public @NonNull AuthCompletionHandler createAuthCompletionHandler( - @NonNull final Result result) { - return authResult -> onAuthenticationCompleted(result, authResult); + public AuthCompletionHandler createAuthCompletionHandler(final Result result) { + return new AuthCompletionHandler() { + @Override + public void onSuccess() { + authenticateSuccess(result); + } + + @Override + public void onFailure() { + authenticateFail(result); + } + + @Override + public void onError(String code, String error) { + if (authInProgress.compareAndSet(true, false)) { + result.error(code, error, null); + } + } + }; } @VisibleForTesting public void sendAuthenticationRequest( - @NonNull AuthOptions options, - @NonNull AuthStrings strings, - boolean allowCredentials, - @NonNull AuthCompletionHandler completionHandler) { + MethodCall call, AuthCompletionHandler completionHandler, boolean allowCredentials) { authHelper = new AuthenticationHelper( - lifecycle, - (FragmentActivity) activity, - options, - strings, - completionHandler, - allowCredentials); + lifecycle, (FragmentActivity) activity, call, completionHandler, allowCredentials); authHelper.authenticate(); } - void onAuthenticationCompleted(Result result, AuthResult value) { + private void authenticateSuccess(Result result) { if (authInProgress.compareAndSet(true, false)) { - result.success(value); + result.success(true); + } + } + + private void authenticateFail(Result result) { + if (authInProgress.compareAndSet(true, false)) { + result.success(false); + } + } + + /* + * Stops the authentication if in progress. + */ + private void stopAuthentication(Result result) { + try { + if (authHelper != null && authInProgress.get()) { + authHelper.stopAuthentication(); + authHelper = null; + } + authInProgress.set(false); + result.success(true); + } catch (Exception e) { + result.success(false); + } + } + + private void deviceSupportsBiometrics(final Result result) { + result.success(hasBiometricHardware()); + } + + /* + * Returns enrolled biometric types available on device. + */ + private void getEnrolledBiometrics(final Result result) { + try { + if (activity == null || activity.isFinishing()) { + result.error("no_activity", "local_auth plugin requires a foreground activity", null); + return; + } + ArrayList biometrics = getEnrolledBiometrics(); + result.success(biometrics); + } catch (Exception e) { + result.error("no_biometrics_available", e.getMessage(), null); } } + @VisibleForTesting + public ArrayList getEnrolledBiometrics() { + ArrayList biometrics = new ArrayList<>(); + if (activity == null || activity.isFinishing()) { + return biometrics; + } + if (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) + == BiometricManager.BIOMETRIC_SUCCESS) { + biometrics.add("weak"); + } + if (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) + == BiometricManager.BIOMETRIC_SUCCESS) { + biometrics.add("strong"); + } + return biometrics; + } + @VisibleForTesting public boolean isDeviceSecure() { if (keyguardManager == null) return false; return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && keyguardManager.isDeviceSecure()); } + @VisibleForTesting + public boolean isDeviceSupported() { + return isDeviceSecure() || canAuthenticateWithBiometrics(); + } + private boolean canAuthenticateWithBiometrics() { if (biometricManager == null) return false; return biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) @@ -222,16 +289,19 @@ public class LocalAuthPlugin implements FlutterPlugin, ActivityAware, LocalAuthA == BiometricManager.BIOMETRIC_SUCCESS; } - @Override - public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - LocalAuthApi.setup(binding.getBinaryMessenger(), this); + private void isDeviceSupported(Result result) { + result.success(isDeviceSupported()); } @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - LocalAuthApi.setup(binding.getBinaryMessenger(), null); + public void onAttachedToEngine(FlutterPluginBinding binding) { + channel = new MethodChannel(binding.getFlutterEngine().getDartExecutor(), CHANNEL_NAME); + channel.setMethodCallHandler(this); } + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {} + private void setServicesFromActivity(Activity activity) { if (activity == null) return; this.activity = activity; @@ -241,10 +311,11 @@ public class LocalAuthPlugin implements FlutterPlugin, ActivityAware, LocalAuthA } @Override - public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { + public void onAttachedToActivity(ActivityPluginBinding binding) { binding.addActivityResultListener(resultListener); setServicesFromActivity(binding.getActivity()); lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding); + channel.setMethodCallHandler(this); } @Override @@ -254,7 +325,7 @@ public class LocalAuthPlugin implements FlutterPlugin, ActivityAware, LocalAuthA } @Override - public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { + public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) { binding.addActivityResultListener(resultListener); setServicesFromActivity(binding.getActivity()); lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding); @@ -263,6 +334,7 @@ public class LocalAuthPlugin implements FlutterPlugin, ActivityAware, LocalAuthA @Override public void onDetachedFromActivity() { lifecycle = null; + channel.setMethodCallHandler(null); activity = null; } diff --git a/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/Messages.java b/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/Messages.java deleted file mode 100644 index e878c481c273d56fee6d6bff01b54c410b1d757d..0000000000000000000000000000000000000000 --- a/packages/local_auth/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/Messages.java +++ /dev/null @@ -1,748 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.0), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -package io.flutter.plugins.localauth; - -import android.util.Log; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import io.flutter.plugin.common.BasicMessageChannel; -import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.MessageCodec; -import io.flutter.plugin.common.StandardMessageCodec; -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -/** Generated class from Pigeon. */ -@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) -public class Messages { - - /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ - public static class FlutterError extends RuntimeException { - - /** The error code. */ - public final String code; - - /** The error details. Must be a datatype supported by the api codec. */ - public final Object details; - - public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) { - super(message); - this.code = code; - this.details = details; - } - } - - @NonNull - protected static ArrayList wrapError(@NonNull Throwable exception) { - ArrayList errorList = new ArrayList(3); - if (exception instanceof FlutterError) { - FlutterError error = (FlutterError) exception; - errorList.add(error.code); - errorList.add(error.getMessage()); - errorList.add(error.details); - } else { - errorList.add(exception.toString()); - errorList.add(exception.getClass().getSimpleName()); - errorList.add( - "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); - } - return errorList; - } - - /** Possible outcomes of an authentication attempt. */ - public enum AuthResult { - /** The user authenticated successfully. */ - SUCCESS(0), - /** The user failed to successfully authenticate. */ - FAILURE(1), - /** An authentication was already in progress. */ - ERROR_ALREADY_IN_PROGRESS(2), - /** There is no foreground activity. */ - ERROR_NO_ACTIVITY(3), - /** The foreground activity is not a FragmentActivity. */ - ERROR_NOT_FRAGMENT_ACTIVITY(4), - /** The authentication system was not available. */ - ERROR_NOT_AVAILABLE(5), - /** No biometrics are enrolled. */ - ERROR_NOT_ENROLLED(6), - /** The user is locked out temporarily due to too many failed attempts. */ - ERROR_LOCKED_OUT_TEMPORARILY(7), - /** The user is locked out until they log in another way due to too many failed attempts. */ - ERROR_LOCKED_OUT_PERMANENTLY(8); - - final int index; - - private AuthResult(final int index) { - this.index = index; - } - } - - /** Pigeon equivalent of the subset of BiometricType used by Android. */ - public enum AuthClassification { - WEAK(0), - STRONG(1); - - final int index; - - private AuthClassification(final int index) { - this.index = index; - } - } - - /** - * Pigeon version of AndroidAuthStrings, plus the authorization reason. - * - *

See auth_messages_android.dart for details. - * - *

Generated class from Pigeon that represents data sent in messages. - */ - public static final class AuthStrings { - private @NonNull String reason; - - public @NonNull String getReason() { - return reason; - } - - public void setReason(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"reason\" is null."); - } - this.reason = setterArg; - } - - private @NonNull String biometricHint; - - public @NonNull String getBiometricHint() { - return biometricHint; - } - - public void setBiometricHint(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"biometricHint\" is null."); - } - this.biometricHint = setterArg; - } - - private @NonNull String biometricNotRecognized; - - public @NonNull String getBiometricNotRecognized() { - return biometricNotRecognized; - } - - public void setBiometricNotRecognized(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"biometricNotRecognized\" is null."); - } - this.biometricNotRecognized = setterArg; - } - - private @NonNull String biometricRequiredTitle; - - public @NonNull String getBiometricRequiredTitle() { - return biometricRequiredTitle; - } - - public void setBiometricRequiredTitle(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"biometricRequiredTitle\" is null."); - } - this.biometricRequiredTitle = setterArg; - } - - private @NonNull String cancelButton; - - public @NonNull String getCancelButton() { - return cancelButton; - } - - public void setCancelButton(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"cancelButton\" is null."); - } - this.cancelButton = setterArg; - } - - private @NonNull String deviceCredentialsRequiredTitle; - - public @NonNull String getDeviceCredentialsRequiredTitle() { - return deviceCredentialsRequiredTitle; - } - - public void setDeviceCredentialsRequiredTitle(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException( - "Nonnull field \"deviceCredentialsRequiredTitle\" is null."); - } - this.deviceCredentialsRequiredTitle = setterArg; - } - - private @NonNull String deviceCredentialsSetupDescription; - - public @NonNull String getDeviceCredentialsSetupDescription() { - return deviceCredentialsSetupDescription; - } - - public void setDeviceCredentialsSetupDescription(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException( - "Nonnull field \"deviceCredentialsSetupDescription\" is null."); - } - this.deviceCredentialsSetupDescription = setterArg; - } - - private @NonNull String goToSettingsButton; - - public @NonNull String getGoToSettingsButton() { - return goToSettingsButton; - } - - public void setGoToSettingsButton(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"goToSettingsButton\" is null."); - } - this.goToSettingsButton = setterArg; - } - - private @NonNull String goToSettingsDescription; - - public @NonNull String getGoToSettingsDescription() { - return goToSettingsDescription; - } - - public void setGoToSettingsDescription(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"goToSettingsDescription\" is null."); - } - this.goToSettingsDescription = setterArg; - } - - private @NonNull String signInTitle; - - public @NonNull String getSignInTitle() { - return signInTitle; - } - - public void setSignInTitle(@NonNull String setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"signInTitle\" is null."); - } - this.signInTitle = setterArg; - } - - /** Constructor is non-public to enforce null safety; use Builder. */ - AuthStrings() {} - - public static final class Builder { - - private @Nullable String reason; - - public @NonNull Builder setReason(@NonNull String setterArg) { - this.reason = setterArg; - return this; - } - - private @Nullable String biometricHint; - - public @NonNull Builder setBiometricHint(@NonNull String setterArg) { - this.biometricHint = setterArg; - return this; - } - - private @Nullable String biometricNotRecognized; - - public @NonNull Builder setBiometricNotRecognized(@NonNull String setterArg) { - this.biometricNotRecognized = setterArg; - return this; - } - - private @Nullable String biometricRequiredTitle; - - public @NonNull Builder setBiometricRequiredTitle(@NonNull String setterArg) { - this.biometricRequiredTitle = setterArg; - return this; - } - - private @Nullable String cancelButton; - - public @NonNull Builder setCancelButton(@NonNull String setterArg) { - this.cancelButton = setterArg; - return this; - } - - private @Nullable String deviceCredentialsRequiredTitle; - - public @NonNull Builder setDeviceCredentialsRequiredTitle(@NonNull String setterArg) { - this.deviceCredentialsRequiredTitle = setterArg; - return this; - } - - private @Nullable String deviceCredentialsSetupDescription; - - public @NonNull Builder setDeviceCredentialsSetupDescription(@NonNull String setterArg) { - this.deviceCredentialsSetupDescription = setterArg; - return this; - } - - private @Nullable String goToSettingsButton; - - public @NonNull Builder setGoToSettingsButton(@NonNull String setterArg) { - this.goToSettingsButton = setterArg; - return this; - } - - private @Nullable String goToSettingsDescription; - - public @NonNull Builder setGoToSettingsDescription(@NonNull String setterArg) { - this.goToSettingsDescription = setterArg; - return this; - } - - private @Nullable String signInTitle; - - public @NonNull Builder setSignInTitle(@NonNull String setterArg) { - this.signInTitle = setterArg; - return this; - } - - public @NonNull AuthStrings build() { - AuthStrings pigeonReturn = new AuthStrings(); - pigeonReturn.setReason(reason); - pigeonReturn.setBiometricHint(biometricHint); - pigeonReturn.setBiometricNotRecognized(biometricNotRecognized); - pigeonReturn.setBiometricRequiredTitle(biometricRequiredTitle); - pigeonReturn.setCancelButton(cancelButton); - pigeonReturn.setDeviceCredentialsRequiredTitle(deviceCredentialsRequiredTitle); - pigeonReturn.setDeviceCredentialsSetupDescription(deviceCredentialsSetupDescription); - pigeonReturn.setGoToSettingsButton(goToSettingsButton); - pigeonReturn.setGoToSettingsDescription(goToSettingsDescription); - pigeonReturn.setSignInTitle(signInTitle); - return pigeonReturn; - } - } - - @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(10); - toListResult.add(reason); - toListResult.add(biometricHint); - toListResult.add(biometricNotRecognized); - toListResult.add(biometricRequiredTitle); - toListResult.add(cancelButton); - toListResult.add(deviceCredentialsRequiredTitle); - toListResult.add(deviceCredentialsSetupDescription); - toListResult.add(goToSettingsButton); - toListResult.add(goToSettingsDescription); - toListResult.add(signInTitle); - return toListResult; - } - - static @NonNull AuthStrings fromList(@NonNull ArrayList list) { - AuthStrings pigeonResult = new AuthStrings(); - Object reason = list.get(0); - pigeonResult.setReason((String) reason); - Object biometricHint = list.get(1); - pigeonResult.setBiometricHint((String) biometricHint); - Object biometricNotRecognized = list.get(2); - pigeonResult.setBiometricNotRecognized((String) biometricNotRecognized); - Object biometricRequiredTitle = list.get(3); - pigeonResult.setBiometricRequiredTitle((String) biometricRequiredTitle); - Object cancelButton = list.get(4); - pigeonResult.setCancelButton((String) cancelButton); - Object deviceCredentialsRequiredTitle = list.get(5); - pigeonResult.setDeviceCredentialsRequiredTitle((String) deviceCredentialsRequiredTitle); - Object deviceCredentialsSetupDescription = list.get(6); - pigeonResult.setDeviceCredentialsSetupDescription((String) deviceCredentialsSetupDescription); - Object goToSettingsButton = list.get(7); - pigeonResult.setGoToSettingsButton((String) goToSettingsButton); - Object goToSettingsDescription = list.get(8); - pigeonResult.setGoToSettingsDescription((String) goToSettingsDescription); - Object signInTitle = list.get(9); - pigeonResult.setSignInTitle((String) signInTitle); - return pigeonResult; - } - } - - /** Generated class from Pigeon that represents data sent in messages. */ - public static final class AuthOptions { - private @NonNull Boolean biometricOnly; - - public @NonNull Boolean getBiometricOnly() { - return biometricOnly; - } - - public void setBiometricOnly(@NonNull Boolean setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"biometricOnly\" is null."); - } - this.biometricOnly = setterArg; - } - - private @NonNull Boolean sensitiveTransaction; - - public @NonNull Boolean getSensitiveTransaction() { - return sensitiveTransaction; - } - - public void setSensitiveTransaction(@NonNull Boolean setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"sensitiveTransaction\" is null."); - } - this.sensitiveTransaction = setterArg; - } - - private @NonNull Boolean sticky; - - public @NonNull Boolean getSticky() { - return sticky; - } - - public void setSticky(@NonNull Boolean setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"sticky\" is null."); - } - this.sticky = setterArg; - } - - private @NonNull Boolean useErrorDialgs; - - public @NonNull Boolean getUseErrorDialgs() { - return useErrorDialgs; - } - - public void setUseErrorDialgs(@NonNull Boolean setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"useErrorDialgs\" is null."); - } - this.useErrorDialgs = setterArg; - } - - /** Constructor is non-public to enforce null safety; use Builder. */ - AuthOptions() {} - - public static final class Builder { - - private @Nullable Boolean biometricOnly; - - public @NonNull Builder setBiometricOnly(@NonNull Boolean setterArg) { - this.biometricOnly = setterArg; - return this; - } - - private @Nullable Boolean sensitiveTransaction; - - public @NonNull Builder setSensitiveTransaction(@NonNull Boolean setterArg) { - this.sensitiveTransaction = setterArg; - return this; - } - - private @Nullable Boolean sticky; - - public @NonNull Builder setSticky(@NonNull Boolean setterArg) { - this.sticky = setterArg; - return this; - } - - private @Nullable Boolean useErrorDialgs; - - public @NonNull Builder setUseErrorDialgs(@NonNull Boolean setterArg) { - this.useErrorDialgs = setterArg; - return this; - } - - public @NonNull AuthOptions build() { - AuthOptions pigeonReturn = new AuthOptions(); - pigeonReturn.setBiometricOnly(biometricOnly); - pigeonReturn.setSensitiveTransaction(sensitiveTransaction); - pigeonReturn.setSticky(sticky); - pigeonReturn.setUseErrorDialgs(useErrorDialgs); - return pigeonReturn; - } - } - - @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(4); - toListResult.add(biometricOnly); - toListResult.add(sensitiveTransaction); - toListResult.add(sticky); - toListResult.add(useErrorDialgs); - return toListResult; - } - - static @NonNull AuthOptions fromList(@NonNull ArrayList list) { - AuthOptions pigeonResult = new AuthOptions(); - Object biometricOnly = list.get(0); - pigeonResult.setBiometricOnly((Boolean) biometricOnly); - Object sensitiveTransaction = list.get(1); - pigeonResult.setSensitiveTransaction((Boolean) sensitiveTransaction); - Object sticky = list.get(2); - pigeonResult.setSticky((Boolean) sticky); - Object useErrorDialgs = list.get(3); - pigeonResult.setUseErrorDialgs((Boolean) useErrorDialgs); - return pigeonResult; - } - } - - /** Generated class from Pigeon that represents data sent in messages. */ - public static final class AuthClassificationWrapper { - private @NonNull AuthClassification value; - - public @NonNull AuthClassification getValue() { - return value; - } - - public void setValue(@NonNull AuthClassification setterArg) { - if (setterArg == null) { - throw new IllegalStateException("Nonnull field \"value\" is null."); - } - this.value = setterArg; - } - - /** Constructor is non-public to enforce null safety; use Builder. */ - AuthClassificationWrapper() {} - - public static final class Builder { - - private @Nullable AuthClassification value; - - public @NonNull Builder setValue(@NonNull AuthClassification setterArg) { - this.value = setterArg; - return this; - } - - public @NonNull AuthClassificationWrapper build() { - AuthClassificationWrapper pigeonReturn = new AuthClassificationWrapper(); - pigeonReturn.setValue(value); - return pigeonReturn; - } - } - - @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(1); - toListResult.add(value == null ? null : value.index); - return toListResult; - } - - static @NonNull AuthClassificationWrapper fromList(@NonNull ArrayList list) { - AuthClassificationWrapper pigeonResult = new AuthClassificationWrapper(); - Object value = list.get(0); - pigeonResult.setValue(AuthClassification.values()[(int) value]); - return pigeonResult; - } - } - - public interface Result { - @SuppressWarnings("UnknownNullness") - void success(T result); - - void error(@NonNull Throwable error); - } - - private static class LocalAuthApiCodec extends StandardMessageCodec { - public static final LocalAuthApiCodec INSTANCE = new LocalAuthApiCodec(); - - private LocalAuthApiCodec() {} - - @Override - protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return AuthClassificationWrapper.fromList((ArrayList) readValue(buffer)); - case (byte) 129: - return AuthOptions.fromList((ArrayList) readValue(buffer)); - case (byte) 130: - return AuthStrings.fromList((ArrayList) readValue(buffer)); - default: - return super.readValueOfType(type, buffer); - } - } - - @Override - protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof AuthClassificationWrapper) { - stream.write(128); - writeValue(stream, ((AuthClassificationWrapper) value).toList()); - } else if (value instanceof AuthOptions) { - stream.write(129); - writeValue(stream, ((AuthOptions) value).toList()); - } else if (value instanceof AuthStrings) { - stream.write(130); - writeValue(stream, ((AuthStrings) value).toList()); - } else { - super.writeValue(stream, value); - } - } - } - - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ - public interface LocalAuthApi { - /** Returns true if this device supports authentication. */ - @NonNull - Boolean isDeviceSupported(); - /** - * Returns true if this device can support biometric authentication, whether any biometrics are - * enrolled or not. - */ - @NonNull - Boolean deviceCanSupportBiometrics(); - /** - * Cancels any in-progress authentication. - * - *

Returns true only if authentication was in progress, and was successfully cancelled. - */ - @NonNull - Boolean stopAuthentication(); - /** - * Returns the biometric types that are enrolled, and can thus be used without additional setup. - */ - @NonNull - List getEnrolledBiometrics(); - /** - * Attempts to authenticate the user with the provided [options], and using [strings] for any - * UI. - */ - void authenticate( - @NonNull AuthOptions options, - @NonNull AuthStrings strings, - @NonNull Result result); - - /** The codec used by LocalAuthApi. */ - static @NonNull MessageCodec getCodec() { - return LocalAuthApiCodec.INSTANCE; - } - /** Sets up an instance of `LocalAuthApi` to handle messages through the `binaryMessenger`. */ - static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable LocalAuthApi api) { - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.local_auth_android.LocalAuthApi.isDeviceSupported", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - ArrayList wrapped = new ArrayList(); - try { - Boolean output = api.isDeviceSupported(); - wrapped.add(0, output); - } catch (Throwable exception) { - ArrayList wrappedError = wrapError(exception); - wrapped = wrappedError; - } - reply.reply(wrapped); - }); - } else { - channel.setMessageHandler(null); - } - } - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.local_auth_android.LocalAuthApi.deviceCanSupportBiometrics", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - ArrayList wrapped = new ArrayList(); - try { - Boolean output = api.deviceCanSupportBiometrics(); - wrapped.add(0, output); - } catch (Throwable exception) { - ArrayList wrappedError = wrapError(exception); - wrapped = wrappedError; - } - reply.reply(wrapped); - }); - } else { - channel.setMessageHandler(null); - } - } - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.local_auth_android.LocalAuthApi.stopAuthentication", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - ArrayList wrapped = new ArrayList(); - try { - Boolean output = api.stopAuthentication(); - wrapped.add(0, output); - } catch (Throwable exception) { - ArrayList wrappedError = wrapError(exception); - wrapped = wrappedError; - } - reply.reply(wrapped); - }); - } else { - channel.setMessageHandler(null); - } - } - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.local_auth_android.LocalAuthApi.getEnrolledBiometrics", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - ArrayList wrapped = new ArrayList(); - try { - List output = api.getEnrolledBiometrics(); - wrapped.add(0, output); - } catch (Throwable exception) { - ArrayList wrappedError = wrapError(exception); - wrapped = wrappedError; - } - reply.reply(wrapped); - }); - } else { - channel.setMessageHandler(null); - } - } - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.local_auth_android.LocalAuthApi.authenticate", - getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - ArrayList wrapped = new ArrayList(); - ArrayList args = (ArrayList) message; - AuthOptions optionsArg = (AuthOptions) args.get(0); - AuthStrings stringsArg = (AuthStrings) args.get(1); - Result resultCallback = - new Result() { - public void success(AuthResult result) { - wrapped.add(0, result.index); - reply.reply(wrapped); - } - - public void error(Throwable error) { - ArrayList wrappedError = wrapError(error); - reply.reply(wrappedError); - } - }; - - api.authenticate(optionsArg, stringsArg, resultCallback); - }); - } else { - channel.setMessageHandler(null); - } - } - } - } -} diff --git a/packages/local_auth/local_auth_android/android/src/main/res/layout/go_to_setting.xml b/packages/local_auth/local_auth_android/android/src/main/res/layout/go_to_setting.xml index 902635ef543685b880ba6b1bdf672cd896285300..8c932d4d19c84d0e5caed3415680af5676193e14 100644 --- a/packages/local_auth/local_auth_android/android/src/main/res/layout/go_to_setting.xml +++ b/packages/local_auth/local_auth_android/android/src/main/res/layout/go_to_setting.xml @@ -1,30 +1,26 @@ - - - - + android:paddingRight="24dp" + android:gravity="center_vertical" + android:orientation="vertical"> + + diff --git a/packages/local_auth/local_auth_android/android/src/main/res/values/colors.xml b/packages/local_auth/local_auth_android/android/src/main/res/values/colors.xml index 0fd4d38020c079850bffa643fe59e9ec84deb2d1..c011fe33787cfb0188a5727d8161ddd6160f1628 100644 --- a/packages/local_auth/local_auth_android/android/src/main/res/values/colors.xml +++ b/packages/local_auth/local_auth_android/android/src/main/res/values/colors.xml @@ -1,6 +1,9 @@ + #E53935 + #BDBDBD + #43A047 #212121 #757575 diff --git a/packages/local_auth/local_auth_android/android/src/main/res/values/dimens.xml b/packages/local_auth/local_auth_android/android/src/main/res/values/dimens.xml index 13a68e95a495274b14bfc7275404e4ef215be8af..678faebffd615f78b54a5ebd22a45079cc19dddf 100644 --- a/packages/local_auth/local_auth_android/android/src/main/res/values/dimens.xml +++ b/packages/local_auth/local_auth_android/android/src/main/res/values/dimens.xml @@ -1,4 +1,5 @@ + 14sp 16sp 20sp diff --git a/packages/local_auth/local_auth_android/android/src/main/res/values/styles.xml b/packages/local_auth/local_auth_android/android/src/main/res/values/styles.xml index ca014754c4a0e06a80c513f06180e648f0bc198d..7a0719f418822a6adb29cda8bec3ef63fbbf2124 100644 --- a/packages/local_auth/local_auth_android/android/src/main/res/values/styles.xml +++ b/packages/local_auth/local_auth_android/android/src/main/res/values/styles.xml @@ -1,6 +1,5 @@ -