4

It looks like BiometricPrompt 1.0.0 has a bug where it stays in invisible state throwing that exception

ill suggest a workaround in the answer

EDIT(thanks to @Isai Damier):

Way to reproduce:

  1. open the BiometricPrompt
  2. press back button - close the prompt
  3. press back again and exit the app
  4. return to the app - try to open the prompt again
gor
  • 1,046
  • 1
  • 14
  • 28

1 Answers1

2

this fix was introduces when biometric prompt version was 1.0.0. this issue dosent reproduces in 1.0.1

//-------------------------------------------------------------------------

i came up with a work around - call 'cancelAuthentication' on the prompt upon user cancelation.

full code is as follows (used in a react native app - thats why the promise are for):

    private const val E_BIOMETRIC_ERR = "E_FINGER_PRINT_ERR"
    private const val OPENED = "success"
    private var bp: BiometricPrompt? = null
    private var mAuthenticationPromise: Promise? = null

    fun authenticate(activity: AppCompatActivity, title: String,
                     subTitle: String, description: String, authenticationPromise: Promise) {
        mAuthenticationPromise = authenticationPromise

        val executor = Executors.newSingleThreadExecutor()

        bp?.cancelAuthentication()
        bp = getBiometricPrompt(activity, executor)

        val promptInfo = BiometricPrompt.PromptInfo.Builder()
                .setTitle(title)
                .setSubtitle(subTitle)
                .setDescription(description)
                .setDeviceCredentialAllowed(true)
                .build()

        bp!!.authenticate(promptInfo)

    }



    private fun getBiometricPrompt(activity: AppCompatActivity, executor: Executor): BiometricPrompt {
        return BiometricPrompt(activity, executor, object : BiometricPrompt.AuthenticationCallback() {

            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                super.onAuthenticationSucceeded(result)
                mAuthenticationPromise?.resolve(OPENED)
            }

            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                super.onAuthenticationError(errorCode, errString)
                bp!!.cancelAuthentication()
            }

            override fun onAuthenticationFailed() {
                super.onAuthenticationFailed()
                bp!!.cancelAuthentication()
            }
        })
    }

I hope it helps anyone - cheers

gor
  • 1,046
  • 1
  • 14
  • 28
  • Hi! I tried your solution, but it does not works...but if you include recreate() method in onAuthenticationError() and onAuthenticationSucceeded() works perfectly!! – fesave Nov 21 '19 at 12:35
  • Great ill try it and re-post – gor Nov 21 '19 at 14:22
  • ok, now i get it when you wrote "recreate" - i dont want to affect the Activity Lifecycle - i just want to open-close-reopen the prompt - so this is why i saved the `bp` in the first place. Anyway, thanks @fesave – gor Nov 21 '19 at 15:42