From 8d47b09e806594347f1d47f2dd23cedea16739b7 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Tue, 21 Jun 2022 12:51:24 +0300 Subject: [PATCH] Add biometric authentication --- app/build.gradle | 1 + .../main/ui/protect/ProtectActivity.kt | 38 +++++++++++++++++-- .../main/ui/protect/ProtectViewModel.kt | 8 +++- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a79a1f1a2..bf66187c7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -92,6 +92,7 @@ dependencies { implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01' implementation 'androidx.preference:preference-ktx:1.2.0' implementation 'androidx.work:work-runtime-ktx:2.7.1' + implementation 'androidx.biometric:biometric-ktx:1.2.0-alpha04' implementation 'com.google.android.material:material:1.7.0-alpha02' //noinspection LifecycleAnnotationProcessorWithJava8 kapt 'androidx.lifecycle:lifecycle-compiler:2.5.0-rc01' diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt index bf3c865eb..953991baa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt @@ -10,6 +10,11 @@ import android.view.View import android.view.WindowManager import android.view.inputmethod.EditorInfo import android.widget.TextView +import androidx.biometric.BiometricManager +import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK +import androidx.biometric.BiometricManager.BIOMETRIC_SUCCESS +import androidx.biometric.BiometricPrompt +import androidx.biometric.BiometricPrompt.AuthenticationCallback import androidx.core.graphics.Insets import org.koin.androidx.viewmodel.ext.android.viewModel import org.koitharu.kotatsu.R @@ -17,8 +22,11 @@ import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.databinding.ActivityProtectBinding import org.koitharu.kotatsu.utils.ext.getDisplayMessage -class ProtectActivity : BaseActivity(), TextView.OnEditorActionListener, - TextWatcher, View.OnClickListener { +class ProtectActivity : + BaseActivity(), + TextView.OnEditorActionListener, + TextWatcher, + View.OnClickListener { private val viewModel by viewModel() @@ -39,7 +47,9 @@ class ProtectActivity : BaseActivity(), TextView.OnEdito finishAfterTransition() } - binding.editPassword.requestFocus() + if (!useFingerprint()) { + binding.editPassword.requestFocus() + } } override fun onWindowInsetsChanged(insets: Insets) { @@ -85,6 +95,28 @@ class ProtectActivity : BaseActivity(), TextView.OnEdito binding.layoutPassword.isEnabled = !isLoading } + private fun useFingerprint(): Boolean { + if (BiometricManager.from(this).canAuthenticate(BIOMETRIC_WEAK) != BIOMETRIC_SUCCESS) { + return false + } + val prompt = BiometricPrompt(this, BiometricCallback()) + val promptInfo = BiometricPrompt.PromptInfo.Builder() + .setAllowedAuthenticators(BIOMETRIC_WEAK) + .setTitle(getString(R.string.app_name)) + .setConfirmationRequired(false) + .setNegativeButtonText(getString(android.R.string.cancel)) + .build() + prompt.authenticate(promptInfo) + return true + } + + private inner class BiometricCallback : AuthenticationCallback() { + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + super.onAuthenticationSucceeded(result) + viewModel.unlock() + } + } + companion object { private const val EXTRA_INTENT = "src_intent" diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt index 07646482b..69e671c01 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt @@ -27,12 +27,16 @@ class ProtectViewModel( val passwordHash = password.md5() val appPasswordHash = settings.appPassword if (passwordHash == appPasswordHash) { - protectHelper.unlock() - onUnlockSuccess.call(Unit) + unlock() } else { delay(PASSWORD_COMPARE_DELAY) throw WrongPasswordException() } } } + + fun unlock() { + protectHelper.unlock() + onUnlockSuccess.call(Unit) + } } \ No newline at end of file