Fixed
Status Update
Comments
al...@google.com <al...@google.com>
al...@google.com <al...@google.com> #2
Thank you for reporting this issue. For us to further investigate this issue, please provide the following additional information:
Please 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.
Expected output
What do you expect to occur?
Current output
What do you see instead?
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.
Please 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.
Expected output
What do you expect to occur?
Current output
What do you see instead?
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.
al...@google.com <al...@google.com> #3
ok, I did some more research, turns out that callback notification goes to the if we press "cancel" button but goes wrong when authentication succeeds
as you can see in the attached project
if you open the bio-prompt in the 1st Fragment and authenticate
and after that you go to the 2nd Fragment and authenticate in the bio-prompt
callback notifies the Fragment1 instead of the Fragment2 as you can see in the logs
expected result is that Fragment2 is notified instead of Fragment1
also if you first go to Fragment2 and after that you go to Fragment1 always opening the prompt and doing the authentication
Fragment2 is notified instead of Fragment1
funny thing is that doing cancel instead of authentication notification works ok
https://drive.google.com/open?id=1ZVhp9sFBJ6pa1bKzHg1AM5tF5XnmyFMM
as you can see in the attached project
if you open the bio-prompt in the 1st Fragment and authenticate
and after that you go to the 2nd Fragment and authenticate in the bio-prompt
callback notifies the Fragment1 instead of the Fragment2 as you can see in the logs
expected result is that Fragment2 is notified instead of Fragment1
also if you first go to Fragment2 and after that you go to Fragment1 always opening the prompt and doing the authentication
Fragment2 is notified instead of Fragment1
funny thing is that doing cancel instead of authentication notification works ok
bu...@google.com <bu...@google.com> #4
manually closing the FingerprintHelperFragment works as a workaround
```
override fun onPause() {
// WORKAROUND forhttps://issuetracker.google.com/issues/123857949
activity?.let { activity ->
activity.supportFragmentManager.findFragmentByTag("FingerprintHelperFragment")?.let {
activity.supportFragmentManager.beginTransaction().remove(it).commitAllowingStateLoss()
}
super.onPause()
}
}
```
```
override fun onPause() {
// WORKAROUND for
activity?.let { activity ->
activity.supportFragmentManager.findFragmentByTag("FingerprintHelperFragment")?.let {
activity.supportFragmentManager.beginTransaction().remove(it).commitAllowingStateLoss()
}
super.onPause()
}
}
```
bu...@google.com <bu...@google.com>
ap...@google.com <ap...@google.com> #5
se...@gmail.com <se...@gmail.com> #6
Comment has been deleted.
je...@gmail.com <je...@gmail.com> #7
Comment has been deleted.
je...@gmail.com <je...@gmail.com> #8
Comment has been deleted.
po...@gmail.com <po...@gmail.com> #9
My mistake in point one:
1. Biometric#mLifecycleObserver#onResume should call mFingerprintHelperFragment.setCallback(...) even if mFingerprintDialogFragment is null.
Here is my temporary fix. Just place it in androidx.biometric package and use it like BiometricPrompt:
package androidx.biometric
import android.annotation.SuppressLint
import androidx.fragment.app.FragmentActivity
import java.util.concurrent.Executor
/**
* Fix for isssuehttps://issuetracker.google.com/issues/123857949
*/
@SuppressLint("RestrictedApi")
class FixedBiometricPrompt(
private val fragmentActivity: FragmentActivity,
executor: Executor,
callback: BiometricPrompt.AuthenticationCallback
) {
private val delegate: BiometricPrompt
init {
// set executor and callback to helper fragment
(fragmentActivity.supportFragmentManager.findFragmentByTag("FingerprintHelperFragment") as? FingerprintHelperFragment)?.setCallback(
executor,
callback
)
delegate = BiometricPrompt(fragmentActivity, executor, callback)
}
fun authenticate(info: BiometricPrompt.PromptInfo, crypto: BiometricPrompt.CryptoObject) {
delegate.authenticate(info, crypto)
}
fun authenticate(info: BiometricPrompt.PromptInfo) {
delegate.authenticate(info)
}
fun cancelAuthentication() {
delegate.cancelAuthentication()
}
fun cleanup() {
// remove executor and callback from helper fragment to prevent memory leak
(fragmentActivity.supportFragmentManager.findFragmentByTag("FingerprintHelperFragment") as? FingerprintHelperFragment)?.setCallback(
null,
null
)
}
}
1. Biometric#mLifecycleObserver#onResume should call mFingerprintHelperFragment.setCallback(...) even if mFingerprintDialogFragment is null.
Here is my temporary fix. Just place it in androidx.biometric package and use it like BiometricPrompt:
package androidx.biometric
import android.annotation.SuppressLint
import androidx.fragment.app.FragmentActivity
import java.util.concurrent.Executor
/**
* Fix for isssue
*/
@SuppressLint("RestrictedApi")
class FixedBiometricPrompt(
private val fragmentActivity: FragmentActivity,
executor: Executor,
callback: BiometricPrompt.AuthenticationCallback
) {
private val delegate: BiometricPrompt
init {
// set executor and callback to helper fragment
(fragmentActivity.supportFragmentManager.findFragmentByTag("FingerprintHelperFragment") as? FingerprintHelperFragment)?.setCallback(
executor,
callback
)
delegate = BiometricPrompt(fragmentActivity, executor, callback)
}
fun authenticate(info: BiometricPrompt.PromptInfo, crypto: BiometricPrompt.CryptoObject) {
delegate.authenticate(info, crypto)
}
fun authenticate(info: BiometricPrompt.PromptInfo) {
delegate.authenticate(info)
}
fun cancelAuthentication() {
delegate.cancelAuthentication()
}
fun cleanup() {
// remove executor and callback from helper fragment to prevent memory leak
(fragmentActivity.supportFragmentManager.findFragmentByTag("FingerprintHelperFragment") as? FingerprintHelperFragment)?.setCallback(
null,
null
)
}
}
Description
Public class
androidx.appcompat.graphics.drawable.AnimatedStateListDrawableCompat
inherits some public methods from its restricted parent classandroidx.appcompat.graphics.drawable.StateListDrawable
. Let's inline those methods intoAnimatedStateListDrawable
so they're not hidden.