mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Better unlock settings
This commit is contained in:
@@ -90,12 +90,12 @@ class UnavailableFeatureDialogFragment : DialogFragment() {
|
||||
}
|
||||
}
|
||||
if (apiName.isEmpty()) {
|
||||
val mapper = arrayOf("ANDROID BASE", "ANDROID BASE 1.1", "CUPCAKE", "DONUT", "ECLAIR", "ECLAIR_0_1", "ECLAIR_MR1", "FROYO", "GINGERBREAD", "GINGERBREAD_MR1", "HONEYCOMB", "HONEYCOMB_MR1", "HONEYCOMB_MR2", "ICE_CREAM_SANDWICH", "ICE_CREAM_SANDWICH_MR1", "JELLY_BEAN", "JELLY_BEAN", "JELLY_BEAN", "KITKAT", "KITKAT", "LOLLIPOOP", "LOLLIPOOP_MR1", "MARSHMALLOW", "NOUGAT", "NOUGAT", "OREO", "OREO")
|
||||
val mapper = arrayOf("ANDROID BASE", "ANDROID BASE 1.1", "CUPCAKE", "DONUT", "ECLAIR", "ECLAIR_0_1", "ECLAIR_MR1", "FROYO", "GINGERBREAD", "GINGERBREAD_MR1", "HONEYCOMB", "HONEYCOMB_MR1", "HONEYCOMB_MR2", "ICE_CREAM_SANDWICH", "ICE_CREAM_SANDWICH_MR1", "JELLY_BEAN", "JELLY_BEAN", "JELLY_BEAN", "KITKAT", "KITKAT", "LOLLIPOOP", "LOLLIPOOP_MR1", "MARSHMALLOW", "NOUGAT", "NOUGAT", "OREO", "OREO", "PIE", "", "")
|
||||
val index = apiNumber - 1
|
||||
apiName = if (index < mapper.size) mapper[index] else "UNKNOWN_VERSION"
|
||||
}
|
||||
if (version.isEmpty()) {
|
||||
val versions = arrayOf("1.0", "1.1", "1.5", "1.6", "2.0", "2.0.1", "2.1", "2.2.X", "2.3", "2.3.3", "3.0", "3.1", "3.2.0", "4.0.1", "4.0.3", "4.1.0", "4.2.0", "4.3.0", "4.4", "4.4", "5.0", "5.1", "6.0", "7.0", "7.1", "8.0.0", "8.1.0")
|
||||
val versions = arrayOf("1.0", "1.1", "1.5", "1.6", "2.0", "2.0.1", "2.1", "2.2.X", "2.3", "2.3.3", "3.0", "3.1", "3.2.0", "4.0.1", "4.0.3", "4.1.0", "4.2.0", "4.3.0", "4.4", "4.4", "5.0", "5.1", "6.0", "7.0", "7.1", "8.0.0", "8.1.0", "9", "10", "11")
|
||||
val index = apiNumber - 1
|
||||
version = if (index < versions.size) versions[index] else "UNKNOWN_VERSION"
|
||||
}
|
||||
|
||||
@@ -307,21 +307,26 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
|
||||
private const val BIOMETRIC_BLOCKS_MODES = KeyProperties.BLOCK_MODE_CBC
|
||||
private const val BIOMETRIC_ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
fun canAuthenticate(context: Context): Int {
|
||||
return try {
|
||||
BiometricManager.from(context).canAuthenticate(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
BiometricManager.from(context).canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
|
||||
BIOMETRIC_STRONG or DEVICE_CREDENTIAL
|
||||
} else {
|
||||
BiometricManager.from(context).canAuthenticate(BIOMETRIC_STRONG)
|
||||
BIOMETRIC_STRONG
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to authenticate with strong biometric.", e)
|
||||
try {
|
||||
BiometricManager.from(context).canAuthenticate(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
BiometricManager.from(context).canAuthenticate(BIOMETRIC_WEAK or DEVICE_CREDENTIAL)
|
||||
BIOMETRIC_WEAK or DEVICE_CREDENTIAL
|
||||
} else {
|
||||
BiometricManager.from(context).canAuthenticate(BIOMETRIC_WEAK)
|
||||
BIOMETRIC_WEAK
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to authenticate with weak biometric.", e)
|
||||
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
|
||||
@@ -329,6 +334,7 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
fun allowInitKeyStore(context: Context): Boolean {
|
||||
val biometricCanAuthenticate = canAuthenticate(context)
|
||||
return ( biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|
||||
@@ -336,8 +342,30 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
|
||||
)
|
||||
}
|
||||
|
||||
fun unlockSupported(context: Context): Boolean {
|
||||
val biometricCanAuthenticate = canAuthenticate(context)
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
fun biometricUnlockSupported(context: Context): Boolean {
|
||||
val biometricCanAuthenticate = try {
|
||||
BiometricManager.from(context).canAuthenticate(BIOMETRIC_STRONG)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to authenticate with strong biometric.", e)
|
||||
try {
|
||||
BiometricManager.from(context).canAuthenticate(BIOMETRIC_WEAK)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to authenticate with weak biometric.", e)
|
||||
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
|
||||
}
|
||||
}
|
||||
return (biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|
||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_STATUS_UNKNOWN
|
||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|
||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED
|
||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED
|
||||
)
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.R)
|
||||
fun deviceCredentialUnlockSupported(context: Context): Boolean {
|
||||
val biometricCanAuthenticate = BiometricManager.from(context).canAuthenticate(DEVICE_CREDENTIAL)
|
||||
return (biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS
|
||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_STATUS_UNKNOWN
|
||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|
||||
@@ -349,6 +377,7 @@ class BiometricUnlockDatabaseHelper(private val context: FragmentActivity) {
|
||||
/**
|
||||
* Remove entry key in keystore
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
fun deleteEntryKeyInKeystoreForBiometric(context: FragmentActivity,
|
||||
biometricCallback: BiometricUnlockErrorCallback) {
|
||||
BiometricUnlockDatabaseHelper(context).apply {
|
||||
|
||||
@@ -30,7 +30,6 @@ import android.view.autofill.AutofillManager
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.SwitchPreference
|
||||
@@ -209,14 +208,15 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
|
||||
activity?.let { activity ->
|
||||
val biometricUnlockEnablePreference: SwitchPreference? = findPreference(getString(R.string.biometric_unlock_enable_key))
|
||||
val deleteKeysFingerprints: Preference? = findPreference(getString(R.string.biometric_delete_all_key_key))
|
||||
// < M solve verifyError exception
|
||||
val deviceCredentialUnlockEnablePreference: SwitchPreference? = findPreference(getString(R.string.device_credential_unlock_enable_key))
|
||||
val autoOpenPromptPreference: SwitchPreference? = findPreference(getString(R.string.biometric_auto_open_prompt_key))
|
||||
|
||||
val biometricUnlockSupported = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
BiometricUnlockDatabaseHelper.unlockSupported(activity)
|
||||
BiometricUnlockDatabaseHelper.biometricUnlockSupported(activity)
|
||||
} else false
|
||||
if (!biometricUnlockSupported) {
|
||||
// False if under Marshmallow
|
||||
biometricUnlockEnablePreference?.apply {
|
||||
// False if under Marshmallow
|
||||
if (!biometricUnlockSupported) {
|
||||
isChecked = false
|
||||
setOnPreferenceClickListener { preference ->
|
||||
(preference as SwitchPreference).isChecked = false
|
||||
@@ -224,9 +224,48 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
.show(parentFragmentManager, "unavailableFeatureDialog")
|
||||
false
|
||||
}
|
||||
}
|
||||
deleteKeysFingerprints?.isEnabled = false
|
||||
} else {
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val checked = (newValue as Boolean)
|
||||
autoOpenPromptPreference?.isEnabled = checked
|
||||
|| deviceCredentialUnlockEnablePreference?.isChecked == true
|
||||
if (checked)
|
||||
deviceCredentialUnlockEnablePreference?.isChecked = false
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val deviceCredentialUnlockSupported = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
BiometricUnlockDatabaseHelper.deviceCredentialUnlockSupported(activity)
|
||||
} else false
|
||||
deviceCredentialUnlockEnablePreference?.apply {
|
||||
if (!deviceCredentialUnlockSupported) {
|
||||
isChecked = false
|
||||
setOnPreferenceClickListener { preference ->
|
||||
(preference as SwitchPreference).isChecked = false
|
||||
UnavailableFeatureDialogFragment.getInstance(Build.VERSION_CODES.R)
|
||||
.show(parentFragmentManager, "unavailableFeatureDialog")
|
||||
false
|
||||
}
|
||||
} else {
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val checked = (newValue as Boolean)
|
||||
autoOpenPromptPreference?.isEnabled = checked ||
|
||||
biometricUnlockEnablePreference?.isChecked == true
|
||||
if (checked)
|
||||
biometricUnlockEnablePreference?.isChecked = false
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
autoOpenPromptPreference?.isEnabled = biometricUnlockEnablePreference?.isChecked == true
|
||||
|| deviceCredentialUnlockEnablePreference?.isChecked == true
|
||||
|
||||
val deleteKeysFingerprints: Preference? = findPreference(getString(R.string.biometric_delete_all_key_key))
|
||||
if (biometricUnlockSupported || deviceCredentialUnlockSupported) {
|
||||
deleteKeysFingerprints?.setOnPreferenceClickListener {
|
||||
context?.let { context ->
|
||||
AlertDialog.Builder(context)
|
||||
@@ -260,6 +299,8 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
|
||||
}
|
||||
false
|
||||
}
|
||||
} else {
|
||||
deleteKeysFingerprints?.isEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -324,8 +324,8 @@
|
||||
<string name="biometric_unlock_enable_summary">Lets you scan your biometric to open the database</string>
|
||||
<string name="device_credential_unlock_enable_title">Device credential unlocking</string>
|
||||
<string name="device_credential_unlock_enable_summary">Lets you use your device credential to open the database</string>
|
||||
<string name="biometric_auto_open_prompt_title">Auto-open biometric prompt</string>
|
||||
<string name="biometric_auto_open_prompt_summary">Automatically ask for biometric if the database is set up to use it</string>
|
||||
<string name="biometric_auto_open_prompt_title">Auto-open prompt</string>
|
||||
<string name="biometric_auto_open_prompt_summary">Automatically request advanced unlock if the database is set up to use it</string>
|
||||
<string name="biometric_delete_all_key_title">Delete encryption keys</string>
|
||||
<string name="biometric_delete_all_key_summary">Delete all encryption keys related to advanced unlock recognition</string>
|
||||
<string name="biometric_delete_all_key_warning">Delete all encryption keys related to advanced unlock recognition?</string>
|
||||
|
||||
@@ -18,34 +18,27 @@
|
||||
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory
|
||||
android:title="@string/general">
|
||||
<Preference
|
||||
android:key="@string/advanced_unlock_explanation_key"
|
||||
android:icon="@drawable/prefs_info_24dp"
|
||||
android:summary="@string/advanced_unlock_explanation_summary"/>
|
||||
<PreferenceCategory
|
||||
android:title="@string/biometric">
|
||||
<SwitchPreference
|
||||
android:key="@string/biometric_unlock_enable_key"
|
||||
android:title="@string/biometric_unlock_enable_title"
|
||||
android:summary="@string/biometric_unlock_enable_summary"
|
||||
android:defaultValue="@bool/biometric_unlock_enable_default"/>
|
||||
<SwitchPreference
|
||||
android:key="@string/biometric_auto_open_prompt_key"
|
||||
android:title="@string/biometric_auto_open_prompt_title"
|
||||
android:summary="@string/biometric_auto_open_prompt_summary"
|
||||
android:dependency="@string/biometric_unlock_enable_key"
|
||||
android:defaultValue="@bool/biometric_auto_open_prompt_default"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/device_credential">
|
||||
<SwitchPreference
|
||||
android:key="@string/device_credential_unlock_enable_key"
|
||||
android:title="@string/device_credential_unlock_enable_title"
|
||||
android:summary="@string/device_credential_unlock_enable_summary"
|
||||
android:defaultValue="@bool/device_credential_unlock_enable_default"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/general">
|
||||
<SwitchPreference
|
||||
android:key="@string/biometric_auto_open_prompt_key"
|
||||
android:title="@string/biometric_auto_open_prompt_title"
|
||||
android:summary="@string/biometric_auto_open_prompt_summary"
|
||||
android:defaultValue="@bool/biometric_auto_open_prompt_default"/>
|
||||
<Preference
|
||||
android:key="@string/biometric_delete_all_key_key"
|
||||
android:title="@string/biometric_delete_all_key_title"
|
||||
|
||||
Reference in New Issue
Block a user