Fixed
Status Update
Comments
vi...@google.com <vi...@google.com>
vi...@google.com <vi...@google.com>
em...@gmail.com <em...@gmail.com> #2
A couple of questions:
1. Have you saw crash in real device or only in simulators?
2. Do you use dynamic feature for language ID?
1. Have you saw crash in real device or only in simulators?
2. Do you use dynamic feature for language ID?
cu...@google.com <cu...@google.com>
ap...@google.com <ap...@google.com> #3
Tested on Android 12 Emulator with custom executor, but cannot repro this issue.
ob...@gmail.com <ob...@gmail.com> #4
-
Second crash in the description is from a real device. Experienced it myself on two different Xiaomi phones, plus lots of crashes from users in the Google Play console.
-
Dynamic features are not used in the application.
As a wild guess, I have downgraded build tools from 31.0.0 to 30.0.3, compileSdk from 31 to 30, and moved all work with Language ID to the service in a separate process (just to be sure that crash can kill secondary process instead of main). This combination is in beta for 2 days by now and I don't see any SIGSEGV crashes.
Description
Here is the if statement where the decision is made (line 716 of BiometricPrompt)
if (!shouldForceFingerprint && canUseBiometricFragment())
canUseBiometricFragment() only checks if the device is running API 28+ and shouldForceFingerprint is calculated mainly by shouldUseFingerprintforCrypto() . That method iterates through a list of devices that are considered not safe for crypto, all of them seem to be Samsung devices. The issue is that the code goes down the path of “I am running API 28 or grater so I am good to go” . This in turn tries to use the FingerprintManager class to get a string for the error during getErrorString(). This is null for our device since the hardware is not there. Devices that do not pass the if check from above (my Nexus 5 running API 23 for example) use the FingerprintHelperFragment and FingerprintDialogFragment classes to correctly handle not having a hardware sensor.
Here is the stacktrace of the issue:
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.hardware.fingerprint.FingerprintManager.getErrorString(int, int)' on a null object reference
at android.hardware.biometrics.BiometricPrompt.lambda$sendError$0(BiometricPrompt.java:490)
at android.hardware.biometrics.-$$Lambda$BiometricPrompt$HqBGXtBUWNc-v8NoHYsj2gLfaRw.run(-.java:6)
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:6725)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
The code should not use BiometricFragment for this scenario or if it does, BiometricFragment should check internally before using the FingerprintManager. Probably, the best solution is to have the code handle this case to use FingerprintHelperFragment and FingerprintDialogFragment.
library version: androidx.biometric:biometric:1.0.1
device: ATT Radiant (running Android 9.0 Go)