Android Biometric API: Getting Started

Learn how to implement biometric authentication in your Android app by using the Android Biometric API to create an app that securely stores messages. By Zahidur Rahman Faisal.

4.6 (8) · 1 Review

Download materials
Save for later
Share

What’s the most commonly used feature of a smartphone, apart from making phone calls or texting? Is it taking photos? File sharing? Listening to music or watching videos? Actually, it’s a feature many people use countless times a day without even thinking about it: biometric authentication!

Biometric authentication allows you to quickly unlock your device with your fingerprint or face, confirming it’s really you who’s using the device. In this tutorial, you’ll learn how to use it to create an app named iCrypt using the Android Biometric API.

This app will securely store your messages, so only you can unlock them using your biometric signature. You’ll learn how to:

  1. Integrate the AndroidX Biometric Library.
  2. Authenticate a user through a biometric prompt.
  3. Encrypt and decrypt sensitive information using biometric credentials.
  4. Properly handle successful or failed authentication.
Note: This tutorial requires a device that has biometric authentication capability, either fingerprint or Android face recognition. The examples and sample code here will focus on the fingerprint authentication process.

Getting Started

Download the materials using the Download Materials button at the top or the bottom of this tutorial. Extract and open the starter project in Android Studio 4.0 or later.

Before you build and run, you need to include a dependency for the AndroidX Biometric Library, which is a one-stop user authentication solution for Android developers.

Open the app-level build.gradle file and add the following line to the end of dependencies {...}:

def biometricLibraryVersion = "1.0.1"
implementation "androidx.biometric:biometric:$biometricLibraryVersion"

In this code, you specify the version of the library to use and include it as a dependency for compilation. Click Sync Now at the top-right corner of the Android Studio to sync your project, and you’re all set! Build and run and you’ll see the login screen:

iCrypt Login Screen

Before proceeding, take a closer look at the library you just added to your code.

Introducing The Android Biometric API

AndroidX Biometric Library allows developers to:

  • Check if the device supports biometric authentication.
  • Display a standardized biometric prompt for fingerprint or facial recognition.
  • Detect successful or failed authentication attempts with simple callbacks.
  • Provide the option to use a device’s PIN/pattern/password instead of biometric credentials.

Here’s how it works under the hood with different Android versions and vendors:

Android Biometric Architecture chart

Note: If you’re interested in learning more about Android Biometric Architecture, check out the official documentation.

You’ll start by checking if a device can use biometric authentication.

Checking Device Capabilities

Since Android Biometric APIs are relatively new, not all devices have biometric capability. So your first step is to check if your user’s device is capable of biometric authentication. This only takes a few simple steps.

Create a new object file named BiometricUtil inside the util package. In Android Studio, select the util package, then click File ▸ New ▸ Kotlin File/Class. Next, select Object and enter the name. This will be your helper class for managing the biometric authentication process.

Now, add this function to check the user’s hardware capability:

fun hasBiometricCapability(context: Context): Int {
  val biometricManager = BiometricManager.from(context)
  return biometricManager.canAuthenticate()
}

Next, add the follow imports at the top of the file:

import android.content.Context
import androidx.biometric.BiometricManager

The code above creates a BiometricManager from the app context and calls canAuthenticate() to check whether the hardware is capable of biometric authentication.

However, this doesn’t guarantee that the user is ready to use biometric authentication. They may have the necessary hardware for facial recognition or reading fingerprints on the device, but you can only call a BiometricPrompt if you’ve registered your fingerprint or face in the device’s Security Settings.

When you run canAuthenticate(), it returns one of three different results:

  1. BIOMETRIC_SUCCESS: The device is ready to use a biometric prompt, meaning the hardware is available and the user has enrolled their biometric data.
  2. BIOMETRIC_ERROR_NONE_ENROLLED: The device supports biometrics, but the user hasn’t enrolled either their fingerprints or their face.
  3. BIOMETRIC_ERROR_NO_HARDWARE: The device hardware has no biometric authentication capability.

To ensure the device is ready to use a biometric prompt, add the following function:

fun isBiometricReady(context: Context) =
      hasBiometricCapability(context) == BiometricManager.BIOMETRIC_SUCCESS

This returns true only if the device has biometric hardware capability and the user has enrolled their biometrics.

Implementing the Biometric Login

You want to show an option for the user to log in with biometrics when they are ready, so open LoginActivity inside the ui package and replace showBiometricLoginOption() with the code below:

fun showBiometricLoginOption() {
  buttonBiometricsLogin.visibility =
      if (BiometricUtil.isBiometricReady(this)) View.VISIBLE
      else View.GONE
}

This adds the following in the imports section on top:

import com.raywenderlich.icrypt.util.BiometricUtil
import kotlinx.android.synthetic.main.activity_login.*

The function above is self-explanatory: It shows the button to log in with biometrics if the device supports biometric login and the user has set their fingerprint or facial ID. Otherwise, it’ll hide the button and the user can’t access the biometric login feature.

Run the app again. If you’ve enrolled your biometrics, you’ll see a new button, USE BIOMETRICS TO LOGIN, appear below the original login button.

Login Screen with Biometric Login button

Building BiometricPrompt

If you’re eager to use biometrics to log in and eliminate the need to type your password, there’s good news. You’re only two steps away from displaying a biometric prompt to ease your login process.

Here’s what you need to do first:

  1. Set PromptInfo with your desired message and configuration.
  2. Initialize the biometric prompt with the calling activity and callback handlers.

Preparing PromptInfo

Open BiometricUtil.kt again and append this function:

fun setBiometricPromptInfo(
    title: String,
    subtitle: String,
    description: String,
    allowDeviceCredential: Boolean
): BiometricPrompt.PromptInfo {
  val builder = BiometricPrompt.PromptInfo.Builder()
      .setTitle(title)
      .setSubtitle(subtitle)
      .setDescription(description)

  // Use Device Credentials if allowed, otherwise show Cancel Button
  builder.apply {
    if (allowDeviceCredential) setDeviceCredentialAllowed(true)
    else setNegativeButtonText("Cancel")
  }

  return builder.build()
}

Next, include this import above the code you just added:

import androidx.biometric.BiometricPrompt

The code above uses a builder class, BiometricPrompt.PromptInfo.Builder, to create the dialog and populate it with the title, subtitle and description — pretty simple!

Are you wondering what allowDeviceCredential is doing here? It allows you to configure fallback options to skip biometric authentication. For example, this lets you offer the option to use the device’s existing passcode/pattern or show a Cancel button when the biometric prompt displays. BiometricPrompt.PromptInfo.Builder offers you both options with some built-in functions.

Setting allowDeviceCredential to true applies setDeviceCredentialAllowed(true) to the dialog builder to create a special button that launches your device’s PIN, passcode or pattern lock screen as an alternative method of user authentication.

The default value for allowDeviceCredential is false. In that case, the biometric prompt shows a Negative or Cancel button. setNegativeButtonText("Cancel") just sets the button text to Cancel. You’re free to set any text, though, like, “Go Away”. :]