mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Add fragment
This commit is contained in:
@@ -434,8 +434,8 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
|
|||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> UriUtil.gotoUrl(this, R.string.file_manager_explanation_url)
|
android.R.id.home -> UriUtil.gotoUrl(this, R.string.file_manager_explanation_url)
|
||||||
}
|
}
|
||||||
|
MenuUtil.onDefaultMenuOptionsItemSelected(this, item)
|
||||||
return MenuUtil.onDefaultMenuOptionsItemSelected(this, item) && super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ import android.widget.*
|
|||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.biometric.BiometricManager
|
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.fragment.app.commit
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog
|
import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog
|
||||||
@@ -50,8 +50,8 @@ import com.kunzisoft.keepass.activities.lock.LockingActivity
|
|||||||
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
import com.kunzisoft.keepass.activities.selection.SpecialModeActivity
|
||||||
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
|
||||||
import com.kunzisoft.keepass.autofill.AutofillHelper
|
import com.kunzisoft.keepass.autofill.AutofillHelper
|
||||||
|
import com.kunzisoft.keepass.biometric.AdvancedUnlockFragment
|
||||||
import com.kunzisoft.keepass.biometric.AdvancedUnlockManager
|
import com.kunzisoft.keepass.biometric.AdvancedUnlockManager
|
||||||
import com.kunzisoft.keepass.biometric.AdvancedUnlockHelper
|
|
||||||
import com.kunzisoft.keepass.database.action.ProgressDatabaseTaskProvider
|
import com.kunzisoft.keepass.database.action.ProgressDatabaseTaskProvider
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
import com.kunzisoft.keepass.database.element.Database
|
||||||
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
|
||||||
@@ -69,14 +69,13 @@ import com.kunzisoft.keepass.settings.PreferencesUtil
|
|||||||
import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION
|
import com.kunzisoft.keepass.utils.BACK_PREVIOUS_KEYBOARD_ACTION
|
||||||
import com.kunzisoft.keepass.utils.MenuUtil
|
import com.kunzisoft.keepass.utils.MenuUtil
|
||||||
import com.kunzisoft.keepass.utils.UriUtil
|
import com.kunzisoft.keepass.utils.UriUtil
|
||||||
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
|
|
||||||
import com.kunzisoft.keepass.view.KeyFileSelectionView
|
import com.kunzisoft.keepass.view.KeyFileSelectionView
|
||||||
import com.kunzisoft.keepass.view.asError
|
import com.kunzisoft.keepass.view.asError
|
||||||
import com.kunzisoft.keepass.viewmodels.DatabaseFileViewModel
|
import com.kunzisoft.keepass.viewmodels.DatabaseFileViewModel
|
||||||
import kotlinx.android.synthetic.main.activity_password.*
|
import kotlinx.android.synthetic.main.activity_password.*
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
|
|
||||||
open class PasswordActivity : SpecialModeActivity() {
|
open class PasswordActivity : SpecialModeActivity(), AdvancedUnlockManager.BuilderListener {
|
||||||
|
|
||||||
// Views
|
// Views
|
||||||
private var toolbar: Toolbar? = null
|
private var toolbar: Toolbar? = null
|
||||||
@@ -86,7 +85,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
private var confirmButtonView: Button? = null
|
private var confirmButtonView: Button? = null
|
||||||
private var checkboxPasswordView: CompoundButton? = null
|
private var checkboxPasswordView: CompoundButton? = null
|
||||||
private var checkboxKeyFileView: CompoundButton? = null
|
private var checkboxKeyFileView: CompoundButton? = null
|
||||||
private var advancedUnlockInfoView: AdvancedUnlockInfoView? = null
|
private var advancedUnlockFragment: AdvancedUnlockFragment? = null
|
||||||
private var infoContainerView: ViewGroup? = null
|
private var infoContainerView: ViewGroup? = null
|
||||||
|
|
||||||
private val databaseFileViewModel: DatabaseFileViewModel by viewModels()
|
private val databaseFileViewModel: DatabaseFileViewModel by viewModels()
|
||||||
@@ -113,7 +112,6 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
|
|
||||||
private var mProgressDatabaseTaskProvider: ProgressDatabaseTaskProvider? = null
|
private var mProgressDatabaseTaskProvider: ProgressDatabaseTaskProvider? = null
|
||||||
|
|
||||||
private var advancedUnlockManager: AdvancedUnlockManager? = null
|
|
||||||
private var mAllowAutoOpenBiometricPrompt: Boolean = true
|
private var mAllowAutoOpenBiometricPrompt: Boolean = true
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -133,7 +131,6 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
keyFileSelectionView = findViewById(R.id.keyfile_selection)
|
keyFileSelectionView = findViewById(R.id.keyfile_selection)
|
||||||
checkboxPasswordView = findViewById(R.id.password_checkbox)
|
checkboxPasswordView = findViewById(R.id.password_checkbox)
|
||||||
checkboxKeyFileView = findViewById(R.id.keyfile_checkox)
|
checkboxKeyFileView = findViewById(R.id.keyfile_checkox)
|
||||||
advancedUnlockInfoView = findViewById(R.id.biometric_info)
|
|
||||||
infoContainerView = findViewById(R.id.activity_password_info_container)
|
infoContainerView = findViewById(R.id.activity_password_info_container)
|
||||||
|
|
||||||
mPermissionAsked = savedInstanceState?.getBoolean(KEY_PERMISSION_ASKED) ?: mPermissionAsked
|
mPermissionAsked = savedInstanceState?.getBoolean(KEY_PERMISSION_ASKED) ?: mPermissionAsked
|
||||||
@@ -170,47 +167,20 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init Biometric elements
|
// Init Biometric elements
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
advancedUnlockFragment = supportFragmentManager
|
||||||
if (PreferencesUtil.isAdvancedUnlockEnable(this)) {
|
.findFragmentByTag(UNLOCK_FRAGMENT_TAG) as? AdvancedUnlockFragment?
|
||||||
advancedUnlockManager = AdvancedUnlockManager(this, advancedUnlockInfoView!!,
|
if (advancedUnlockFragment == null) {
|
||||||
object: AdvancedUnlockManager.BuilderListener {
|
advancedUnlockFragment = AdvancedUnlockFragment()
|
||||||
|
supportFragmentManager.commit {
|
||||||
override fun retrieveCredentialForEncryption(): String {
|
replace(R.id.fragment_advanced_unlock_container_view,
|
||||||
return passwordView?.text?.toString() ?: ""
|
advancedUnlockFragment!!,
|
||||||
}
|
UNLOCK_FRAGMENT_TAG)
|
||||||
|
|
||||||
override fun conditionToStoreCredential(): Boolean {
|
|
||||||
return checkboxPasswordView?.isChecked == true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCredentialEncrypted(databaseUri: Uri,
|
|
||||||
encryptedCredential: String,
|
|
||||||
ivSpec: String) {
|
|
||||||
// Load the database if password is registered with biometric
|
|
||||||
verifyCheckboxesAndLoadDatabase(
|
|
||||||
CipherDatabaseEntity(
|
|
||||||
databaseUri.toString(),
|
|
||||||
encryptedCredential,
|
|
||||||
ivSpec)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCredentialDecrypted(databaseUri: Uri,
|
|
||||||
decryptedCredential: String) {
|
|
||||||
// Load the database if password is retrieve from biometric
|
|
||||||
// Retrieve from biometric
|
|
||||||
verifyKeyFileCheckboxAndLoadDatabase(decryptedCredential)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen password checkbox to init advanced unlock and confirmation button
|
// Listen password checkbox to init advanced unlock and confirmation button
|
||||||
checkboxPasswordView?.setOnCheckedChangeListener { _, _ ->
|
checkboxPasswordView?.setOnCheckedChangeListener { _, _ ->
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
advancedUnlockFragment?.checkUnlockAvailability()
|
||||||
advancedUnlockManager?.checkUnlockAvailability()
|
|
||||||
}
|
|
||||||
enableOrNotTheConfirmationButton()
|
enableOrNotTheConfirmationButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,12 +217,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
when (actionTask) {
|
when (actionTask) {
|
||||||
ACTION_DATABASE_LOAD_TASK -> {
|
ACTION_DATABASE_LOAD_TASK -> {
|
||||||
// Recheck advanced unlock if error
|
// Recheck advanced unlock if error
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
advancedUnlockFragment?.initAdvancedUnlockMode()
|
||||||
if (PreferencesUtil.isAdvancedUnlockEnable(this@PasswordActivity)) {
|
|
||||||
// Stay with the same mode and init it
|
|
||||||
advancedUnlockManager?.initAdvancedUnlockMode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
mDatabaseKeyFileUri = null
|
mDatabaseKeyFileUri = null
|
||||||
@@ -360,6 +325,33 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun retrieveCredentialForEncryption(): String {
|
||||||
|
return passwordView?.text?.toString() ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun conditionToStoreCredential(): Boolean {
|
||||||
|
return checkboxPasswordView?.isChecked == true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCredentialEncrypted(databaseUri: Uri,
|
||||||
|
encryptedCredential: String,
|
||||||
|
ivSpec: String) {
|
||||||
|
// Load the database if password is registered with biometric
|
||||||
|
verifyCheckboxesAndLoadDatabase(
|
||||||
|
CipherDatabaseEntity(
|
||||||
|
databaseUri.toString(),
|
||||||
|
encryptedCredential,
|
||||||
|
ivSpec)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCredentialDecrypted(databaseUri: Uri,
|
||||||
|
decryptedCredential: String) {
|
||||||
|
// Load the database if password is retrieve from biometric
|
||||||
|
// Retrieve from biometric
|
||||||
|
verifyKeyFileCheckboxAndLoadDatabase(decryptedCredential)
|
||||||
|
}
|
||||||
|
|
||||||
private val onEditorActionListener = object : TextView.OnEditorActionListener {
|
private val onEditorActionListener = object : TextView.OnEditorActionListener {
|
||||||
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
|
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
|
||||||
if (actionId == IME_ACTION_DONE) {
|
if (actionId == IME_ACTION_DONE) {
|
||||||
@@ -426,18 +418,9 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
verifyCheckboxesAndLoadDatabase(password, keyFileUri)
|
verifyCheckboxesAndLoadDatabase(password, keyFileUri)
|
||||||
} else {
|
} else {
|
||||||
// Init Biometric elements
|
// Init Biometric elements
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
advancedUnlockFragment?.loadDatabase(databaseFileUri,
|
||||||
databaseFileUri?.let { databaseUri ->
|
|
||||||
if (PreferencesUtil.isAdvancedUnlockEnable(this)) {
|
|
||||||
advancedUnlockManager?.connect(databaseUri)
|
|
||||||
advancedUnlockManager?.isBiometricPromptAutoOpenEnable =
|
|
||||||
mAllowAutoOpenBiometricPrompt
|
mAllowAutoOpenBiometricPrompt
|
||||||
&& mProgressDatabaseTaskProvider?.isBinded() != true
|
&& mProgressDatabaseTaskProvider?.isBinded() != true)
|
||||||
} else {
|
|
||||||
advancedUnlockManager?.disconnect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enableOrNotTheConfirmationButton()
|
enableOrNotTheConfirmationButton()
|
||||||
@@ -489,10 +472,6 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
mProgressDatabaseTaskProvider?.unregisterProgressTask()
|
mProgressDatabaseTaskProvider?.unregisterProgressTask()
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
advancedUnlockManager?.disconnect()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reinit locking activity UI variable
|
// Reinit locking activity UI variable
|
||||||
LockingActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = null
|
LockingActivity.LOCKING_ACTIVITY_UI_VISIBLE_DURING_LOCK = null
|
||||||
mAllowAutoOpenBiometricPrompt = true
|
mAllowAutoOpenBiometricPrompt = true
|
||||||
@@ -500,12 +479,6 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
advancedUnlockManager = null
|
|
||||||
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
outState.putBoolean(KEY_PERMISSION_ASKED, mPermissionAsked)
|
outState.putBoolean(KEY_PERMISSION_ASKED, mPermissionAsked)
|
||||||
mDatabaseKeyFileUri?.let {
|
mDatabaseKeyFileUri?.let {
|
||||||
@@ -607,11 +580,6 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
MenuUtil.defaultMenuInflater(inflater, menu)
|
MenuUtil.defaultMenuInflater(inflater, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
// biometric menu
|
|
||||||
advancedUnlockManager?.inflateOptionsMenu(inflater, menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onCreateOptionsMenu(menu)
|
super.onCreateOptionsMenu(menu)
|
||||||
|
|
||||||
launchEducation(menu)
|
launchEducation(menu)
|
||||||
@@ -687,14 +655,16 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
performedNextEducation(passwordActivityEducation, menu)
|
performedNextEducation(passwordActivityEducation, menu)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// TODO Education
|
||||||
|
/*
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||||
&& !readOnlyEducationPerformed) {
|
&& !readOnlyEducationPerformed) {
|
||||||
val biometricCanAuthenticate = AdvancedUnlockHelper.canAuthenticate(this)
|
val biometricCanAuthenticate = AdvancedUnlockHelper.canAuthenticate(this)
|
||||||
PreferencesUtil.isAdvancedUnlockEnable(applicationContext)
|
PreferencesUtil.isAdvancedUnlockEnable(applicationContext)
|
||||||
&& (biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED || biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS)
|
&& (biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED || biometricCanAuthenticate == BiometricManager.BIOMETRIC_SUCCESS)
|
||||||
&& advancedUnlockInfoView != null && advancedUnlockInfoView?.visibility == View.VISIBLE
|
&& advancedUnlockFragment != null && advancedUnlockFragment?.visibility == View.VISIBLE
|
||||||
&& advancedUnlockInfoView?.unlockIconImageView != null
|
&& advancedUnlockFragment?.unlockIconImageView != null
|
||||||
&& passwordActivityEducation.checkAndPerformedBiometricEducation(advancedUnlockInfoView?.unlockIconImageView!!,
|
&& passwordActivityEducation.checkAndPerformedBiometricEducation(advancedUnlockFragment?.unlockIconImageView!!,
|
||||||
{
|
{
|
||||||
performedNextEducation(passwordActivityEducation, menu)
|
performedNextEducation(passwordActivityEducation, menu)
|
||||||
},
|
},
|
||||||
@@ -702,6 +672,8 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
performedNextEducation(passwordActivityEducation, menu)
|
performedNextEducation(passwordActivityEducation, menu)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,10 +695,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
readOnly = !readOnly
|
readOnly = !readOnly
|
||||||
changeOpenFileReadIcon(item)
|
changeOpenFileReadIcon(item)
|
||||||
}
|
}
|
||||||
R.id.menu_keystore_remove_key -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
else -> MenuUtil.onDefaultMenuOptionsItemSelected(this, item)
|
||||||
advancedUnlockManager?.deleteEncryptedDatabaseKey()
|
|
||||||
}
|
|
||||||
else -> return MenuUtil.onDefaultMenuOptionsItemSelected(this, item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
@@ -741,9 +710,7 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
mAllowAutoOpenBiometricPrompt = false
|
mAllowAutoOpenBiometricPrompt = false
|
||||||
|
|
||||||
// To get device credential unlock result
|
// To get device credential unlock result
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
advancedUnlockFragment?.onActivityResult(requestCode, resultCode, data)
|
||||||
advancedUnlockManager?.onActivityResult(requestCode, resultCode, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// To get entry in result
|
// To get entry in result
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
@@ -778,6 +745,8 @@ open class PasswordActivity : SpecialModeActivity() {
|
|||||||
|
|
||||||
private val TAG = PasswordActivity::class.java.name
|
private val TAG = PasswordActivity::class.java.name
|
||||||
|
|
||||||
|
private const val UNLOCK_FRAGMENT_TAG = "UNLOCK_FRAGMENT_TAG"
|
||||||
|
|
||||||
private const val KEY_FILENAME = "fileName"
|
private const val KEY_FILENAME = "fileName"
|
||||||
private const val KEY_KEYFILE = "keyFile"
|
private const val KEY_KEYFILE = "keyFile"
|
||||||
private const val VIEW_INTENT = "android.intent.action.VIEW"
|
private const val VIEW_INTENT = "android.intent.action.VIEW"
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package com.kunzisoft.keepass.biometric
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.*
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.activities.stylish.StylishFragment
|
||||||
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
|
|
||||||
|
class AdvancedUnlockFragment: StylishFragment() {
|
||||||
|
|
||||||
|
private var advancedUnlockManager: AdvancedUnlockManager? = null
|
||||||
|
|
||||||
|
private var advancedUnlockEnabled = false
|
||||||
|
|
||||||
|
override fun onAttach(context: Context) {
|
||||||
|
super.onAttach(context)
|
||||||
|
|
||||||
|
advancedUnlockEnabled = PreferencesUtil.isAdvancedUnlockEnable(context)
|
||||||
|
try {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
if (advancedUnlockEnabled) {
|
||||||
|
advancedUnlockManager?.builderListener = context as AdvancedUnlockManager.BuilderListener
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: ClassCastException) {
|
||||||
|
throw ClassCastException(context.toString()
|
||||||
|
+ " must implement " + AdvancedUnlockManager.BuilderListener::class.java.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
if (advancedUnlockEnabled) {
|
||||||
|
if (advancedUnlockManager == null) {
|
||||||
|
advancedUnlockManager = AdvancedUnlockManager { context as FragmentActivity }
|
||||||
|
} else {
|
||||||
|
advancedUnlockManager?.retrieveContext = { context as FragmentActivity }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retainInstance = true
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState)
|
||||||
|
|
||||||
|
val rootView = inflater.cloneInContext(contextThemed)
|
||||||
|
.inflate(R.layout.fragment_advanced_unlock, container, false)
|
||||||
|
|
||||||
|
advancedUnlockManager?.advancedUnlockInfoView = rootView.findViewById(R.id.advanced_unlock_view)
|
||||||
|
|
||||||
|
return rootView
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class ActivityResult(var requestCode: Int, var resultCode: Int, var data: Intent?)
|
||||||
|
private var activityResult: ActivityResult? = null
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
// To wait resume
|
||||||
|
activityResult = ActivityResult(requestCode, resultCode, data)
|
||||||
|
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
advancedUnlockEnabled = PreferencesUtil.isAdvancedUnlockEnable(requireContext())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
|
||||||
|
if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
// biometric menu
|
||||||
|
advancedUnlockManager?.inflateOptionsMenu(inflater, menu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.menu_keystore_remove_key -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
advancedUnlockManager?.deleteEncryptedDatabaseKey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadDatabase(databaseUri: Uri?, autoOpenPrompt: Boolean) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
// To get device credential unlock result, only if same database uri
|
||||||
|
activityResult?.let {
|
||||||
|
if (databaseUri != null && advancedUnlockManager?.databaseFileUri == databaseUri) {
|
||||||
|
advancedUnlockManager?.onActivityResult(it.requestCode, it.resultCode, it.data)
|
||||||
|
}
|
||||||
|
} ?: run {
|
||||||
|
if (databaseUri != null && advancedUnlockEnabled) {
|
||||||
|
advancedUnlockManager?.connect(databaseUri)
|
||||||
|
advancedUnlockManager?.autoOpenPrompt = autoOpenPrompt
|
||||||
|
} else {
|
||||||
|
advancedUnlockManager?.disconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activityResult = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check unlock availability and change the current mode depending of device's state
|
||||||
|
*/
|
||||||
|
fun checkUnlockAvailability() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
advancedUnlockManager?.checkUnlockAvailability()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun initAdvancedUnlockMode() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
if (advancedUnlockEnabled) {
|
||||||
|
advancedUnlockManager?.initAdvancedUnlockMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
advancedUnlockManager?.disconnect()
|
||||||
|
advancedUnlockManager?.builderListener = null
|
||||||
|
advancedUnlockManager = null
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetach() {
|
||||||
|
advancedUnlockManager?.builderListener = null
|
||||||
|
|
||||||
|
super.onDetach()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,7 +47,7 @@ import javax.crypto.SecretKey
|
|||||||
import javax.crypto.spec.IvParameterSpec
|
import javax.crypto.spec.IvParameterSpec
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
class AdvancedUnlockHelper(private val context: FragmentActivity) {
|
class AdvancedUnlockHelper(private var retrieveContext: () -> FragmentActivity) {
|
||||||
|
|
||||||
private var keyStore: KeyStore? = null
|
private var keyStore: KeyStore? = null
|
||||||
private var keyGenerator: KeyGenerator? = null
|
private var keyGenerator: KeyGenerator? = null
|
||||||
@@ -72,8 +72,8 @@ class AdvancedUnlockHelper(private val context: FragmentActivity) {
|
|||||||
|
|
||||||
private var isKeyManagerInit = false
|
private var isKeyManagerInit = false
|
||||||
|
|
||||||
private val deviceCredentialUnlockEnable = PreferencesUtil.isDeviceCredentialUnlockEnable(context)
|
private val deviceCredentialUnlockEnable = PreferencesUtil.isDeviceCredentialUnlockEnable(retrieveContext())
|
||||||
private val biometricUnlockEnable = PreferencesUtil.isBiometricUnlockEnable(context)
|
private val biometricUnlockEnable = PreferencesUtil.isBiometricUnlockEnable(retrieveContext())
|
||||||
|
|
||||||
val isKeyManagerInitialized: Boolean
|
val isKeyManagerInitialized: Boolean
|
||||||
get() {
|
get() {
|
||||||
@@ -99,7 +99,7 @@ class AdvancedUnlockHelper(private val context: FragmentActivity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (isDeviceSecure(context)
|
if (isDeviceSecure(retrieveContext())
|
||||||
&& (deviceCredentialUnlockEnable || biometricUnlockEnable)) {
|
&& (deviceCredentialUnlockEnable || biometricUnlockEnable)) {
|
||||||
try {
|
try {
|
||||||
this.keyStore = KeyStore.getInstance(ADVANCED_UNLOCK_KEYSTORE)
|
this.keyStore = KeyStore.getInstance(ADVANCED_UNLOCK_KEYSTORE)
|
||||||
@@ -144,11 +144,6 @@ class AdvancedUnlockHelper(private val context: FragmentActivity) {
|
|||||||
// Require the user to authenticate with a fingerprint to authorize every use
|
// Require the user to authenticate with a fingerprint to authorize every use
|
||||||
// of the key
|
// of the key
|
||||||
.setUserAuthenticationRequired(true)
|
.setUserAuthenticationRequired(true)
|
||||||
.apply {
|
|
||||||
if (isDeviceCredentialBiometricOperation()) {
|
|
||||||
setUserAuthenticationParameters(0, KeyProperties.AUTH_DEVICE_CREDENTIAL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.build())
|
.build())
|
||||||
keyGenerator?.generateKey()
|
keyGenerator?.generateKey()
|
||||||
}
|
}
|
||||||
@@ -287,20 +282,20 @@ class AdvancedUnlockHelper(private val context: FragmentActivity) {
|
|||||||
fun openAdvancedUnlockPrompt(cryptoPrompt: AdvancedUnlockCryptoPrompt) {
|
fun openAdvancedUnlockPrompt(cryptoPrompt: AdvancedUnlockCryptoPrompt) {
|
||||||
// Init advanced unlock prompt
|
// Init advanced unlock prompt
|
||||||
if (biometricPrompt == null) {
|
if (biometricPrompt == null) {
|
||||||
biometricPrompt = BiometricPrompt(context,
|
biometricPrompt = BiometricPrompt(retrieveContext(),
|
||||||
Executors.newSingleThreadExecutor(),
|
Executors.newSingleThreadExecutor(),
|
||||||
authenticationCallback)
|
authenticationCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
val promptTitle = context.getString(cryptoPrompt.promptTitleId)
|
val promptTitle = retrieveContext().getString(cryptoPrompt.promptTitleId)
|
||||||
val promptDescription = cryptoPrompt.promptDescriptionId?.let { descriptionId ->
|
val promptDescription = cryptoPrompt.promptDescriptionId?.let { descriptionId ->
|
||||||
context.getString(descriptionId)
|
retrieveContext().getString(descriptionId)
|
||||||
} ?: ""
|
} ?: ""
|
||||||
|
|
||||||
if (cryptoPrompt.isDeviceCredentialOperation) {
|
if (cryptoPrompt.isDeviceCredentialOperation) {
|
||||||
// TODO open intent keyguard for response
|
// TODO open intent keyguard for response
|
||||||
val keyGuardManager = ContextCompat.getSystemService(context, KeyguardManager::class.java)
|
val keyGuardManager = ContextCompat.getSystemService(retrieveContext(), KeyguardManager::class.java)
|
||||||
context.startActivityForResult(
|
retrieveContext().startActivityForResult(
|
||||||
keyGuardManager?.createConfirmDeviceCredentialIntent(promptTitle, promptDescription),
|
keyGuardManager?.createConfirmDeviceCredentialIntent(promptTitle, promptDescription),
|
||||||
REQUEST_DEVICE_CREDENTIAL)
|
REQUEST_DEVICE_CREDENTIAL)
|
||||||
}
|
}
|
||||||
@@ -313,7 +308,7 @@ class AdvancedUnlockHelper(private val context: FragmentActivity) {
|
|||||||
if (isDeviceCredentialBiometricOperation()) {
|
if (isDeviceCredentialBiometricOperation()) {
|
||||||
setAllowedAuthenticators(DEVICE_CREDENTIAL)
|
setAllowedAuthenticators(DEVICE_CREDENTIAL)
|
||||||
} else {
|
} else {
|
||||||
setNegativeButtonText(context.getString(android.R.string.cancel))
|
setNegativeButtonText(retrieveContext().getString(android.R.string.cancel))
|
||||||
}
|
}
|
||||||
}.build()
|
}.build()
|
||||||
|
|
||||||
@@ -449,9 +444,9 @@ class AdvancedUnlockHelper(private val context: FragmentActivity) {
|
|||||||
* Remove entry key in keystore
|
* Remove entry key in keystore
|
||||||
*/
|
*/
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
fun deleteEntryKeyInKeystoreForBiometric(context: FragmentActivity,
|
fun deleteEntryKeyInKeystoreForBiometric(fragmentActivity: FragmentActivity,
|
||||||
advancedCallback: AdvancedUnlockErrorCallback) {
|
advancedCallback: AdvancedUnlockErrorCallback) {
|
||||||
AdvancedUnlockHelper(context).apply {
|
AdvancedUnlockHelper{ fragmentActivity }.apply {
|
||||||
advancedUnlockCallback = object : AdvancedUnlockCallback {
|
advancedUnlockCallback = object : AdvancedUnlockCallback {
|
||||||
override fun onAuthenticationSucceeded() {}
|
override fun onAuthenticationSucceeded() {}
|
||||||
|
|
||||||
|
|||||||
@@ -39,15 +39,16 @@ import com.kunzisoft.keepass.settings.PreferencesUtil
|
|||||||
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
|
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
class AdvancedUnlockManager(var context: FragmentActivity,
|
class AdvancedUnlockManager(var retrieveContext: () -> FragmentActivity)
|
||||||
private var advancedUnlockInfoView: AdvancedUnlockInfoView,
|
|
||||||
private var builderListener: BuilderListener)
|
|
||||||
: AdvancedUnlockHelper.AdvancedUnlockCallback {
|
: AdvancedUnlockHelper.AdvancedUnlockCallback {
|
||||||
|
|
||||||
private var advancedUnlockHelper: AdvancedUnlockHelper? = null
|
private var advancedUnlockHelper: AdvancedUnlockHelper? = null
|
||||||
private var biometricMode: Mode = Mode.BIOMETRIC_UNAVAILABLE
|
private var biometricMode: Mode = Mode.BIOMETRIC_UNAVAILABLE
|
||||||
|
lateinit var advancedUnlockInfoView: AdvancedUnlockInfoView
|
||||||
|
var builderListener: BuilderListener ? = null
|
||||||
|
|
||||||
private var databaseFileUri: Uri? = null
|
var databaseFileUri: Uri? = null
|
||||||
|
private set
|
||||||
|
|
||||||
// Only to fix multiple fingerprint menu #332
|
// Only to fix multiple fingerprint menu #332
|
||||||
private var mAllowAdvancedUnlockMenu = false
|
private var mAllowAdvancedUnlockMenu = false
|
||||||
@@ -56,8 +57,8 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
/**
|
/**
|
||||||
* Manage setting to auto open biometric prompt
|
* Manage setting to auto open biometric prompt
|
||||||
*/
|
*/
|
||||||
private var biometricPromptAutoOpenPreference = PreferencesUtil.isAdvancedUnlockPromptAutoOpenEnable(context)
|
private var biometricPromptAutoOpenPreference = PreferencesUtil.isAdvancedUnlockPromptAutoOpenEnable(retrieveContext())
|
||||||
var isBiometricPromptAutoOpenEnable: Boolean = false
|
var autoOpenPrompt: Boolean = false
|
||||||
get() {
|
get() {
|
||||||
return field && biometricPromptAutoOpenPreference
|
return field && biometricPromptAutoOpenPreference
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,7 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
// checkBiometricAvailability() allows open biometric prompt and onDestroy() removes the authorization
|
// checkBiometricAvailability() allows open biometric prompt and onDestroy() removes the authorization
|
||||||
private var allowOpenBiometricPrompt = false
|
private var allowOpenBiometricPrompt = false
|
||||||
|
|
||||||
private var cipherDatabaseAction = CipherDatabaseAction.getInstance(context.applicationContext)
|
private var cipherDatabaseAction = CipherDatabaseAction.getInstance(retrieveContext().applicationContext)
|
||||||
|
|
||||||
private var cipherDatabaseListener: CipherDatabaseAction.DatabaseListener? = null
|
private var cipherDatabaseListener: CipherDatabaseAction.DatabaseListener? = null
|
||||||
|
|
||||||
@@ -76,18 +77,18 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
*/
|
*/
|
||||||
fun checkUnlockAvailability() {
|
fun checkUnlockAvailability() {
|
||||||
|
|
||||||
if (PreferencesUtil.isDeviceCredentialUnlockEnable(context)) {
|
if (PreferencesUtil.isDeviceCredentialUnlockEnable(retrieveContext())) {
|
||||||
advancedUnlockInfoView.setIconResource(R.drawable.bolt)
|
advancedUnlockInfoView.setIconResource(R.drawable.bolt)
|
||||||
} else if (PreferencesUtil.isBiometricUnlockEnable(context)) {
|
} else if (PreferencesUtil.isBiometricUnlockEnable(retrieveContext())) {
|
||||||
advancedUnlockInfoView.setIconResource(R.drawable.fingerprint)
|
advancedUnlockInfoView.setIconResource(R.drawable.fingerprint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// biometric not supported (by API level or hardware) so keep option hidden
|
// biometric not supported (by API level or hardware) so keep option hidden
|
||||||
// or manually disable
|
// or manually disable
|
||||||
val biometricCanAuthenticate = AdvancedUnlockHelper.canAuthenticate(context)
|
val biometricCanAuthenticate = AdvancedUnlockHelper.canAuthenticate(retrieveContext())
|
||||||
allowOpenBiometricPrompt = true
|
allowOpenBiometricPrompt = true
|
||||||
|
|
||||||
if (!PreferencesUtil.isAdvancedUnlockEnable(context)
|
if (!PreferencesUtil.isAdvancedUnlockEnable(retrieveContext())
|
||||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE
|
||||||
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) {
|
|| biometricCanAuthenticate == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) {
|
||||||
toggleMode(Mode.BIOMETRIC_UNAVAILABLE)
|
toggleMode(Mode.BIOMETRIC_UNAVAILABLE)
|
||||||
@@ -101,7 +102,7 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
// Check if fingerprint well init (be called the first time the fingerprint is configured
|
// Check if fingerprint well init (be called the first time the fingerprint is configured
|
||||||
// and the activity still active)
|
// and the activity still active)
|
||||||
if (advancedUnlockHelper?.isKeyManagerInitialized != true) {
|
if (advancedUnlockHelper?.isKeyManagerInitialized != true) {
|
||||||
advancedUnlockHelper = AdvancedUnlockHelper(context)
|
advancedUnlockHelper = AdvancedUnlockHelper(retrieveContext)
|
||||||
// callback for fingerprint findings
|
// callback for fingerprint findings
|
||||||
advancedUnlockHelper?.advancedUnlockCallback = this
|
advancedUnlockHelper?.advancedUnlockCallback = this
|
||||||
}
|
}
|
||||||
@@ -109,7 +110,7 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
if (advancedUnlockHelper?.isKeyManagerInitialized != true) {
|
if (advancedUnlockHelper?.isKeyManagerInitialized != true) {
|
||||||
toggleMode(Mode.KEY_MANAGER_UNAVAILABLE)
|
toggleMode(Mode.KEY_MANAGER_UNAVAILABLE)
|
||||||
} else {
|
} else {
|
||||||
if (builderListener.conditionToStoreCredential()) {
|
if (builderListener?.conditionToStoreCredential() == true) {
|
||||||
// listen for encryption
|
// listen for encryption
|
||||||
toggleMode(Mode.STORE_CREDENTIAL)
|
toggleMode(Mode.STORE_CREDENTIAL)
|
||||||
} else {
|
} else {
|
||||||
@@ -148,7 +149,7 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
private fun openBiometricSetting() {
|
private fun openBiometricSetting() {
|
||||||
advancedUnlockInfoView.setIconViewClickListener(false) {
|
advancedUnlockInfoView.setIconViewClickListener(false) {
|
||||||
// ACTION_SECURITY_SETTINGS does not contain fingerprint enrollment on some devices...
|
// ACTION_SECURITY_SETTINGS does not contain fingerprint enrollment on some devices...
|
||||||
context.startActivity(Intent(Settings.ACTION_SETTINGS))
|
retrieveContext().startActivity(Intent(Settings.ACTION_SETTINGS))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,12 +182,12 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
|
|
||||||
advancedUnlockInfoView.setIconViewClickListener(false) {
|
advancedUnlockInfoView.setIconViewClickListener(false) {
|
||||||
onAuthenticationError(BiometricPrompt.ERROR_UNABLE_TO_PROCESS,
|
onAuthenticationError(BiometricPrompt.ERROR_UNABLE_TO_PROCESS,
|
||||||
context.getString(R.string.credential_before_click_advanced_unlock_button))
|
retrieveContext().getString(R.string.credential_before_click_advanced_unlock_button))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openAdvancedUnlockPrompt(cryptoPrompt: AdvancedUnlockCryptoPrompt) {
|
private fun openAdvancedUnlockPrompt(cryptoPrompt: AdvancedUnlockCryptoPrompt) {
|
||||||
context.runOnUiThread {
|
retrieveContext().runOnUiThread {
|
||||||
if (allowOpenBiometricPrompt) {
|
if (allowOpenBiometricPrompt) {
|
||||||
try {
|
try {
|
||||||
advancedUnlockHelper
|
advancedUnlockHelper
|
||||||
@@ -229,8 +230,8 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Auto open the biometric prompt
|
// Auto open the biometric prompt
|
||||||
if (isBiometricPromptAutoOpenEnable) {
|
if (autoOpenPrompt) {
|
||||||
isBiometricPromptAutoOpenEnable = false
|
autoOpenPrompt = false
|
||||||
openAdvancedUnlockPrompt(cryptoPrompt)
|
openAdvancedUnlockPrompt(cryptoPrompt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,7 +267,7 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
&& (biometricMode != Mode.BIOMETRIC_UNAVAILABLE
|
&& (biometricMode != Mode.BIOMETRIC_UNAVAILABLE
|
||||||
&& biometricMode != Mode.KEY_MANAGER_UNAVAILABLE)
|
&& biometricMode != Mode.KEY_MANAGER_UNAVAILABLE)
|
||||||
mAddBiometricMenuInProgress = false
|
mAddBiometricMenuInProgress = false
|
||||||
context.invalidateOptionsMenu()
|
retrieveContext().invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,21 +323,21 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||||
context.runOnUiThread {
|
retrieveContext().runOnUiThread {
|
||||||
Log.e(TAG, "Biometric authentication error. Code : $errorCode Error : $errString")
|
Log.e(TAG, "Biometric authentication error. Code : $errorCode Error : $errString")
|
||||||
setAdvancedUnlockedMessageView(errString.toString())
|
setAdvancedUnlockedMessageView(errString.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAuthenticationFailed() {
|
override fun onAuthenticationFailed() {
|
||||||
context.runOnUiThread {
|
retrieveContext().runOnUiThread {
|
||||||
Log.e(TAG, "Biometric authentication failed, biometric not recognized")
|
Log.e(TAG, "Biometric authentication failed, biometric not recognized")
|
||||||
setAdvancedUnlockedMessageView(R.string.advanced_unlock_not_recognized)
|
setAdvancedUnlockedMessageView(R.string.advanced_unlock_not_recognized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAuthenticationSucceeded() {
|
override fun onAuthenticationSucceeded() {
|
||||||
context.runOnUiThread {
|
retrieveContext().runOnUiThread {
|
||||||
when (biometricMode) {
|
when (biometricMode) {
|
||||||
Mode.BIOMETRIC_UNAVAILABLE -> {
|
Mode.BIOMETRIC_UNAVAILABLE -> {
|
||||||
}
|
}
|
||||||
@@ -350,8 +351,10 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
}
|
}
|
||||||
Mode.STORE_CREDENTIAL -> {
|
Mode.STORE_CREDENTIAL -> {
|
||||||
// newly store the entered password in encrypted way
|
// newly store the entered password in encrypted way
|
||||||
advancedUnlockHelper?.encryptData(builderListener.retrieveCredentialForEncryption())
|
builderListener?.retrieveCredentialForEncryption()?.let { credential ->
|
||||||
AdvancedUnlockNotificationService.startServiceForTimeout(context)
|
advancedUnlockHelper?.encryptData(credential)
|
||||||
|
}
|
||||||
|
AdvancedUnlockNotificationService.startServiceForTimeout(retrieveContext())
|
||||||
}
|
}
|
||||||
Mode.EXTRACT_CREDENTIAL -> {
|
Mode.EXTRACT_CREDENTIAL -> {
|
||||||
// retrieve the encrypted value from preferences
|
// retrieve the encrypted value from preferences
|
||||||
@@ -369,14 +372,14 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
|
|
||||||
override fun handleEncryptedResult(encryptedValue: String, ivSpec: String) {
|
override fun handleEncryptedResult(encryptedValue: String, ivSpec: String) {
|
||||||
databaseFileUri?.let { databaseUri ->
|
databaseFileUri?.let { databaseUri ->
|
||||||
builderListener.onCredentialEncrypted(databaseUri, encryptedValue, ivSpec)
|
builderListener?.onCredentialEncrypted(databaseUri, encryptedValue, ivSpec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleDecryptedResult(decryptedValue: String) {
|
override fun handleDecryptedResult(decryptedValue: String) {
|
||||||
// Load database directly with password retrieve
|
// Load database directly with password retrieve
|
||||||
databaseFileUri?.let {
|
databaseFileUri?.let {
|
||||||
builderListener.onCredentialDecrypted(it, decryptedValue)
|
builderListener?.onCredentialDecrypted(it, decryptedValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,25 +393,25 @@ class AdvancedUnlockManager(var context: FragmentActivity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showFingerPrintViews(show: Boolean) {
|
private fun showFingerPrintViews(show: Boolean) {
|
||||||
context.runOnUiThread {
|
retrieveContext().runOnUiThread {
|
||||||
advancedUnlockInfoView.visibility = if (show) View.VISIBLE else View.GONE
|
advancedUnlockInfoView.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setAdvancedUnlockedTitleView(textId: Int) {
|
private fun setAdvancedUnlockedTitleView(textId: Int) {
|
||||||
context.runOnUiThread {
|
retrieveContext().runOnUiThread {
|
||||||
advancedUnlockInfoView.setTitle(textId)
|
advancedUnlockInfoView.setTitle(textId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setAdvancedUnlockedMessageView(textId: Int) {
|
private fun setAdvancedUnlockedMessageView(textId: Int) {
|
||||||
context.runOnUiThread {
|
retrieveContext().runOnUiThread {
|
||||||
advancedUnlockInfoView.setMessage(textId)
|
advancedUnlockInfoView.setMessage(textId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setAdvancedUnlockedMessageView(text: CharSequence) {
|
private fun setAdvancedUnlockedMessageView(text: CharSequence) {
|
||||||
context.runOnUiThread {
|
retrieveContext().runOnUiThread {
|
||||||
advancedUnlockInfoView.message = text
|
advancedUnlockInfoView.message = text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,23 +53,19 @@ object MenuUtil {
|
|||||||
fun onDefaultMenuOptionsItemSelected(activity: Activity,
|
fun onDefaultMenuOptionsItemSelected(activity: Activity,
|
||||||
item: MenuItem,
|
item: MenuItem,
|
||||||
readOnly: Boolean = READ_ONLY_DEFAULT,
|
readOnly: Boolean = READ_ONLY_DEFAULT,
|
||||||
timeoutEnable: Boolean = false): Boolean {
|
timeoutEnable: Boolean = false) {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.menu_contribute -> {
|
R.id.menu_contribute -> {
|
||||||
onContributionItemSelected(activity)
|
onContributionItemSelected(activity)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
R.id.menu_app_settings -> {
|
R.id.menu_app_settings -> {
|
||||||
// To avoid flickering when launch settings in a LockingActivity
|
// To avoid flickering when launch settings in a LockingActivity
|
||||||
SettingsActivity.launch(activity, readOnly, timeoutEnable)
|
SettingsActivity.launch(activity, readOnly, timeoutEnable)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
R.id.menu_about -> {
|
R.id.menu_about -> {
|
||||||
val intent = Intent(activity, AboutActivity::class.java)
|
val intent = Intent(activity, AboutActivity::class.java)
|
||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
else -> return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,17 +68,10 @@
|
|||||||
android:padding="0dp"
|
android:padding="0dp"
|
||||||
android:contentDescription="@string/about"
|
android:contentDescription="@string/about"
|
||||||
android:src="@drawable/ic_launcher_foreground"/>
|
android:src="@drawable/ic_launcher_foreground"/>
|
||||||
<FrameLayout
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/fragment_advanced_unlock_container_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent" />
|
||||||
<com.kunzisoft.keepass.view.AdvancedUnlockInfoView
|
|
||||||
android:id="@+id/biometric_info"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:background="?attr/colorPrimary"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
|||||||
13
app/src/main/res/layout/fragment_advanced_unlock.xml
Normal file
13
app/src/main/res/layout/fragment_advanced_unlock.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<com.kunzisoft.keepass.view.AdvancedUnlockInfoView
|
||||||
|
android:id="@+id/advanced_unlock_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</FrameLayout>
|
||||||
Reference in New Issue
Block a user