Files
OwnDroid/app/src/main/java/com/bintianqi/owndroid/Auth.kt
2024-05-15 12:42:59 +08:00

96 lines
4.0 KiB
Kotlin

package com.bintianqi.owndroid
import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.biometric.BiometricPrompt.AuthenticationCallback
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
class AuthFragment: Fragment() {
@SuppressLint("UnrememberedMutableState")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val sharedPref = context?.getSharedPreferences("data", Context.MODE_PRIVATE)!!
val onAuthSucceed = {
val fragmentManager = this.parentFragmentManager
val fragment = fragmentManager.findFragmentByTag("auth")
if(fragment != null) {
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.base, homeFragment)
fragmentTransaction.commit()
}
}
val callback = object: AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
onAuthSucceed()
}
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
if(errorCode == BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL) onAuthSucceed()
if(errorCode == BiometricPrompt.ERROR_CANCELED) return
Toast.makeText(context, errString, Toast.LENGTH_SHORT).show()
}
}
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)
}
}
}
}
}
@Composable
fun Auth(activity: FragmentActivity, callback: AuthenticationCallback) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)
){
Text(text = "Authenticate", style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onBackground)
Button(
onClick = {
authWithBiometricPrompt(activity, callback)
}
){
Text(text = "Start")
}
}
}
private fun authWithBiometricPrompt(activity: FragmentActivity, 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)
}