Android 使用设备凭据时生物识别不导航
Android Biometrics not navigating when using Device Credentials
我正在使用生物识别库来锁定应用程序。一切正常,当我使用指纹解锁时 onAuthenticationSucceeded() 被调用并且设备从锁定屏幕导航。但是,如果使用模式解锁,则会调用 onAuthenticationSucceeded() 但导航不会初始化,我会卡在锁定屏幕片段上。
编辑:这只影响具有任何设备凭据的 API29
EDIT2:我也得到了
FragmentNavigator: Ignoring popBackStack() call: FragmentManager has
already saved its state
FragmentNavigator: Ignoring navigate() call: FragmentManager has already saved its state
private lateinit var biometricPrompt: BiometricPrompt
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
biometricPrompt = createBiometricPrompt()
return inflater.inflate(R.layout.lock_screen_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val isAppLockEnabled: Boolean = PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean("lock_app_preference", false)
// If app locks is not set go to home fragment else display app lock screen
if (!isAppLockEnabled) {
findNavController().navigate(R.id.action_lock_screen_fragment_dest_to_home_fragment_dest)
} else {
// Prompt appears when user clicks "Unlock".
unlock_button.setOnClickListener {
val promptInfo = createPromptInfo()
biometricPrompt.authenticate(promptInfo)
}
}
}
private fun createBiometricPrompt(): BiometricPrompt {
val executor = ContextCompat.getMainExecutor(context)
val callback = object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
Log.d("AuthenticationError()", "$errorCode :: $errString")
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
Log.d("AuthenticationFailed()", "Authentication failed for an unknown reason")
}
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
lock_icon.setImageResource(R.drawable.ic_unlock)
lock_screen_text_view.text = getString(R.string.app_unlocked)
//This doesn't work when using pattern unlock findNavController().navigate(R.id.action_lock_screen_fragment_dest_to_home_fragment_dest)
}
}
return BiometricPrompt(this, executor, callback)
}
private fun createPromptInfo(): BiometricPrompt.PromptInfo {
return BiometricPrompt.PromptInfo.Builder()
.setTitle("Unlock App")
.setConfirmationRequired(false)
.setDeviceCredentialAllowed(true)
.build()
}
}
好的,所以我解决了这个问题。将导航从 onAuthenticationSucceeded() 移动到片段 onResume()。设备凭据 window 暂停了我的应用程序,之后无法以某种方式调用导航。
解决方案代码:
private var isAppUnlocked : Boolean = false
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
isAppUnlocked = true
unlockApp()
Log.d("AuthenticationSuccess", "Authentication succeeded")
}
override fun onResume() {
super.onResume()
if(isAppUnlocked){
unlockApp()
}
}
private fun unlockApp(){
lock_icon.setImageResource(R.drawable.ic_unlock)
lock_screen_text_view.text = getString(R.string.app_unlocked)
findNavController().navigate(R.id.action_lock_screen_fragment_dest_to_home_fragment_dest)
}
我正在使用生物识别库来锁定应用程序。一切正常,当我使用指纹解锁时 onAuthenticationSucceeded() 被调用并且设备从锁定屏幕导航。但是,如果使用模式解锁,则会调用 onAuthenticationSucceeded() 但导航不会初始化,我会卡在锁定屏幕片段上。
编辑:这只影响具有任何设备凭据的 API29
EDIT2:我也得到了
FragmentNavigator: Ignoring popBackStack() call: FragmentManager has already saved its state
FragmentNavigator: Ignoring navigate() call: FragmentManager has already saved its state
private lateinit var biometricPrompt: BiometricPrompt
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
biometricPrompt = createBiometricPrompt()
return inflater.inflate(R.layout.lock_screen_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val isAppLockEnabled: Boolean = PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean("lock_app_preference", false)
// If app locks is not set go to home fragment else display app lock screen
if (!isAppLockEnabled) {
findNavController().navigate(R.id.action_lock_screen_fragment_dest_to_home_fragment_dest)
} else {
// Prompt appears when user clicks "Unlock".
unlock_button.setOnClickListener {
val promptInfo = createPromptInfo()
biometricPrompt.authenticate(promptInfo)
}
}
}
private fun createBiometricPrompt(): BiometricPrompt {
val executor = ContextCompat.getMainExecutor(context)
val callback = object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
Log.d("AuthenticationError()", "$errorCode :: $errString")
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
Log.d("AuthenticationFailed()", "Authentication failed for an unknown reason")
}
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
lock_icon.setImageResource(R.drawable.ic_unlock)
lock_screen_text_view.text = getString(R.string.app_unlocked)
//This doesn't work when using pattern unlock findNavController().navigate(R.id.action_lock_screen_fragment_dest_to_home_fragment_dest)
}
}
return BiometricPrompt(this, executor, callback)
}
private fun createPromptInfo(): BiometricPrompt.PromptInfo {
return BiometricPrompt.PromptInfo.Builder()
.setTitle("Unlock App")
.setConfirmationRequired(false)
.setDeviceCredentialAllowed(true)
.build()
}
}
好的,所以我解决了这个问题。将导航从 onAuthenticationSucceeded() 移动到片段 onResume()。设备凭据 window 暂停了我的应用程序,之后无法以某种方式调用导航。
解决方案代码:
private var isAppUnlocked : Boolean = false
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
isAppUnlocked = true
unlockApp()
Log.d("AuthenticationSuccess", "Authentication succeeded")
}
override fun onResume() {
super.onResume()
if(isAppUnlocked){
unlockApp()
}
}
private fun unlockApp(){
lock_icon.setImageResource(R.drawable.ic_unlock)
lock_screen_text_view.text = getString(R.string.app_unlocked)
findNavController().navigate(R.id.action_lock_screen_fragment_dest_to_home_fragment_dest)
}