mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
support using biometrics to auth
This commit is contained in:
@@ -10,6 +10,7 @@ import android.widget.Toast
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import androidx.biometric.BiometricPrompt.AuthenticationCallback
|
||||
import androidx.biometric.BiometricPrompt.PromptInfo
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -22,12 +23,15 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
class AuthFragment: Fragment() {
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
@SuppressLint("UnrememberedMutableState")
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
val sharedPref = context?.getSharedPreferences("data", Context.MODE_PRIVATE)!!
|
||||
@@ -40,6 +44,11 @@ class AuthFragment: Fragment() {
|
||||
fragmentTransaction.commit()
|
||||
}
|
||||
}
|
||||
val promptInfo = PromptInfo.Builder()
|
||||
.setTitle("Auth")
|
||||
.setSubtitle("Auth OwnDroid with password or biometric")
|
||||
.setConfirmationRequired(true)
|
||||
var fallback = false
|
||||
val callback = object: AuthenticationCallback() {
|
||||
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
||||
super.onAuthenticationSucceeded(result)
|
||||
@@ -48,16 +57,32 @@ class AuthFragment: Fragment() {
|
||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||
super.onAuthenticationError(errorCode, errString)
|
||||
if(errorCode == BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL) onAuthSucceed()
|
||||
if(errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) fallback = true
|
||||
if(errorCode == BiometricPrompt.ERROR_CANCELED) return
|
||||
Toast.makeText(context, errString, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
GlobalScope.launch(Dispatchers.Main) {
|
||||
while(true){
|
||||
if(fallback){
|
||||
val fallbackPromptInfo = PromptInfo.Builder()
|
||||
.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
|
||||
.setTitle("Auth")
|
||||
.setSubtitle("Auth OwnDroid with password")
|
||||
.setConfirmationRequired(true)
|
||||
.build()
|
||||
authWithBiometricPrompt(requireActivity(), fallbackPromptInfo, callback)
|
||||
break
|
||||
}
|
||||
delay(50)
|
||||
}
|
||||
}
|
||||
return ComposeView(requireContext()).apply {
|
||||
setContent {
|
||||
val materialYou = mutableStateOf(sharedPref.getBoolean("material_you",true))
|
||||
val blackTheme = mutableStateOf(sharedPref.getBoolean("black_theme", false))
|
||||
OwnDroidTheme(materialYou.value, blackTheme.value) {
|
||||
Auth(this@AuthFragment.requireActivity(), callback)
|
||||
Auth(this@AuthFragment.requireActivity(), callback, promptInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +90,8 @@ class AuthFragment: Fragment() {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Auth(activity: FragmentActivity, callback: AuthenticationCallback) {
|
||||
fun Auth(activity: FragmentActivity, callback: AuthenticationCallback, promptInfo: PromptInfo.Builder) {
|
||||
val context = LocalContext.current
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
@@ -74,7 +100,19 @@ fun Auth(activity: FragmentActivity, callback: AuthenticationCallback) {
|
||||
Text(text = "Authenticate", style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onBackground)
|
||||
Button(
|
||||
onClick = {
|
||||
authWithBiometricPrompt(activity, callback)
|
||||
val bioManager = BiometricManager.from(context)
|
||||
when(BiometricManager.BIOMETRIC_SUCCESS){
|
||||
bioManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) ->
|
||||
promptInfo
|
||||
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG)
|
||||
.setNegativeButtonText("Use password")
|
||||
bioManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) ->
|
||||
promptInfo
|
||||
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK)
|
||||
.setNegativeButtonText("Use password")
|
||||
else -> promptInfo.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
|
||||
}
|
||||
authWithBiometricPrompt(activity, promptInfo.build(), callback)
|
||||
}
|
||||
){
|
||||
Text(text = "Start")
|
||||
@@ -82,14 +120,8 @@ fun Auth(activity: FragmentActivity, callback: AuthenticationCallback) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun authWithBiometricPrompt(activity: FragmentActivity, callback: AuthenticationCallback) {
|
||||
private fun authWithBiometricPrompt(activity: FragmentActivity, promptInfo: PromptInfo, callback: AuthenticationCallback) {
|
||||
val executor = ContextCompat.getMainExecutor(activity.applicationContext)
|
||||
val biometricPrompt = BiometricPrompt(activity, executor, callback)
|
||||
val promptInfo = BiometricPrompt.PromptInfo.Builder()
|
||||
.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
|
||||
.setTitle("Auth")
|
||||
.setConfirmationRequired(true)
|
||||
.setSubtitle("Enter password")
|
||||
.build()
|
||||
biometricPrompt.authenticate(promptInfo)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user