From bd15e36b52681b6c10ebbfece6d7c9200ef4d2b0 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Fri, 22 Aug 2025 22:50:58 +0200 Subject: [PATCH] fix: Multiple biometric prompt --- .../keepass/biometric/DeviceUnlockFragment.kt | 114 +++++++++--------- 1 file changed, 59 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/biometric/DeviceUnlockFragment.kt b/app/src/main/java/com/kunzisoft/keepass/biometric/DeviceUnlockFragment.kt index 884e11de4..4bf24f4f8 100644 --- a/app/src/main/java/com/kunzisoft/keepass/biometric/DeviceUnlockFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/biometric/DeviceUnlockFragment.kt @@ -133,37 +133,39 @@ class DeviceUnlockFragment: Fragment() { viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) { mDeviceUnlockViewModel.uiState.collect { uiState -> - lifecycleScope.launch(Dispatchers.Main) { - // Change mode - toggleDeviceCredentialMode(uiState.newDeviceUnlockMode) - // Prompt - manageDeviceCredentialPrompt(uiState.cryptoPromptState) - // Advanced menu - mAllowDeviceUnlockMenu = uiState.allowDeviceUnlockMenu - activity?.invalidateOptionsMenu() - } + // Change mode + toggleDeviceCredentialMode(uiState.newDeviceUnlockMode) + // Prompt + manageDeviceCredentialPrompt(uiState.cryptoPromptState) + // Advanced menu + mAllowDeviceUnlockMenu = uiState.allowDeviceUnlockMenu + activity?.invalidateOptionsMenu() } } } } fun cancelBiometricPrompt() { - mBiometricPrompt?.cancelAuthentication() + lifecycleScope.launch(Dispatchers.Main) { + mBiometricPrompt?.cancelAuthentication() + } } private fun toggleDeviceCredentialMode(deviceUnlockMode: DeviceUnlockMode) { - try { - when (deviceUnlockMode) { - DeviceUnlockMode.BIOMETRIC_UNAVAILABLE -> setNotAvailableMode() - DeviceUnlockMode.BIOMETRIC_SECURITY_UPDATE_REQUIRED -> setSecurityUpdateRequiredMode() - DeviceUnlockMode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED -> setNotConfiguredMode() - DeviceUnlockMode.KEY_MANAGER_UNAVAILABLE -> setKeyManagerNotAvailableMode() - DeviceUnlockMode.WAIT_CREDENTIAL -> setWaitCredentialMode() - DeviceUnlockMode.STORE_CREDENTIAL -> setStoreCredentialMode() - DeviceUnlockMode.EXTRACT_CREDENTIAL -> setExtractCredentialMode() + lifecycleScope.launch(Dispatchers.Main) { + try { + when (deviceUnlockMode) { + DeviceUnlockMode.BIOMETRIC_UNAVAILABLE -> setNotAvailableMode() + DeviceUnlockMode.BIOMETRIC_SECURITY_UPDATE_REQUIRED -> setSecurityUpdateRequiredMode() + DeviceUnlockMode.DEVICE_CREDENTIAL_OR_BIOMETRIC_NOT_CONFIGURED -> setNotConfiguredMode() + DeviceUnlockMode.KEY_MANAGER_UNAVAILABLE -> setKeyManagerNotAvailableMode() + DeviceUnlockMode.WAIT_CREDENTIAL -> setWaitCredentialMode() + DeviceUnlockMode.STORE_CREDENTIAL -> setStoreCredentialMode() + DeviceUnlockMode.EXTRACT_CREDENTIAL -> setExtractCredentialMode() + } + } catch (e: Exception) { + mDeviceUnlockViewModel.setException(e) } - } catch (e: Exception) { - mDeviceUnlockViewModel.setException(e) } } @@ -186,44 +188,46 @@ class DeviceUnlockFragment: Fragment() { } private fun openPrompt(cryptoPrompt: DeviceUnlockCryptoPrompt) { - try { - val promptTitle = getString(cryptoPrompt.titleId) - val promptDescription = cryptoPrompt.descriptionId?.let { descriptionId -> - getString(descriptionId) - } ?: "" + lifecycleScope.launch(Dispatchers.Main) { + try { + val promptTitle = getString(cryptoPrompt.titleId) + val promptDescription = cryptoPrompt.descriptionId?.let { descriptionId -> + getString(descriptionId) + } ?: "" - if (cryptoPrompt.isBiometricOperation) { - mBiometricPrompt?.authenticate( - BiometricPrompt.PromptInfo.Builder().apply { - setTitle(promptTitle) - if (promptDescription.isNotEmpty()) - setDescription(promptDescription) - setConfirmationRequired(false) - if (isDeviceCredentialBiometricOperation(context)) { - setAllowedAuthenticators(DEVICE_CREDENTIAL) - } else { - setNegativeButtonText(getString(android.R.string.cancel)) - } - }.build(), - BiometricPrompt.CryptoObject(cryptoPrompt.cipher) - ) - } else if (cryptoPrompt.isDeviceCredentialOperation) { - context?.let { context -> - @Suppress("DEPRECATION") - mDeviceCredentialResultLauncher?.launch( - ContextCompat.getSystemService( - context, - KeyguardManager::class.java - )?.createConfirmDeviceCredentialIntent( - promptTitle, - promptDescription - ) + if (cryptoPrompt.isBiometricOperation) { + mBiometricPrompt?.authenticate( + BiometricPrompt.PromptInfo.Builder().apply { + setTitle(promptTitle) + if (promptDescription.isNotEmpty()) + setDescription(promptDescription) + setConfirmationRequired(false) + if (isDeviceCredentialBiometricOperation(context)) { + setAllowedAuthenticators(DEVICE_CREDENTIAL) + } else { + setNegativeButtonText(getString(android.R.string.cancel)) + } + }.build(), + BiometricPrompt.CryptoObject(cryptoPrompt.cipher) ) + } else if (cryptoPrompt.isDeviceCredentialOperation) { + context?.let { context -> + @Suppress("DEPRECATION") + mDeviceCredentialResultLauncher?.launch( + ContextCompat.getSystemService( + context, + KeyguardManager::class.java + )?.createConfirmDeviceCredentialIntent( + promptTitle, + promptDescription + ) + ) + } } + } catch (e: Exception) { + Log.e(TAG, "Unable to open prompt", e) + mDeviceUnlockViewModel.setException(e) } - } catch (e: Exception) { - Log.e(TAG, "Unable to open prompt", e) - mDeviceUnlockViewModel.setException(e) } }