AndroidX BiometricPrompt vs FingerprintManager: the good and the ugly

Fidel Montesino
Kin + Carta Created
4 min readOct 10, 2019

We are all used to using our fingerprint not just to unlock our Android phone, but also to authenticate purchases in Google Play, lock application access, approve money transfers on our banking app, etc.

Biometric recognition has evolved a lot in the past few years. We are slowly starting to see new types of biometric recognition (iris, face, etc.) and the Android ecosystem (starting with Android P) is quickly catching up with these new technologies.

In this post we are going to explore which options we have in the Android SDK in order to implement biometric recognition, their benefits and also their downsides.

Option 1: The recommended (official) way

AndroidX BiometricPrompt is the new approach to use all the new biometric authentication APIs from Android P and since it’s part of the AndroidX library, it’s backwards compatible with older versions of Android.

Using BiometricPrompt in our app offers us some advantages:

  • Multiple biometrics: if the device has more than one biometric authentication method (like iris, face, etc) it will select the authentication method configured by the user (before Android P it will just use fingerprints).
AndroidX BiometricPrompt asking for iris, face and fingerprint authentication
  • Consistent UI: it provides a standardised dialog that works out of the box across multiple Android versions and persists across orientation changes.
  • Easy implementation: it keeps things simple by only requiring you to provide the text that will be displayed to the user and a few callbacks for authentication success or failure.
val biometricPrompt = BiometricPrompt(activity, executor, object : BiometricPrompt.AuthenticationCallback() {

override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
//Handle here the errors
}

override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
//Handle here the success
}

override fun onAuthenticationFailed() {
//Handle here a failure
}
})
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Set the title to display.")
.setSubtitle("Set the subtitle to display.")
.setDescription("Set the description to display")
.setNegativeButtonText("Negative Button")
.build()
biometricPrompt.authenticate(promptInfo)

Sadly enough, the current implementation of the AndroidX BiometricPrompt doesn’t allow us to restrict or select which biometric capabilities are being used, a huge downside if you want more granular control about the authentication method your app uses.

It also lacks the ability to know beforehand whether the device has biometric hardware or the user has biometric data enrolled. You must try to show the biometric authentication prompt in order to capture these scenarios as an error callback.

Option 2: Limit the prompt to use just fingerprints

Manufacturers like Samsung warn you about face recognition not being a strong check as the device can be tricked with a picture. What if you are developing a banking app and concerned about the security and reliability of this new biometric authentication methods? What if you are designing and building an app that has to work just with fingerprints? Then the FingerprintManager comes into play.

The FingerprintManager (and its backwards-compatible version FingerprintManagerCompat) was the first official biometric API in Android. Now it has been deprecated in favour of the BiometricPrompt, so we won’t be getting official updates for it.

We will need to build our own UI from scratch, requiring some time and effort that we might want to spend elsewhere in the app. We will also need to implement our custom error handling for multiple scenarios (authentication cancelled, too many attempts, etc), apart from the authentication successful and authentication failure callbacks.

However, the FingerprintManager works only with fingerprints and that is something we might need as a requirement for our application for security and usability reasons. It has direct access to the fingerprint hardware, so we can know beforehand if the device has biometric hardware or fingerprints enrolled.

Also, with this approach we’ve solved most of the issues we’ve encountered with the BiometricPrompt: devices using in-display fingerprint readers (such as OnePlus 6T or Samsung Galaxy S10) weren’t showing the built-in UI.

AndroidX BiometricPrompt: emulator (left), OnePlus 6T (centre), Custom UI with FPM: OnePlus 6T (right)

Finally, we gained control over the accessibility announcements. With this new custom UI we can control what, how and when we announce texts for accessibility, something we also struggled to implement with the above mentioned devices.

Conclusion

The new AndroidX BiometricPrompt is the easy and out-of-the box solution for most of the biometric authentication needs. It works with the preferred biometric set by the user (either face, iris or fingerprint) and provides a consistent, lifecycle-aware UI that makes our development process faster and safer.

However, if you are concerned about the security of these new biometrics or have a design constraint and you want to restrict the biometric authentication to use just fingerprints, your best solution is to use the deprecated FingerprintManager.

Since the AndroidX biometric library is still an alpha version, we might see some changes in the API, hopefully allowing us to restrict to specific biometrics or, at least, enforce using strong biometrics such as fingerprint.

If that’s not the case, we hope they remove the deprecation or, at least, we can continue using the FingerprintManager for a bit longer, as it’s our only solution for making our apps more secure.

--

--