Status Update
Comments
ex...@gmail.com <ex...@gmail.com> #2
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)
gm...@gmail.com <gm...@gmail.com> #3
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.
kc...@google.com <kc...@google.com> #4
gm...@gmail.com <gm...@gmail.com> #5
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,
gm...@gmail.com <gm...@gmail.com> #6
ex...@gmail.com <ex...@gmail.com> #7
gm...@gmail.com <gm...@gmail.com> #8
ex...@gmail.com <ex...@gmail.com> #9
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.
jo...@gmail.com <jo...@gmail.com> #10
na...@gmail.com <na...@gmail.com> #11
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.
ex...@gmail.com <ex...@gmail.com> #12
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)
ex...@gmail.com <ex...@gmail.com> #13
an...@atlassian.com <an...@atlassian.com> #14
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.
an...@gmail.com <an...@gmail.com> #15
du...@google.com <du...@google.com>
gm...@gmail.com <gm...@gmail.com> #16
1) clear steps to repro
2) full bugreport (not just the stacktrace), "adb bugreport issue.zip"
3) optionally, attach sample code to repro (less necessary if bugreport is there, but is still useful so I can see what you're doing / trying to do)
Comments on the previous comments
Starting on
#9) It's possible for your executor to be null, how did you reproduce this issue, was it the same as the steps in
aosp-androidx/samples/BiometricDemos/src/main/java/com/example/android/biometric/BiometricPromptDemo.java
#11) looks like a similar issue, can you try the suggestion above?
#12) I need more info, can you clarify what " tap off the authenticate dialog." means? Can you attach a full bugreport? Bits of stack traces are not enough to understand the issue
kc...@google.com <kc...@google.com> #18
In alpha03, as long as the library correctly handles fragments, and also correctly handles the callbacks given to it, I believe this bug report can be closed. Though the app attached in
ry...@gmail.com <ry...@gmail.com> #19
gm...@gmail.com <gm...@gmail.com> #20
Steps to reproduce:
1) Display authenticate dialog on Oreo. Don't apply fingerprint.
2) Perform 2a) or 2b). Performing 2a) I was able to reproduce issue more often comparing with similar 2b).
2a) Open bunch of heavy apps: youtube, gmail, playstore etc;
2b) 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
In my opinion the reason of AuthenticationCallback == null is that
a) this callback is assigned in 2 places only (see code below);
b) when application is restored after process death, the retained fragment mFingerprintHelperFragment is also restored and sometimes when mLifecycleObserver.onResume() is called (see Place 1):
1) After this call:
mFingerprintHelperFragment = (FingerprintHelperFragment) mFragmentActivity.getSupportFragmentManager().findFragmentByTag(FINGERPRINT_HELPER_FRAGMENT_TAG);
mFingerprintHelperFragment sometimes is null because mFingerprintHelperFragment fragment transaction sometimes is not started yet and FragmentManager doesn't reference such a fragment;
2) Therefore this check returns false and callback is not set:
if (mFingerprintDialogFragment != null && mFingerprintHelperFragment != null) {
mFingerprintHelperFragment.setCallback(mExecutor, mAuthenticationCallback);
c) when BiometricPrompt.authenticate() is called (see Place 2), mFingerprintHelperFragment fragment transaction is already started and this check
if (mFingerprintHelperFragment == null)
fails (because mFingerprintHelperFragment is not null) and again callback is not set:
mFingerprintHelperFragment.setCallback(mExecutor, mAuthenticationCallback);
androidx.biometric.BiometricPrompt.java
Place 1.
private final LifecycleObserver mLifecycleObserver = new LifecycleObserver() {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume() {
...
mFingerprintHelperFragment = (FingerprintHelperFragment) mFragmentActivity
.getSupportFragmentManager().findFragmentByTag(
FINGERPRINT_HELPER_FRAGMENT_TAG);
if (mFingerprintDialogFragment != null && mFingerprintHelperFragment != null) {
mFingerprintHelperFragment.setCallback(mExecutor, mAuthenticationCallback);
Place 2.
private void authenticateInternal(@NonNull PromptInfo info, @Nullable CryptoObject crypto) {
...
if (mFingerprintHelperFragment == null) {
mFingerprintHelperFragment = FingerprintHelperFragment.newInstance();
mFingerprintHelperFragment.setCallback(mExecutor, mAuthenticationCallback);
}
no...@gmail.com <no...@gmail.com> #21
Let's get this fixed! These are some serious fragment bugs.
gm...@gmail.com <gm...@gmail.com> #22
```
override fun onPause() {
// WORKAROUND for
supportFragmentManager.fragments.filter { it is BiometricFragment || it is FingerprintDialogFragment }.forEach {
supportFragmentManager.beginTransaction().remove(it).commitNow()
}
super.onPause()
}
```
[Deleted User] <[Deleted User]> #23
```
fun FragmentManager.removeBiometricFragments() {
fragments.filter {
it is BiometricFragment || it is FingerprintDialogFragment || it is FingerprintHelperFragment
}.forEach {
beginTransaction().remove(it).commitNow()
}
}
```
[Deleted User] <[Deleted User]> #24
```
fun FragmentManager.removeBiometricFragments() {
findFragmentByTag("FingerprintDialogFragment")?.let {
(it as DialogFragment).dismiss()
}
findFragmentByTag("FingerprintHelperFragment")?.let {
beginTransaction().remove(it).commitNow()
}
findFragmentByTag("BiometricFragment")?.let {
beginTransaction().remove(it).commitNow()
}
}
```
kc...@google.com <kc...@google.com> #25
[Deleted User] <[Deleted User]> #26
th...@googlemail.com <th...@googlemail.com> #27
Besides, the workaround from #24 needs improvements. Before removing fragments;
fragment.setRetainInstance(false);
to avoid state saving for the biometric fragments.
cu...@google.com <cu...@google.com>
da...@gmail.com <da...@gmail.com> #28
ma...@asaas.com.br <ma...@asaas.com.br> #29
se...@gratisbroker.de <se...@gratisbroker.de> #30
ir...@gmail.com <ir...@gmail.com> #31
ca...@gmail.com <ca...@gmail.com> #32
ma...@gmail.com <ma...@gmail.com> #33
jo...@motorolasolutions.com <jo...@motorolasolutions.com> #34
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getString(int)' on a null object reference
at androidx.biometric.BiometricFragment$2$1.run(BiometricFragment.java:86)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7045)
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:964)
pi...@gmail.com <pi...@gmail.com> #35
Just to add to this - we've seen this issue on the Samsung Galaxy A40 as well.
However it only happens sporadically meaning, that the user will be able to authenticate correctly after a few tries, but when opening our app usually the first time using the Device Credentials won't work and the user will just end up on our login screen. If they try a few times with Device Credentials they'll be able to login.
The user has biometrics enrolled, but chose to use the Device Credentials instead.
If I set the allowed authenticators to DEVICE_CREDENTIALS only the user will be able to login immediately, but the combination of BIOMETRIC_WEAK and DEVICE_CREDENTIALS will create this weird behaviour.
Also if I set the allowed authenticators to DEVICE_CREDENTIALS only then when I call BiometricManager.canAuthenticate(Authenticators.DEVICE_CREDENTIAL)
it returns BIOMETRIC_ERROR_UNSUPPORTED
and so I end up using the old KeyguardManager
to create a Device Credentials Activity.
This is truly a mess of proportions with all these weird bugs depending on what version of Android and what device you're running on.
I'm wondering why it seems that you won't just stop the new development on this project for just a while and look at all the bugs being reported and fix these bugs before you move on to new things, like Kotlin Extensions etc. I feel like you're just making a mockery of the community by just keep on adding new features instead of fixing whatever bugs comes up. :-(
ps...@gmail.com <ps...@gmail.com> #36
ps...@gmail.com <ps...@gmail.com> #37
ps...@gmail.com <ps...@gmail.com> #38
Google NAMESPACE:Patrick Rene Guerrero
ERRATA-ID:RFC2119
NAME:ALBUQUERQUE-RDP-V6-1
HANDLE:ICI 61-ARIN
Copyright License(2021) and Official Patent Holder, Patrick Rene Guerrero,.
Bug Bounty Hunter and Fiscal EARNINGS and ALL PROCEEDS MUST GO TO THE PROPER IDENTITY , IDENTIFIED as
ps...@gmail.com <ps...@gmail.com> #39
ORGANIZATION: JCS Enterprises LLC
NAME: Patrick Rene Guerrero
STATUS:VALIDATED
NETWORK:ALBUQUERQUE-RDP-V6-1
Charter: IPNGP
OBSOLETES:RFC2119
Email:
ps...@gmail.com <ps...@gmail.com> #40
ORGANIZATION: JCS Enterprises LLC
NAME: Patrick Rene Guerrero
STATUS:VALIDATED
NETWORK:ALBUQUERQUE-RDP-V6-1
Charter: IPNGP
OBSOLETES:RFC2119
Email:
ys...@gmail.com <ys...@gmail.com> #41
Do you have any news about this issue? We receive many similar open points in our side. Do you plan to release a fix?
Thank you,
ps...@gmail.com <ps...@gmail.com> #42
cu...@google.com <cu...@google.com> #43
Version 1.2.0-alpha04 (releasing today) has a workaround that should fix this for most, if not all, devices.
kc...@google.com <kc...@google.com>
an...@gmail.com <an...@gmail.com> #44
me...@gmail.com <me...@gmail.com> #45
1.2.0-alpha04 doesn't fix anything on a Samsung S6, running OS on API 26. Doesn't matter if fingerprints are enrolled.
Calling this:
prompt = new BiometricPrompt.PromptInfo.Builder()
.setTitle(title)
.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
.build();
Results in this, when the authentication screen is supposed to come:
java.lang.IllegalArgumentException: Authenticator combination is unsupported on API 26: DEVICE_CREDENTIAL
at androidx.biometric.BiometricPrompt$PromptInfo$Builder.build(BiometricPrompt.java:579)
at ccom.example.app.util.bioPinAuthentication.authenticate(auth.java:76)
at ccom.example.app.MainActivity.authBio(MainActivity.java:346)
at ccom.example.app.MainActivity.onResume(MainActivity.java:479)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1361)
at android.app.Activity.performResume(Activity.java:7415)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3765)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3830)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3038)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
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)
What I want to do is use PIN only, but it only works when this is called and no fingerprints are enrolled on the device:
prompt = new BiometricPrompt.PromptInfo.Builder()
.setTitle(title)
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.BIOMETRIC_WEAK | BiometricManager.Authenticators.DEVICE_CREDENTIAL)
.build();
Don't know if this is a completely unrelated issue from all above.
an...@gmail.com <an...@gmail.com> #46
In reply to last comment: To use (PIN||pattern||password||biometric if enrolled), forget about this biometric API and use the legacy
em...@gmail.com <em...@gmail.com> #47
st...@gmail.com <st...@gmail.com> #48
Tried the solution of #46, but createConfirmDeviceCredentialIntent() also always returns Canceled.
Description
BUILD INFO
- Device type: Emulator x86_64
- OS version: Android Q
- Biometric library version: 1.0.0-rc1
STEPS TO REPRODUCE
1. Run emulator
2. Set Fingerprint+pattern
3. Run project
4. Tap button
5. Tap 'Use pattern'
EXPECTED RESULTS
Authentication canceled error hasn't been thrown.
OBSERVED RESULTS
Authentication canceled error has been thrown.
NUMBER OF TIMES YOU WERE ABLE TO REPRODUCE
Always
I used Basic activity Android Studio template with the next code:
package com.myapplication
import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricPrompt
import androidx.biometric.BiometricPrompt.AuthenticationCallback
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
@SuppressLint("NewApi")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
fab.setOnClickListener { view ->
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("test")
.setDeviceCredentialAllowed(true)
.build();
val prompt = BiometricPrompt(this, this.mainExecutor, object : AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
Log.e("Authentication", "Cancel");
super.onAuthenticationError(errorCode, errString)
}
})
prompt.authenticate(promptInfo);
}
}
}