### Compose Multiplatform Biometric Authentication Setup Source: https://context7.com/icerockdev/moko-biometry/llms.txt This code demonstrates setting up biometric authentication in a Compose Multiplatform application. It uses `rememberBiometryAuthenticatorFactory()` to get a platform-aware factory and `BindBiometryAuthenticatorEffect` for necessary Android lifecycle binding. ```kotlin @Composable fun BiometricLoginScreen() { val biometryFactory: BiometryAuthenticatorFactory = rememberBiometryAuthenticatorFactory() val viewModel = remember { AuthViewModel( biometryAuthenticator = biometryFactory.createBiometryAuthenticator() ) } BindBiometryAuthenticatorEffect(viewModel.biometryAuthenticator) Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Button(onClick = { viewModel.performBiometricLogin() }) { Text("Login with Biometrics") } } } ``` -------------------------------- ### iOS ViewController Integration for Biometry (Swift) Source: https://github.com/icerockdev/moko-biometry/blob/master/README.md Provides a Swift example for integrating Moko-Biometry into an iOS `UIViewController`. It shows how to initialize the `SampleViewModel` with a platform-specific `BiometryBiometryAuthenticator` and trigger the authentication process via an IBAction. ```swift class SampleViewController: UIViewController { private var viewModel: SampleViewModel! override func viewDidLoad() { super.viewDidLoad() self.viewModel = SampleViewModel( biometryAuthenticator: BiometryBiometryAuthenticator(), ) } @IBAction private func loginAction() { self.viewModel.tryToAuth() } } ``` -------------------------------- ### Moko Biometry Dependency Setup in Gradle Source: https://github.com/icerockdev/moko-biometry/blob/master/README.md This Groovy script demonstrates how to add the Moko Biometry library and its Compose Multiplatform extension to your project's dependencies in the project-level build.gradle file. It specifies the commonMain API for multiplatform usage and also shows an option for Jetpack Compose on Android if not using multiplatform. ```groovy dependencies { commonMainApi("dev.icerock.moko:biometry:0.4.0") // Compose Multiplatform commonMainApi("dev.icerock.moko:biometry-compose:0.4.0") // Jetpack Compose (only for android, if you don't use multiplatform) implementation("dev.icerock.moko:biometry-compose:0.4.0") } ``` -------------------------------- ### Android Compose Activity Setup for Biometrics Source: https://context7.com/icerockdev/moko-biometry/llms.txt Configures an Android Activity to support biometric authentication within Jetpack Compose. The Activity must extend `FragmentActivity` instead of `ComponentActivity` to correctly display the biometric prompt dialog. This setup includes initializing the `BiometryAuthenticator` and binding it to the Activity's lifecycle using `BindBiometryAuthenticatorEffect`. ```kotlin import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.material.Button import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.fragment.app.FragmentActivity import dev.icerock.moko.biometry.compose.BindBiometryAuthenticatorEffect import dev.icerock.moko.biometry.compose.rememberBiometryAuthenticatorFactory import kotlinx.coroutines.launch // Dummy extension function for demonstration fun String.desc(): String = this // Dummy AuthViewModel for demonstration class AuthViewModel(val biometryAuthenticator: BiometryAuthenticator) { // ViewModel logic here } // Android - MainActivity.kt for Compose class MainActivity : FragmentActivity() { // Must be FragmentActivity, not ComponentActivity override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MaterialTheme { val biometryFactory = rememberBiometryAuthenticatorFactory() val viewModel = remember { AuthViewModel( biometryAuthenticator = biometryFactory.createBiometryAuthenticator() ) } // Bind to lifecycle - connects to FragmentActivity BindBiometryAuthenticatorEffect(viewModel.biometryAuthenticator) BiometricLoginContent(viewModel = viewModel) } } } } @Composable fun BiometricLoginContent(viewModel: AuthViewModel) { var resultText by remember { mutableStateOf("Ready to authenticate") } val scope = rememberCoroutineScope() Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text(text = resultText) Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { scope.launch { resultText = "Authenticating..." try { val success = viewModel.biometryAuthenticator.checkBiometryAuthentication( requestTitle = "Verify Identity".desc(), requestReason = "Please authenticate to proceed".desc(), failureButtonText = "Use Password".desc(), allowDeviceCredentials = false ) resultText = if (success) "Success!" else "Cancelled" } catch (e: Throwable) { resultText = "Error: ${e.message}" } } }) { Text("Authenticate with Biometrics") } } } ``` -------------------------------- ### Android Compose Activity Integration for Biometry (Kotlin) Source: https://github.com/icerockdev/moko-biometry/blob/master/README.md Illustrates how to integrate Moko-Biometry with Jetpack Compose in an Android Activity. This example extends `FragmentActivity`, uses `rememberBiometryAuthenticatorFactory` to create the authenticator, and employs `BindBiometryAuthenticatorEffect` to manage the authenticator's lifecycle within the Compose UI. ```kotlin class MainActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setContent { val biometryFactory: BiometryAuthenticatorFactory = rememberBiometryAuthenticatorFactory() // Create viewModel from common code val viewModel = getViewModel { SampleViewModel( // Pass platform implementation of the Biometry Authenticator // to a common code biometryAuthenticator = biometryFactory.createBiometryAuthenticator() ) } // Binds the Biometry Authenticator to the view lifecycle BindBiometryAuthenticatorEffect(viewModel.biometryAuthenticator) // Same screen content here } } } ``` -------------------------------- ### iOS Biometry Integration and Info.plist Configuration Source: https://context7.com/icerockdev/moko-biometry/llms.txt For iOS, BiometryAuthenticator can be created directly without binding. It's crucial to add the NSFaceIDUsageDescription key to Info.plist to inform users about Face ID usage. This Swift code shows the ViewController setup. ```swift import UIKit import MultiPlatformLibrary class LoginViewController: UIViewController { private var viewModel: AuthViewModel! override func viewDidLoad() { super.viewDidLoad() self.viewModel = AuthViewModel( biometryAuthenticator: BiometryBiometryAuthenticator() ) } @IBAction private func loginButtonTapped() { self.viewModel.performBiometricLogin() } } // Info.plist - Add Face ID usage description (required for Face ID) // NSFaceIDUsageDescription // $(PRODUCT_NAME) uses Face ID to securely authenticate you ``` -------------------------------- ### Create ViewModel for Biometric Authentication (Kotlin) Source: https://github.com/icerockdev/moko-biometry/blob/master/README.md Demonstrates how to create a ViewModel in common Kotlin code that utilizes the BiometryAuthenticator. It includes a function to initiate biometric authentication with customizable request details and handles success or failure callbacks. This is the core logic that can be shared across platforms. ```kotlin class SampleViewModel( val biometryAuthenticator: BiometryAuthenticator ) : ViewModel() { fun tryToAuth() = viewModelScope.launch { try { val isSuccess = biometryAuthenticator.checkBiometryAuthentication( requestTitle = "Biometry".desc(), requestReason = "Just for test".desc(), failureButtonText = "Oops".desc(), allowDeviceCredentials = false // true - if biometric permission is not granted user can authorise by device creds ) if (isSuccess) { // Do something onSuccess } } catch (throwable: Throwable) { // Do something onFailed } } } ``` -------------------------------- ### Android Activity Integration for Biometry (Kotlin) Source: https://github.com/icerockdev/moko-biometry/blob/master/README.md Shows how to integrate the common ViewModel with BiometryAuthenticator into an Android Activity. It covers creating the ViewModel, passing the platform-specific `applicationContext`, and binding the authenticator to the Activity's lifecycle for proper management. ```kotlin class MainActivity : AppCompatActivity() { private lateinit var viewModel: SampleViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create viewModel from common code. viewModel = getViewModel { SampleViewModel( // Pass platform implementation of the Biometry Authenticator // to a common code biometryAuthenticator = BiometryAuthenticator( applicationContext = applicationContext ) ) } // Binds the Biometry Authenticator to the view lifecycle viewModel.biometryAuthenticator.bind( lifecycle = this@MainActivity.lifecycle, fragmentManager = supportFragmentManager ) } } ``` -------------------------------- ### Project-Level Gradle Configuration for Moko Biometry Source: https://github.com/icerockdev/moko-biometry/blob/master/README.md This Groovy script configures the root build.gradle file to include Maven Central as a repository, which is necessary for resolving dependencies like Moko Biometry. ```groovy allprojects { repositories { mavenCentral() } } ``` -------------------------------- ### iOS Info.plist Configuration for Biometry (XML) Source: https://github.com/icerockdev/moko-biometry/blob/master/README.md This snippet shows the necessary addition to your iOS project's `Info.plist` file. It includes the `NSFaceIDUsageDescription` key, which is required to explain to the user why your app needs access to Face ID or Touch ID. ```xml NSFaceIDUsageDescription $(PRODUCT_NAME) Authentication with TouchId or FaceID ``` -------------------------------- ### Compose Multiplatform Biometry Screen (Kotlin) Source: https://github.com/icerockdev/moko-biometry/blob/master/README.md Demonstrates a composable function for a Biometry screen in a Compose Multiplatform application. It utilizes `rememberBiometryAuthenticatorFactory` and `getViewModel` to set up the ViewModel and `BindBiometryAuthenticatorEffect` to bind the authenticator to the composable's lifecycle, displaying authentication status and a button to trigger the action. ```kotlin @Composable fun BiometryScreen() { val biometryFactory: BiometryAuthenticatorFactory = rememberBiometryAuthenticatorFactory() BiometryScreen( viewModel = getViewModel( key = "biometry-screen", factory = viewModelFactory { BiometryViewModel( biometryAuthenticator = biometryAuthenticatorFactory.createBiometryAuthenticator() ) } ) ) } @Composable private fun BiometryScreen( viewModel: BiometryViewModel ) = NavigationScreen(title = "moko-biometry") { paddingValues -> BindBiometryAuthenticatorEffect(viewModel.biometryAuthenticator) val text: String by viewModel.result.collectAsState() Column( modifier = Modifier.fillMaxSize().padding(paddingValues), horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = text) Button(onClick = viewModel::onButtonClick) { Text(text = "Click on me") } } } ``` -------------------------------- ### Add moko-biometry Dependencies to Kotlin Multiplatform Project Source: https://context7.com/icerockdev/moko-biometry/llms.txt Integrates the moko-biometry library into your Kotlin Multiplatform project by adding its dependencies to your Gradle build files. This enables biometric authentication features across Android and iOS. Ensure mavenCentral() is available in your project-level repositories. ```kotlin // build.gradle.kts (project level) allprojects { repositories { mavenCentral() } } // build.gradle.kts (module level) kotlin { sourceSets { val commonMain by getting { dependencies { // Core biometry module api("dev.icerock.moko:biometry:0.4.0") // For Compose Multiplatform support api("dev.icerock.moko:biometry-compose:0.4.0") } } } } // For Android-only Jetpack Compose projects dependencies { implementation("dev.icerock.moko:biometry-compose:0.4.0") } ``` -------------------------------- ### Android Biometry Integration with Lifecycle Binding Source: https://context7.com/icerockdev/moko-biometry/llms.txt On Android, the BiometryAuthenticator requires binding to an Activity's lifecycle and FragmentManager for proper biometric prompt display. This Kotlin code demonstrates creating and binding the authenticator within an AppCompatActivity. ```kotlin class MainActivity : AppCompatActivity(), AuthViewModel.EventListener { private lateinit var viewModel: AuthViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val biometryAuthenticator = BiometryAuthenticator( applicationContext = applicationContext ) viewModel = getViewModel { AuthViewModel(biometryAuthenticator = biometryAuthenticator) } viewModel.biometryAuthenticator.bind( lifecycle = this.lifecycle, fragmentManager = supportFragmentManager ) } fun onLoginButtonClick(view: View) { viewModel.performBiometricLogin() } } ``` -------------------------------- ### Perform Biometric Authentication using BiometryAuthenticator Source: https://context7.com/icerockdev/moko-biometry/llms.txt Initiates a biometric authentication process using the `BiometryAuthenticator`. This suspend function displays a system prompt for fingerprint or face scan. It returns `true` on success, `false` if cancelled, and throws an exception on errors. Utilize this in your shared ViewModel logic. ```kotlin // commonMain - Shared ViewModel with biometric authentication import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import dev.icerock.moko.biometry.BiometryAuthenticator import dev.icerock.moko.resources.desc // Assuming 'desc()' is an extension for resource strings class AuthViewModel( val biometryAuthenticator: BiometryAuthenticator ) : ViewModel() { fun performBiometricLogin() = viewModelScope.launch { try { val isSuccess = biometryAuthenticator.checkBiometryAuthentication( requestTitle = "Authenticate".desc(), // Dialog title requestReason = "Confirm your identity".desc(), // Subtitle/reason failureButtonText = "Use Password".desc(), // Negative button text allowDeviceCredentials = false // true = allow PIN/pattern fallback ) if (isSuccess) { // Authentication successful - proceed with secure operation println("Biometric authentication passed") } else { // User cancelled or dismissed the prompt println("Authentication cancelled by user") } } catch (exception: Throwable) { // Authentication failed (too many attempts, biometric not enrolled, etc.) println("Authentication error: ${exception.message}") } } } ``` -------------------------------- ### Check Biometric Availability with BiometryAuthenticator Source: https://context7.com/icerockdev/moko-biometry/llms.txt Determines if biometric authentication is available on the current device. This method returns `true` if the hardware supports biometrics and at least one biometric is enrolled, otherwise it returns `false`. Use this to conditionally display biometric login options. ```kotlin // commonMain - Check biometric availability before showing auth UI import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch import dev.icerock.moko.biometry.BiometryAuthenticator import dev.icerock.moko.resources.desc // Assuming 'desc()' is an extension for resource strings class SecurityViewModel( val biometryAuthenticator: BiometryAuthenticator ) : ViewModel() { fun checkAndAuthenticate() { if (biometryAuthenticator.isBiometricAvailable()) { // Biometrics available - show biometric login option performBiometricLogin() } else { // Biometrics not available - fall back to password showPasswordLoginScreen() } } private fun performBiometricLogin() = viewModelScope.launch { try { val success = biometryAuthenticator.checkBiometryAuthentication( requestTitle = "Biometric Login".desc(), requestReason = "Authenticate to access your account".desc(), failureButtonText = "Cancel".desc(), allowDeviceCredentials = true // Allow device passcode as fallback ) if (success) onLoginSuccess() else onLoginCancelled() } catch (e: Throwable) { onLoginError(e) } } private fun showPasswordLoginScreen() { /* ... */ } private fun onLoginSuccess() { /* ... */ } private fun onLoginCancelled() { /* ... */ } private fun onLoginError(e: Throwable) { /* ... */ } } ``` -------------------------------- ### Bind Biometry Authenticator Effect for Compose Multiplatform Source: https://context7.com/icerockdev/moko-biometry/llms.txt A Composable side-effect that binds the BiometryAuthenticator to the current lifecycle. This is crucial for Android to connect the authenticator to the FragmentActivity's lifecycle and FragmentManager. On iOS, it's a no-op but included for cross-platform compatibility. It takes a BiometryAuthenticator instance as input and returns nothing. ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material.Button import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.unit.dp import dev.icerock.moko.biometry.BiometryAuthenticator import dev.icerock.moko.biometry.compose.BindBiometryAuthenticatorEffect import dev.icerock.moko.biometry.compose.rememberBiometryAuthenticatorFactory import kotlinx.coroutines.launch // Dummy extension function for demonstration fun String.desc(): String = this sealed class AuthState { object Idle : AuthState() object Success : AuthState() object Cancelled : AuthState() data class Error(val message: String) : AuthState() } @Composable fun SecureAppScreen() { val biometryFactory = rememberBiometryAuthenticatorFactory() val biometryAuthenticator = remember { biometryFactory.createBiometryAuthenticator() } // REQUIRED: Bind to lifecycle for Android compatibility BindBiometryAuthenticatorEffect(biometryAuthenticator) var authState by remember { mutableStateOf(AuthState.Idle) } val scope = rememberCoroutineScope() Column( modifier = Modifier.fillMaxSize().padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = when (authState) { AuthState.Idle -> "Tap to authenticate" AuthState.Success -> "Authentication successful!" AuthState.Cancelled -> "Authentication cancelled" is AuthState.Error -> "Error: ${(authState as AuthState.Error).message}" } ) Spacer(modifier = Modifier.height(24.dp)) Button( onClick = { scope.launch { authState = try { val success = biometryAuthenticator.checkBiometryAuthentication( requestTitle = "Secure Access".desc(), requestReason = "Authenticate to continue".desc(), failureButtonText = "Cancel".desc(), allowDeviceCredentials = true ) if (success) AuthState.Success else AuthState.Cancelled } catch (e: Throwable) { AuthState.Error(e.message ?: "Unknown error") } } } ) { Text("Authenticate") } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.