1

Android BiometricPrompt has completed fingerprint recognition, but onAuthenicationSucceeded does not work.

And I used androidx

Example: Log.i("finger", "onAuthenticationSucceeded") is not output

Copied this code: https://developer.android.com/training/sign-in/biometric-auth#kotlin

MainActivity:

private fun showBiometricPrompt() {
    val promptInfo = BiometricPrompt.PromptInfo.Builder()
        .setTitle("Biometric login for my app")
        .setSubtitle("Log in using your biometric credential")
        .setNegativeButtonText("Cancel")
        .build()
    Log.i("finger", "o")
    val biometricPrompt = BiometricPrompt(this, executor,
        object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationError(errorCode: Int,
                                               errString: CharSequence) {
                Log.i("finger", "onAuthenticationError")
                super.onAuthenticationError(errorCode, errString)
                Toast.makeText(applicationContext,
                    "Authentication error: $errString", Toast.LENGTH_SHORT)
                    .show()
            }

            override fun onAuthenticationSucceeded(
                result: BiometricPrompt.AuthenticationResult) {
                super.onAuthenticationSucceeded(result)
                Log.i("finger", "onAuthenticationSucceeded")
                val authenticatedCryptoObject: BiometricPrompt.CryptoObject? =
                    result.getCryptoObject()
                // User has verified the signature, cipher, or message
                // authentication code (MAC) associated with the crypto object,
                // so you can use it in your app's crypto-driven workflows.

            }

            override fun onAuthenticationFailed() {
                Log.i("finger", "onAuthenticationFailed")
                super.onAuthenticationFailed()
                Toast.makeText(applicationContext, "Authentication failed",
                    Toast.LENGTH_SHORT)
                    .show()
            }
        })

    // Displays the "log in" prompt.
    biometricPrompt.authenticate(promptInfo)
    }
}

Logs from the current android studio

2019-11-27 19:45:22.348 11633-11633/? I/e.myapplicatio: Late-enabling -Xcheck:jni
2019-11-27 19:45:23.124 11633-11633/com.example.myapplication W/e.myapplicatio: JIT profile information will not be recorded: profile file does not exits.
2019-11-27 19:45:23.127 11633-11633/com.example.myapplication I/chatty: uid=10263(com.example.myapplication) identical 10 lines
2019-11-27 19:45:23.127 11633-11633/com.example.myapplication W/e.myapplicatio: JIT profile information will not be recorded: profile file does not exits.
2019-11-27 19:45:23.197 11633-11633/com.example.myapplication I/InstantRun: starting instant run server: is main process
2019-11-27 19:45:23.363 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden method Landroid/graphics/drawable/Drawable;->getOpticalInsets()Landroid/graphics/Insets; (light greylist, linking)
2019-11-27 19:45:23.363 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden field Landroid/graphics/Insets;->left:I (light greylist, linking)
2019-11-27 19:45:23.363 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden field Landroid/graphics/Insets;->right:I (light greylist, linking)
2019-11-27 19:45:23.363 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden field Landroid/graphics/Insets;->top:I (light greylist, linking)
2019-11-27 19:45:23.363 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden field Landroid/graphics/Insets;->bottom:I (light greylist, linking)
2019-11-27 19:45:23.421 11633-11633/com.example.myapplication D/PhoneWindow: windowLightStatusBar : false, disable View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
2019-11-27 19:45:23.489 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden method Landroid/view/View;->getAccessibilityDelegate()Landroid/view/View$AccessibilityDelegate; (light greylist, linking)
2019-11-27 19:45:23.593 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
2019-11-27 19:45:23.594 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
2019-11-27 19:45:23.610 11633-11633/com.example.myapplication W/e.myapplicatio: Accessing hidden method Landroid/widget/TextView;->getTextDirectionHeuristic()Landroid/text/TextDirectionHeuristic; (light greylist, linking)
2019-11-27 19:45:23.726 11633-11633/com.example.myapplication I/App can authenticate using biometrics.: OK
2019-11-27 19:45:23.760 11633-11633/com.example.myapplication D/OpenGLRenderer: Skia GL Pipeline
2019-11-27 19:45:23.835 11633-11633/com.example.myapplication I/TouchFilterInputStageHelper: [needTouchEventFilter] Displayid : 0
2019-11-27 19:45:23.841 11633-11633/com.example.myapplication D/BezellessGripSuppressionFilter: getdisplaysize, x : 1440 y : 2880
2019-11-27 19:45:23.924 11633-11733/com.example.myapplication I/Adreno: QUALCOMM build                   : 6aca7ed, I9a84ac9597
    Build Date                       : 08/23/19
    OpenGL ES Shader Compiler Version: EV031.25.03.07
    Local Branch                     : 
    Remote Branch                    : refs/tags/AU_LINUX_ANDROID_LA.UM.7.5.2.R1.09.00.00.538.032
    Remote Branch                    : NONE
    Reconstruct Branch               : NOTHING
