For now, you can use Biometric API which under the hood checks which type of biometric is available on the device (face unlock or fingerprint) and will do all the stuff, including handling many hardware-specific issues.
So, start with adding the dependency:
implementation 'androidx.biometric:biometric:1.0.1'
You can check availability with the following method:
val biometricManager = BiometricManager.from(this)
when (biometricManager.canAuthenticate()) {
BiometricManager.BIOMETRIC_SUCCESS ->
// App can authenticate using biometrics
BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE ->
// No biometric features available on this device
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE ->
// Biometric features are currently unavailable
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED ->
// The user hasn't associated any biometric credentials with their account
}
Use a provided for you system dialog:
private lateinit var executor: Executor
private lateinit var biometricPrompt: BiometricPrompt
private lateinit var promptInfo: BiometricPrompt.PromptInfo
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
executor = ContextCompat.getMainExecutor(this)
biometricPrompt = BiometricPrompt(this, executor,
object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int,
errString: CharSequence) {
super.onAuthenticationError(errorCode, errString)
// Authentication error
}
override fun onAuthenticationSucceeded(
result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
// Authentication succeeded!
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
// Authentication failed
}
})
promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric login for my app")
.setSubtitle("Log in using your biometric credential")
.setNegativeButtonText("Use account password")
.build()
// Prompt appears when user clicks "Log in".
// Consider integrating with the keystore to unlock cryptographic operations,
// if needed by your app.
biometricLoginButton.setOnClickListener {
biometricPrompt.authenticate(promptInfo)
}
}
If you want your app to unlock press a confirmation after a face unlock (for instance, when user performs a purchase) - it is the default behavior.
If you want to unlock the app right away without confirmation:
// Allows the user to authenticate without performing an action, such as pressing a button, after their biometric credential is accepted.
promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric login for my app")
.setSubtitle("Log in using your biometric credential")
.setNegativeButtonText("Use account password")
.setConfirmationRequired(false)
.build()
Also, you may need to set a fallback for user to unlock with the device pin/password/pattern. It is done in the following way:
promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric login for my app")
.setSubtitle("Log in using your biometric credential")
// Cannot call setNegativeButtonText() and
// setDeviceCredentialAllowed() at the same time.
// .setNegativeButtonText("Use account password")
.setDeviceCredentialAllowed(true)
.build()
Additional info and details on cryptography can be found here: https://developer.android.com/training/sign-in/biometric-auth