AndroidX Biometric Library: Getting Started
In this tutorial you will learn how to use the AndroidX Biometric Library by showing the biometric prompt and using its callbacks. By Abdalla Ali.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
After long hours spent working on your app, nothing beats seeing it fully functional. Although building a good-looking, bug-free app is important, you also need to include security features to help keep your users protected. There are many security features available, with biometric security being particularly effective.
The Android Biometric Library makes adding these features easy and fun.
This library is available back to API level 23 and includes a biometric prompt UI out of the box. It also lets you see if a device supports biometric hardware with a single method call.
In this tutorial, you’ll use the Android Biometric Library to build an app called SecurePass. You’ll learn how to:
- Use the AndroidX Biometric API.
- Initialize
BiometricPrompt
and callbacks. - Use it with Android’s
SharedPreferences
.
Getting Started
Download the project materials by clicking the Download Materials button at the top or bottom of this tutorial. Launch Android Studio 3.5.3 or later and select the Open an existing Android Studio project option. Then navigate to and select the begin project folder.
Once Gradle build loading is complete, build and run the app. Explore the begin project.
Adding the Biometric Library Dependency
First, open build.gradle (Module:app) and add the following library dependency within dependencies
:
implementation 'androidx.biometric:biometric:1.0.1'
Click Sync now to sync the project so you can use the Biometric API.
Working With Biometric API
Now, you’ll learn how to initialize the BiometricPrompt
and use its biometric callbacks.
Open MainActivity.kt and add the following code at the bottom of onCreate
:
val executor = ContextCompat.getMainExecutor(this)
val biometricManager = BiometricManager.from(this)
Add the BiometricManager
missing import by pressing Option+Enter on Mac or Alt+Enter on PC.
Here, you get a reference to the Executor
that performs tasks on the main thread and a reference of BiometricManager
, both for the current context. You pass executor
to your biometric prompt, which uses it to perform UI operations. Then you take advantage of biometricManager
to see if the device supports biometric hardware.
You’ll see all that in a moment.
Next, add the following code block just below biometricManager
initialization:
when (biometricManager.canAuthenticate()) {
BiometricManager.BIOMETRIC_SUCCESS ->
authUser(executor)
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
Toast.makeText(
this,
getString(R.string.error_msg_no_biometric_hardware),
Toast.LENGTH_LONG
).show()
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
Toast.makeText(
this,
getString(R.string.error_msg_biometric_hw_unavailable),
Toast.LENGTH_LONG
).show()
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED ->
Toast.makeText(
this,
getString(R.string.error_msg_biometric_not_setup),
Toast.LENGTH_LONG
).show()
}
Don’t be afraid of the unresolved reference of authUser
. You’ll define it soon.
In the code above, you use biometricManager
to see if the user’s device supports biometric features before you perform any authentication. If it doesn’t, you show a user-friendly message stating the device doesn’t support this feature.
Adding Biometric Authentication
You’ll now create the authUser
function which takes executor
as a paremeter. You’ll use this function to perform biometric authentication if the device can handle it. Copy the code below at the bottom of MainActivity.kt.
private fun authUser(executor: Executor) {
}
Add the following code inside authUser.
:
// 1
val promptInfo = BiometricPrompt.PromptInfo.Builder()
// 2
.setTitle(getString(R.string.auth_title))
// 3
.setSubtitle(getString(R.string.auth_subtitle))
// 4
.setDescription(getString(R.string.auth_description))
// 5
.setDeviceCredentialAllowed(true)
// 6
.build()
Add BiometricPrompt
missing import by pressing Option+Enter on Mac or Alt+Enter on PC. Select Import, if asked, and choose androidx.biometric
.
Here you create the authentication dialog by specifying its properties.
Here’s a code breakdown:
-
promptInfo
: Declares this variable and intializes it withBiometricPrompt.PromptInfo
builder to build the authentication dialog. -
setTitle
: Gives the dialog a title. -
setSubtitle
: Assigns the dialog a subtitle that is placed below the main title. -
setDescription
: Describes this dialog so the end-user understands what it is and the function behind it. -
setDeviceCredentialAllowed(true)
: Use this to let a user whose device doesn’t support fingerprint authentication use a password or a pattern instead. -
build()
: Call this to build the dialog with the properties you specified above.
Now that you’ve set up the authentication dialog, you need to handle the callbacks and the flow of when the user interacts with it.
Handling the Authentication Callbacks
Add the following block of code below promptInfo
initialization:
// 1
val biometricPrompt = BiometricPrompt(this, executor,
object : BiometricPrompt.AuthenticationCallback() {
// 2
override fun onAuthenticationSucceeded(
result: BiometricPrompt.AuthenticationResult
) {
super.onAuthenticationSucceeded(result)
main_layout.visibility = View.VISIBLE
}
// 3
override fun onAuthenticationError(
errorCode: Int, errString: CharSequence
) {
super.onAuthenticationError(errorCode, errString)
Toast.makeText(
applicationContext,
getString(R.string.error_msg_auth_error, errString),
Toast.LENGTH_SHORT
).show()
}
// 4
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
Toast.makeText(applicationContext,
getString(R.string.error_msg_auth_failed),
Toast.LENGTH_SHORT
).show()
}
})
That’s a lot of code. Here’s a breakdown:
- You declare a variable called
biometricPrompt
and initialize it withBiometricPrompt
.BiometricPrompt
takes three parameters: The context, the executor and the authentication callbacks. The callbacks deal with whether the authentication is successful, an error occurred we can recover from, or when it completely fails. - When the user authenticates successfully,
onAuthenticationSucceeded
triggers and changes the visibility of the layout fromView.GONE
toView.VISIBLE
. - When an error occurs that can’t be recovered from,
onAuthenticationError
is triggered. In this case you show aToast
to the user, explaining what happened. -
onAuthenticationFailed
: This callback triggers when a biometric is valid but isn’t recognized. In this case you show anotherToast
to the user.
Finally, add this line of code at the bottom of authUser
to see the dialog triggered on the screen:
biometricPrompt.authenticate(promptInfo)
You authenticate the dialog by passing promptInfo
, which holds the dialog properties, to biometricPrompt
so you can see the dialog.
Now, moment you’ve been waiting for. :]
Build and run the project to see the authentication in action.
Finally! It feels good to see the biometric dialog appear on your screen. :]
Instead of using a fingerprint for authentication, you also have the option of using a password.
Persisting Data After Authentication
Right now, the profile screen looks static, and you can’t interact with it that much. You’ll make it interactive by using Android SharedPreferences
to persist your info on your device. Then you’ll see your info appear again the next time you open the app.
Open activity_main.xml and add the following code at the end, right before the closing LinearLayout
tag.
<Button
android:id="@+id/btnSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/label_save_changes" />
Here you added an Android Button to save the data from the form to SharedPreferences
.
Next, go back to MainActivity.kt and add this code at the bottom of onCreate
:
btnSave.setOnClickListener {
}
You added OnClickListener
so the button responds to your action whenever you tap on it.