Biometric Login System in Android with Jetpack Compose

Sufyan Sattar
4 min readOct 5, 2023

Biometric authentication has become increasingly popular in recent years due to its convenience and security.

In this tutorial, we will guide you through the process of implementing a biometric login system in an Android app using Jetpack Compose. Jetpack Compose is a modern Android UI toolkit that makes it easier to build user interfaces using a declarative syntax.

We will break down the implementation into several steps:

Setting Up Your Project

First, make sure you have Android Studio installed and set up. Create a new Android project or use an existing one.

Adding Dependencies

In your app-level build.gradle file, add the following dependencies:

implementation "androidx.compose.ui:ui:1.0.0"
implementation "androidx.compose.ui:ui-tooling:1.0.0"
implementation "androidx.compose.ui:ui-material:1.0.0"
implementation "androidx.activity:activity-compose:1.4.0"
implementation "androidx.biometric:biometric:1.2.1"

Make sure to sync your project after adding these dependencies.

Checking Biometric Availability

Inside your Composable function, initialize the BiometricManager with the current context:

val context = LocalContext.current
val biometricManager = remember { BiometricManager.from(context) }

val isBiometricAvailable = remember {
biometricManager.canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
}
when (isBiometricAvailable) {
BiometricManager.BIOMETRIC_SUCCESS -> {
// Biometric is enabled in device
}

BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> {
// No biometric in deivice
}

BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> {
// Biometric currently unavailable
}

BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED -> {
// Biometric features available but a security vulnerability has been discovered
}

BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED -> {
// Biometric features are currently unavailable because the specified options are incompatible with the current Android version..
}

BiometricManager.BIOMETRIC_STATUS_UNKNOWN -> {
// Unable to determine whether the user can authenticate using biometrics
}

BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> {
// The user can't authenticate because no biometric or device credential is enrolled.
}
}

Creating the Biometric Login Screen

Create a new Composable function for your biometric login screen. You can design the layout using Compose’s declarative syntax. Here’s a simple example:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.*
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel

@Composable
fun BiometricLoginScreen() {
var password by remember { mutableStateOf("") }
var isBiometricEnabled by remember { mutableStateOf(false) }

val context = LocalContext.current
val isBiometricAvailable = LocalBiometricManager.current.isBiometricAvailable(context)

Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Biometric Login",
style = MaterialTheme.typography.h4,
modifier = Modifier.padding(bottom = 16.dp)
)

BasicTextField(
value = password,
onValueChange = { password = it },
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = {
if (isBiometricEnabled) {
// Authenticate using biometrics
authenticateWithBiometrics(context)
} else {
// Handle non-biometric login
// Replace this with your own login logic
}
}
),
modifier = Modifier
.fillMaxWidth()
.background(Color.Gray)
.padding(8.dp)
)

Spacer(modifier = Modifier.height(16.dp))

if (isBiometricAvailable) {
TextButton(
onClick = { isBiometricEnabled = true },
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
) {
Text(text = "Enable Biometric Login")
}
}

Spacer(modifier = Modifier.height(16.dp))

Button(
onClick = {
// Handle non-biometric login
// Replace this with your own login logic
},
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
) {
Text(text = "Login")
}
}
}

This Composable function creates a simple biometric login screen with a password field, an option to enable biometric login, and a login button.

Biometric Authentication

To implement biometric authentication, create a helper function authenticateWithBiometrics. Here's an example using the BiometricPrompt:

import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat

fun authenticateWithBiometrics(context: Context) {
val biometricPrompt = BiometricPrompt(
context,
ContextCompat.getMainExecutor(context),
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
// Biometric authentication successful
// Implement your logic here
}

override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
// Biometric authentication failed
// Handle errors
}
}
)

val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric Login")
.setSubtitle("Sufyan Please Place your finger on the sensor")
.setNegativeButtonText("Use Password")
.build()

biometricPrompt.authenticate(promptInfo)
}

Integration

Finally, integrate the BiometricLoginScreen Composable into your app's navigation flow or activity layout. You can use the NavHost for navigation or simply add it to your setContent in your MainActivity.

  • Change your MainActivity’s parent from ComponentActivity to FragmentActivity. If you face any context exception.
setContent {
BiometricLoginScreen()
}

Testing and Customization

Test your biometric login system on a device with biometric hardware (e.g., fingerprint sensor or face recognition). You can customize the appearance and behavior of the biometric prompt to match your app’s design. You can contact me for futhurt information that you need

Security Considerations

Ensure that you handle the authentication result securely and store user data safely. Biometric authentication should enhance security, not compromise it.

With these steps, you have implemented a biometric login system in your Android app using Jetpack Compose. Users can now enjoy the convenience of logging in with their biometric data, adding an extra layer of security to your app.

Hope you find this article helpful. Thanks!

--

--

Sufyan Sattar

Software Engineer — Android — Spring Boot — AWS — Vaadin — React