Fixed
Status Update
Comments
ku...@google.com <ku...@google.com>
ku...@google.com <ku...@google.com> #2
Even I'm also facing same exception issue. When user failed biometrics multiple times(5) and biometric is locked there is no way to find if biometrics can be shown or not. If user tries to enable again within the 30 sec time limit app is crashing. Please fix it ASAP.
Logs :
java.lang.IllegalStateException: Fragment already added: BiometricFragment{60be538 #2 BiometricFragment}
at androidx.fragment.app.FragmentManagerImpl.addFragment(FragmentManager.java:1916)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:765)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Logs :
java.lang.IllegalStateException: Fragment already added: BiometricFragment{60be538 #2 BiometricFragment}
at androidx.fragment.app.FragmentManagerImpl.addFragment(FragmentManager.java:1916)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:765)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
ch...@gmail.com <ch...@gmail.com> #3
We are unable to reproduce this issue with latest version of androidx.biometric (androidx.biometric:biometric:1.0.0-alpha03)
Re: comment #2 : Its similar to issue 117105236 (which is fixed).
Please check with latest version of the support libs & let us know the results.
If you are still able to reproduce this issue then provide the following info :
Provide sample project or apk to reproduce the issue. Also mention the steps to be followed for reproducing the issue with the given sample project or apk.
Android bug report
After reproducing the issue, press the volume up, volume down, and power button simultaneously. This will capture a bug report on your device in the “bug reports” directory. Attach the bug report file to this issue.
Alternate method:
After reproducing the issue, navigate to developer settings, ensure ‘USB debugging’ is enabled, then enable ‘Bug report shortcut’. To take bug report, hold the power button and select the ‘Take bug report’ option.
NOTE: Please upload the files to Google Drive and share the folder to android-bugreport@google.com, then share the link here.
Re:
Please check with latest version of the support libs & let us know the results.
If you are still able to reproduce this issue then provide the following info :
Provide sample project or apk to reproduce the issue. Also mention the steps to be followed for reproducing the issue with the given sample project or apk.
Android bug report
After reproducing the issue, press the volume up, volume down, and power button simultaneously. This will capture a bug report on your device in the “bug reports” directory. Attach the bug report file to this issue.
Alternate method:
After reproducing the issue, navigate to developer settings, ensure ‘USB debugging’ is enabled, then enable ‘Bug report shortcut’. To take bug report, hold the power button and select the ‘Take bug report’ option.
NOTE: Please upload the files to Google Drive and share the folder to android-bugreport@google.com, then share the link here.
ch...@gmail.com <ch...@gmail.com> #4
I think this issue needs to be fixed as a first priority. You can reproduce the error with opening app and calling biometricPrompt.authenticate() after that press home button and then, show your finger to sensor. It'll crash instantly. You can reproduce the issue easily. I can do that with my Oreo device. I think that cancelAuthenticate doesn't work properly.
ku...@google.com <ku...@google.com> #5
This issue looks like fixed with library -- androidx.biometric:biometric:1.0.0-alpha03
Q) Once user tries for 5 times, the popUp will not be visible for next 30 seconds. It is taking too much time to give errorCode=7 (ERROR_LOCKOUT) when tries to see the biometric popup again. Is there a way to see the errorCode faster than usual?
Thanks,
Q) Once user tries for 5 times, the popUp will not be visible for next 30 seconds. It is taking too much time to give errorCode=7 (ERROR_LOCKOUT) when tries to see the biometric popup again. Is there a way to see the errorCode faster than usual?
Thanks,
ja...@gmail.com <ja...@gmail.com> #6
I'm using alpha03 as well but the bug still remains. I'm facing it right now. You can check the problem when you open dialogfragment via authenticate() and press home button and then showing your finger to sensor.
ja...@gmail.com <ja...@gmail.com> #7
I'll attach a crash log to this, we're getting dozens of crashes per day, over 3% of our user sessions. Will try alpha03, and some of the reproduction notes here.
ku...@google.com <ku...@google.com>
ma...@gmail.com <ma...@gmail.com> #8
Here's a recent crashlytics bug report on this, with alpha02.
kc...@google.com <kc...@google.com> #9
Tried alpha03, and I don't have exactly the same issue, a different one has now surfaced with #6's reproduction notes:
2018-12-20 16:54:19.708 9948-9948/com.varomoney.varo.dev E/AndroidRuntime: FATAL EXCEPTION: main
Process:com.varomoney.varo.dev , PID: 9948
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.varomoney.varo.dev/com.varomoney.varo.presentation.launcher.LauncherActivity }: java.lang.IllegalArgumentException: Executor must not be null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.IllegalArgumentException: Executor must not be null
at android.hardware.biometrics.BiometricPrompt$Builder.setNegativeButton(BiometricPrompt.java:182)
at androidx.biometric.BiometricFragment.onCreate(BiometricFragment.java:201)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2414)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1418)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1861)
at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3269)
at androidx.fragment.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:3223)
at androidx.fragment.app.FragmentController.dispatchCreate(FragmentController.java:190)
at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:369)
at androidx.appcompat.app.AppCompatActivity.onCreate(AppCompatActivity.java:85)
at com.varomoney.varo.presentation.base.BaseActivity.onCreate(BaseActivity.kt:73)
at com.varomoney.varo.presentation.launcher.LauncherActivity.onCreate(LauncherActivity.kt:59)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
I've looked and I'm passing com.google.android.gms.tasks.TaskExecutors.MAIN_THREAD for the executor in my use of the API.
2018-12-20 16:54:19.708 9948-9948/
Process:
java.lang.RuntimeException: Unable to start activity ComponentInfo{
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.IllegalArgumentException: Executor must not be null
at android.hardware.biometrics.BiometricPrompt$Builder.setNegativeButton(BiometricPrompt.java:182)
at androidx.biometric.BiometricFragment.onCreate(BiometricFragment.java:201)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2414)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1418)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1861)
at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3269)
at androidx.fragment.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:3223)
at androidx.fragment.app.FragmentController.dispatchCreate(FragmentController.java:190)
at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:369)
at androidx.appcompat.app.AppCompatActivity.onCreate(AppCompatActivity.java:85)
at com.varomoney.varo.presentation.base.BaseActivity.onCreate(BaseActivity.kt:73)
at com.varomoney.varo.presentation.launcher.LauncherActivity.onCreate(LauncherActivity.kt:59)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
I've looked and I'm passing com.google.android.gms.tasks.TaskExecutors.MAIN_THREAD for the executor in my use of the API.
ap...@google.com <ap...@google.com> #10
Sorry I was using a Pixel 3 on that last report. Will try with Oreo.
jo...@google.com <jo...@google.com>
ch...@gmail.com <ch...@gmail.com> #11
If I use alpha03, and set 'Don't keep activities' on, and do the following:
1) Perform an authenticate
2) Hit home button before applying fingerprint
3) Return to the app, and apply fingerprint
I get:
Process:com.varomoney.varo.dev , PID: 8463
java.lang.NullPointerException: Attempt to invoke interface method 'void java.util.concurrent.Executor.execute(java.lang.Runnable)' on a null object reference
at androidx.biometric.FingerprintHelperFragment$1.onAuthenticationSucceeded(FingerprintHelperFragment.java:128)
at androidx.core.hardware.fingerprint.FingerprintManagerCompat$1.onAuthenticationSucceeded(FingerprintManagerCompat.java:176)
at android.hardware.fingerprint.FingerprintManager$MyHandler.sendAuthenticatedSucceeded(FingerprintManager.java:961)
at android.hardware.fingerprint.FingerprintManager$MyHandler.handleMessage(FingerprintManager.java:882)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Doesn't seem to be remembering the executor that is passed in for some reason. Arguably this is probably a new bug and not the same one as in alpha02.
1) Perform an authenticate
2) Hit home button before applying fingerprint
3) Return to the app, and apply fingerprint
I get:
Process:
java.lang.NullPointerException: Attempt to invoke interface method 'void java.util.concurrent.Executor.execute(java.lang.Runnable)' on a null object reference
at androidx.biometric.FingerprintHelperFragment$1.onAuthenticationSucceeded(FingerprintHelperFragment.java:128)
at androidx.core.hardware.fingerprint.FingerprintManagerCompat$1.onAuthenticationSucceeded(FingerprintManagerCompat.java:176)
at android.hardware.fingerprint.FingerprintManager$MyHandler.sendAuthenticatedSucceeded(FingerprintManager.java:961)
at android.hardware.fingerprint.FingerprintManager$MyHandler.handleMessage(FingerprintManager.java:882)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Doesn't seem to be remembering the executor that is passed in for some reason. Arguably this is probably a new bug and not the same one as in alpha02.
ph...@gmail.com <ph...@gmail.com> #12
Here's another issue:
1) Display authenticate dialog on Oreo. Don't apply fingerprint.
2) Go to developer settings > Running Services > Show Cached Processes, and kill the app in question.
3) Re-launch the app and just tap off the authenticate dialog.
4) App will crash with:
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.biometric.BiometricPrompt$AuthenticationCallback.onAuthenticationError(int, java.lang.CharSequence)' on a null object reference
at androidx.biometric.FingerprintHelperFragment.sendErrorToClient(FingerprintHelperFragment.java:268)
at androidx.biometric.FingerprintHelperFragment.cancel(FingerprintHelperFragment.java:224)
at androidx.biometric.FingerprintDialogFragment.onCancel(FingerprintDialogFragment.java:215)
at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1364)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
1) Display authenticate dialog on Oreo. Don't apply fingerprint.
2) Go to developer settings > Running Services > Show Cached Processes, and kill the app in question.
3) Re-launch the app and just tap off the authenticate dialog.
4) App will crash with:
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.biometric.BiometricPrompt$AuthenticationCallback.onAuthenticationError(int, java.lang.CharSequence)' on a null object reference
at androidx.biometric.FingerprintHelperFragment.sendErrorToClient(FingerprintHelperFragment.java:268)
at androidx.biometric.FingerprintHelperFragment.cancel(FingerprintHelperFragment.java:224)
at androidx.biometric.FingerprintDialogFragment.onCancel(FingerprintDialogFragment.java:215)
at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1364)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
ph...@gmail.com <ph...@gmail.com> #13
I'll spend some time and make an app that demonstrates these issues so that you can work to tighten up this library.
ph...@gmail.com <ph...@gmail.com> #14
I spent some time extracting out a small working example of what I'm seeing with alpha03. There's some sort of issue with callback reuse in there for sure. alpha02 with this example (just have to change a version number and import in BiometricRepository.kt). Hope it helps find some issues.
What I'm seeing when I run the test app:
1) App will begin with an Enroll button showing.
2) Tap the Enroll button.
3) Present fingerprint.
4) Should be able to tap the Login button to authenticate.
5) Login dialog will show.
6) Present fingerprint.
7) App will crash because the callback being used will be the 'Enroll' callback, not the 'Login' callback.
Open App again.
8) Login dialog will show.
9) Present fingerprint
10) Should see Authenticated toast.
11) Tap Login Button
12) Present Fingerprint
13) App will crash because the login callback (from the initial run) is being reused again, and it's stale.
I fully expect I could be doing something wrong with the API. I also apologize in advance, the app is code extracted from a much larger project and I removed all of the Dagger 2, and just brought in what I needed, so it's a bit of a mess.
I really can't explain the behaviour I'm seeing on alpha03, I hope this helps find out what's wrong.
What I'm seeing when I run the test app:
1) App will begin with an Enroll button showing.
2) Tap the Enroll button.
3) Present fingerprint.
4) Should be able to tap the Login button to authenticate.
5) Login dialog will show.
6) Present fingerprint.
7) App will crash because the callback being used will be the 'Enroll' callback, not the 'Login' callback.
Open App again.
8) Login dialog will show.
9) Present fingerprint
10) Should see Authenticated toast.
11) Tap Login Button
12) Present Fingerprint
13) App will crash because the login callback (from the initial run) is being reused again, and it's stale.
I fully expect I could be doing something wrong with the API. I also apologize in advance, the app is code extracted from a much larger project and I removed all of the Dagger 2, and just brought in what I needed, so it's a bit of a mess.
I really can't explain the behaviour I'm seeing on alpha03, I hope this helps find out what's wrong.
Description
Version used:1.0.0-alpha03
Theme used:Theme.MaterialComponents.Light.NoActionBar"
Devices/Android versions reproduced on:
- Galaxy S9+/8.0.0
- Emulator/9.0.0
- Relevant code to trigger the issue.
override fun onResume() {
super.onResume()
DataManager.instance.getBiometricCredential(this)?.let {
BiometricUtils.authenticateBiometric(this,
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int,
errString: CharSequence) {
Log.d(TAG,
"onAuthenticationError - errorCode: $errorCode, errorString: $errString")
if(errorCode != BiometricPrompt.ERROR_CANCELED) {
R.string.unable_to_verify_fingerprint,
null,
null,
R.string.dismiss,
null,
null,
{ dialog -> dialog.dismiss() },
true))
}
}
override fun onAuthenticationFailed() {
Log.d(TAG, "onAuthenticationFailed")
R.string.unable_to_verify_fingerprint,
null,
null,
R.string.dismiss,
null,
null,
{ dialog -> dialog.dismiss() },
true))
}
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
val user = DataManager.instance.getBiometricCredential(
context)
Log.d(TAG,
"onAuthenticationSucceeded - logging in biometric user: ${user?.id
?: ""}")
user?.let {
binding.textEmail.setText(user.username)
binding.textPassword.setText(user.password)
signIn()
} ?: run {
R.string.error_general_error_message,
null,
null,
R.string.dismiss,
null,
null,
{ dialog -> dialog.dismiss() },
true))
}
}
})
}
}
fun authenticateBiometric(activity: FragmentActivity,
callback: BiometricPrompt.AuthenticationCallback) {
var signature: Signature? = null
try {
KeyStoreUtil.getKeyPair(KeyStoreUtil.BIOMETRIC)?.let {
signature = Signature.getInstance("SHA256withECDSA")
signature?.initSign(it.private)
}
} catch (e: Exception) {
}
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle(stringProvider.getString(R.string.fingerprint_login))
.setDescription("")
.setNegativeButtonText(stringProvider.getString(R.string.cancel))
.build()
signature?.let {
BiometricPrompt(activity, TaskExecutors.MAIN_THREAD, callback).authenticate(promptInfo,
BiometricPrompt.CryptoObject(
it))
}
}
Pressing cancel on the BiometricDialog produces the following exception:
2018-12-27 15:14:00.933 5960-5960/
Process:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.CharSequence androidx.biometric.FingerprintDialogFragment.getNegativeButtonText()' on a null object reference
at androidx.biometric.BiometricPrompt$1$1.run(BiometricPrompt.java:336)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)