mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-19 08:01:08 +02:00
Merge pull request #208 from maxmoney21m/bugfix/204-fingerprint-crash-android9
Biometric support down to app's minimum SDK level 26, fixes #204
This commit is contained in:
@@ -1,8 +1,16 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.KeyguardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.compose.ManagedActivityResultLauncher
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.ActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.biometric.BiometricManager
|
import androidx.biometric.BiometricManager
|
||||||
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG
|
import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG
|
||||||
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||||
@@ -105,10 +113,17 @@ private fun NSecCopyButton(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val keyguardLauncher =
|
||||||
|
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
copyNSec(context, scope, account, clipboardManager)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier.padding(horizontal = 3.dp),
|
modifier = Modifier.padding(horizontal = 3.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
authenticatedCopyNSec(context, scope, account, clipboardManager)
|
authenticatedCopyNSec(context, scope, account, clipboardManager, keyguardLauncher)
|
||||||
},
|
},
|
||||||
shape = RoundedCornerShape(20.dp), colors = ButtonDefaults.buttonColors(
|
shape = RoundedCornerShape(20.dp), colors = ButtonDefaults.buttonColors(
|
||||||
backgroundColor = MaterialTheme.colors.primary
|
backgroundColor = MaterialTheme.colors.primary
|
||||||
@@ -141,10 +156,33 @@ private fun authenticatedCopyNSec(
|
|||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
account: Account,
|
account: Account,
|
||||||
clipboardManager: ClipboardManager,
|
clipboardManager: ClipboardManager,
|
||||||
|
keyguardLauncher: ManagedActivityResultLauncher<Intent, ActivityResult>
|
||||||
) {
|
) {
|
||||||
val fragmentContext = context.getFragmentActivity()!!
|
val fragmentContext = context.getFragmentActivity()!!
|
||||||
val authenticators = BIOMETRIC_STRONG or DEVICE_CREDENTIAL
|
val keyguardManager =
|
||||||
|
fragmentContext.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
||||||
|
|
||||||
|
if (!keyguardManager.isDeviceSecure) {
|
||||||
|
copyNSec(context, scope, account, clipboardManager)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fun keyguardPrompt() {
|
||||||
|
val intent = keyguardManager.createConfirmDeviceCredentialIntent(
|
||||||
|
context.getString(R.string.app_name_release),
|
||||||
|
context.getString(R.string.copy_my_secret_key),
|
||||||
|
)
|
||||||
|
|
||||||
|
keyguardLauncher.launch(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
|
||||||
|
keyguardPrompt()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val biometricManager = BiometricManager.from(context)
|
val biometricManager = BiometricManager.from(context)
|
||||||
|
val authenticators = BIOMETRIC_STRONG or DEVICE_CREDENTIAL
|
||||||
|
|
||||||
val promptInfo = BiometricPrompt.PromptInfo.Builder()
|
val promptInfo = BiometricPrompt.PromptInfo.Builder()
|
||||||
.setTitle(context.getString(R.string.app_name_release))
|
.setTitle(context.getString(R.string.app_name_release))
|
||||||
@@ -155,6 +193,23 @@ private fun authenticatedCopyNSec(
|
|||||||
val biometricPrompt = BiometricPrompt(
|
val biometricPrompt = BiometricPrompt(
|
||||||
fragmentContext,
|
fragmentContext,
|
||||||
object : BiometricPrompt.AuthenticationCallback() {
|
object : BiometricPrompt.AuthenticationCallback() {
|
||||||
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||||
|
super.onAuthenticationError(errorCode, errString)
|
||||||
|
|
||||||
|
when (errorCode) {
|
||||||
|
BiometricPrompt.ERROR_NEGATIVE_BUTTON -> keyguardPrompt()
|
||||||
|
BiometricPrompt.ERROR_LOCKOUT -> keyguardPrompt()
|
||||||
|
else ->
|
||||||
|
scope.launch {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
"${context.getString(R.string.biometric_error)}: $errString",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onAuthenticationFailed() {
|
override fun onAuthenticationFailed() {
|
||||||
super.onAuthenticationFailed()
|
super.onAuthenticationFailed()
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@@ -173,11 +228,9 @@ private fun authenticatedCopyNSec(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
val canAuth = biometricManager.canAuthenticate(authenticators)
|
when (biometricManager.canAuthenticate(authenticators)) {
|
||||||
if (canAuth == BiometricManager.BIOMETRIC_SUCCESS) {
|
BiometricManager.BIOMETRIC_SUCCESS -> biometricPrompt.authenticate(promptInfo)
|
||||||
biometricPrompt.authenticate(promptInfo)
|
else -> keyguardPrompt()
|
||||||
} else {
|
|
||||||
copyNSec(context, scope, account, clipboardManager)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -187,7 +187,7 @@
|
|||||||
<string name="secret_key_copied_to_clipboard">Secret key (nsec) copied to clipboard</string>
|
<string name="secret_key_copied_to_clipboard">Secret key (nsec) copied to clipboard</string>
|
||||||
<string name="copy_my_secret_key">Copy my secret key</string>
|
<string name="copy_my_secret_key">Copy my secret key</string>
|
||||||
<string name="biometric_authentication_failed">Authentication failed</string>
|
<string name="biometric_authentication_failed">Authentication failed</string>
|
||||||
|
<string name="biometric_error">Error</string>
|
||||||
<string name="badge_created_by">"Created by %1$s"</string>
|
<string name="badge_created_by">"Created by %1$s"</string>
|
||||||
<string name="badge_award_image_for">"Badge award image for %1$s"</string>
|
<string name="badge_award_image_for">"Badge award image for %1$s"</string>
|
||||||
<string name="new_badge_award_notif">You Received a new Badge Award</string>
|
<string name="new_badge_award_notif">You Received a new Badge Award</string>
|
||||||
|
Reference in New Issue
Block a user