2019-11-27 19:45:23.924 11633-11733/com.example.myapplication I/Adreno: Build Config                     : S L 6.0.7 AArch64
2019-11-27 19:45:23.924 11633-11733/com.example.myapplication D/vndksupport: Loading /vendor/lib64/hw/gralloc.msm8996.so from current namespace instead of sphal namespace.
2019-11-27 19:45:23.938 11633-11733/com.example.myapplication I/Adreno: PFP: 0x005ff112, ME: 0x005ff066
2019-11-27 19:45:23.980 11633-11733/com.example.myapplication I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
2019-11-27 19:45:23.982 11633-11733/com.example.myapplication I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 0
2019-11-27 19:45:23.983 11633-11733/com.example.myapplication I/OpenGLRenderer: Initialized EGL, version 1.4
2019-11-27 19:45:23.983 11633-11733/com.example.myapplication D/OpenGLRenderer: Swap behavior 2
2019-11-27 19:45:24.008 11633-11733/com.example.myapplication D/vndksupport: Loading /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so from current namespace instead of sphal namespace.
2019-11-27 19:45:24.009 11633-11733/com.example.myapplication D/vndksupport: Loading /vendor/lib64/hw/gralloc.msm8996.so from current namespace instead of sphal namespace.
2019-11-27 19:45:24.178 11633-11633/com.example.myapplication I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@64768ba time:68742526
2019-11-27 19:45:26.690 11633-11633/com.example.myapplication I/ViewRootImpl: ViewRoot's Touch Event : ACTION_DOWN
2019-11-27 19:45:26.761 11633-11633/com.example.myapplication I/ViewRootImpl: ViewRoot's Touch Event : ACTION_UP
Markus Kauppinen
  • 3,025
  • 4
  • 20
  • 30
타터터
  • 101
  • 2
  • 5
  • So which logs **do** you get? – Michael Nov 27 '19 at 09:44
  • After completing fingerprint recognition, I would like to add functions. But after recognizing the fingerprint, I tried to print Log.i, but failed. – 타터터 Nov 27 '19 at 10:01
  • Right. There are some logs you aren't getting for some reason. But I was asking which logs you **are** getting. – Michael Nov 27 '19 at 10:05
  • I'm sorry. I didn't understand English because I lacked it. Can you tell me if the log you are talking to is the log that I am trying to output or the log that is output to android studio Logs? – 타터터 Nov 27 '19 at 10:36
  • *"File does not exits."* <- Is this a literal copy/paste, or did you type in the logs by hand? "exist" is misspelled. – tripleee Nov 27 '19 at 10:53
  • The logcat output you've posted doesn't seem to include that `"o"` log from the beginning of `showBiometricPrompt`. Are you sure you haven't filtered out logs from your app or something? – Michael Nov 27 '19 at 10:53
  • Copying and pasting as provided. @ tripleee – 타터터 Nov 27 '19 at 11:03
  • Does the "o" is Log.i("finger", "o")?? you mean the Log on this? That's what I printed out for the test. That's an output, but onauthenicationError or onauthenicationSucceeded and... OnAuthenicationFailed, Toast or Logs that are output to the next are not printed @Michael – 타터터 Nov 27 '19 at 11:08
  • Yes, that's the log I mean. I don't see it in the logcat output you've posted. By the way, your `onAuthenticationSucceeded` seems to expect to get a `CryptoObject` from the result, but you're not passing any `CryptoObject` to `authenticate`. – Michael Nov 27 '19 at 11:16
  • Then can you tell me what to do if I want to add a function after I succeed in fingerprint authentication? I understand that if onAuthenicationSucceeded is successful, it will write down the next function. Is that correct? @ Michael – 타터터 Nov 27 '19 at 13:21

1 Answers1

1

Try following the instructions in this blog post. It provides step by step instructions on how to implement BiometricPrompt. There is also more details in this blog post.

Here is a summary:

1- Add the Gradle dependency to your app module (latest release)

 def biometric_version= '1.0.0'
 implementation "androidx.biometric:biometric:$biometric_version"

2- Create an instance of BiometricPrompt. You should get this value inside onCreate() of your activity or onCreateView() of your Fragment

private fun createBiometricPrompt(): BiometricPrompt {
   val executor = ContextCompat.getmainExecutor(context)

   val callback = object: BiometricPrompt.AuthenticationCallback() {
       override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
           super.onAuthenticationError(errorCode, errString)
           showMessage("$errorCode :: $errString")
       }

       override fun onAuthenticationFailed() {
           super.onAuthenticationFailed()
           showMessage("Authentication failed for an unknown reason")
       }

       override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
           super.onAuthenticationSucceeded(result)
           showMessage("Authentication was successful")
       }
   }

   val biometricPrompt = BiometricPrompt(context, executor, callback)
   return biometricPrompt
}

3- Build a PromptInfo object

private fun createPromptInfo(): BiometricPrompt.PromptInfo {
   val promptInfo = BiometricPrompt.PromptInfo.Builder()
       .setTitle("My App's Authentication")
       .setSubtitle("Please login to get access")
       .setDescription("My App is using Android biometric authentication")
              .setDeviceCredentialAllowed(true)
       .build()
   return promptInfo
}

4- Ask the user to authenticate

val canAuthenticate = biometricManager.canAuthenticate()
if (canAuthenticate == BiometricManager.BIOMETRIC_SUCCESS) {

   biometricPrompt.authenticate(createPromptInfo())
} else {
   Log.d(TAG, "could not authenticate because: $canAuthenticate")
}
Isai Damier
  • 976
  • 6
  • 8
  • Disclaimer: I work on Biometrics at Google and I wrote both blog posts. – Isai Damier Nov 27 '19 at 17:17
  • Also, I'm available to answer any follow up questions – Isai Damier Nov 27 '19 at 17:33
  • My somewhat unrelated follow-up is that I hope that Google will consider addressing [what I consider to be an oversight in the biometric API](https://issuetracker.google.com/issues/111315641). – Michael Nov 28 '19 at 09:43
  • I'm very grateful to those who helped me.I solved the problem. Thankyou. @ Isai Damier @ Michael @ tripleee – 타터터 Nov 28 '19 at 13:01
  • if this answer directed you to solve your problem, please mark it as accepted so others can find it more easily. – Isai Damier Dec 18 '19 at 18:20
  • 1
    But even if `canAuthenticate()` doesn't return `BiometricManager.BIOMETRIC_SUCCESS`, it's still possible that it can take a password input if you set `setDeviceCredentialAllowed(true)`. Isn't it therefore wrong to wrap the prompt into this `BIOMETRIC_SUCCESS` check? – Florian Walther Dec 31 '19 at 21:43
  • Thanks for the question! Password here can mean device password or account password. A device password is a password that unlocks the whole device. An account password is a password specific to your app: e.g. a user's bank account password for a banking app. This present implementation allows the user to login with biometrics or their app specific account password. `setDeviceCredentialAllowed()`, on the other hand, doesn't allow the user to enter the account password but rather to rely on the device credential for authentication -- which can be device password, PIN, or pattern. – Isai Damier Jan 02 '20 at 18:49
  • Also recall that `setDeviceCredentialAllowed()` is not compatible with `CryptoObject` or with `setNegativeButtonText()`. – Isai Damier Jan 02 '20 at 18:50
  • @IsaiDamier I think we need to add `createBiometricPrompt().cancelAuthentication()` when authentication failed .Else next time user won't be able to open prompt. – sandeep dhami May 13 '20 at 09:41
  • how to validate cryptoobject in onAuthenticationSucceeded? to avoid any security attack? – Ritzor Jun 25 '20 at 09:50