Skip to content

Backport of Android Pie's BiometricPrompt using Kotlin and RxJava

License

Notifications You must be signed in to change notification settings

diamirio/BiometricAuth

Repository files navigation

BiometricAuth

Download API 15

This library brings the new Android P BiometricPrompt for fingerprint authentication to Android SDK 23, using RxJava (2 or 3) and Kotlin.

Android 23..27 (>= Marshmallow) Android >= 28 (Pie, Q)
Dialog on Marshmallow devices Dialog on Pie devices

Setup

To use this library your minSdkVersion must be >= 15 (Note that the dialog however will only show starting Android SDK 23).

In your root-level build.gradle file, make sure you include the following maven repository:

allprojects {
    repositories {
        maven {
            url 'https://maven.tailored-apps.com/repository/maven-public/'
            // The content-filter ensures (for your safety) that only artifacts with the given group 
            // should be fetched from this repository:
            content { includeGroup 'com.tailoredapps' }
        }
    }
}

In your application build.gradle file, include the dependency (for RxJava2):

dependencies {
    implementation 'com.tailoredapps:biometricauth-rxjava2:1.4.0'
}

Or if you are using RxJava3:

dependencies {
    implementation 'com.tailoredapps:biometricauth-rxjava3:1.4.0'
}

Usage

Create a BiometricAuth instance:

val biometricAuth = BiometricAuth.create(this, useAndroidXBiometricPrompt = false) // where this is an (AppCompat-)Activity
if(!biometricAuth.hasFingerprintHardware) {
    //The devices does not support fingerprint authentication (i.e. has no fingerprint hardware)
    Toast.makeText(this, "Device does not support fingerprint", Toast.LENGTH_SHORT).show()
} else if(!biometricAuth.hasFingerprintsEnrolled) {
    //The user has not enrolled any fingerprints (i.e. fingerprint authentication is not activated by the user)
    Toast.makeText(this, "User has not enrolled any fingerprints", Toast.LENGTH_SHORT).show()
} else {
    biometricAuth
        .authenticate(
                title = "Please authenticate",
                subtitle = "'Awesome Feature' requires your authentication",
                description = "'Awesome Feature' exposes data private to you, which is why you need to authenticate.",
                negativeButtonText = "Cancel",
                prompt = "Touch the fingerprint sensor",
                notRecognizedErrorText = "Not recognized"
        )
        .subscribe(
                { Log.d("BiometricAuth", "User authentication successful.") },
                { throwable ->
                    if(throwable is BiometricAuthenticationCancelledException) {
                        Log.d("BiometricAuth", "User cancelled the operation")
                    } else if(throwable is BiometricAuthenticationException) {
                        // Might want to check throwable.errorMessageId for fields in BiometricConstants.Error,
                        // to get more information about the error / further actions here.
                        Log.d("BiometricAuth", "Unrecoverable authentication error")
                    } else {
                        Log.d("BiometricAuth", "Error during user authentication.")
                    }
                }
        )
}

The authenticate() function returns a Completable, which either:

  • completes, which indicates an authentication success, or
  • emits an error:
    • BiometricAuthenticationCancelledException, which signals that the operation has been cancelled (most likely triggered by the user).
    • BiometricAuthenticationException, which signals an unrecoverable error during biometric authentication (e.g. too many invalid attempts). The exception contains the localized error-message provided by the system. Furthermore, the errorMessageId contained in this exception is most likely one of the fields in BiometricConstants.Error (but not exclusively), which allows to get more information on the type or error.
    • any other unexpected error during authentication (Not any of the internal fingerprint errors like "not detected", as they will be handled internally).

CryptoObject

If you need to pass a crypto-object, add a BiometricAuth.CryptoObject as a first parameter to the BiometricAuth.authenticate method, which will then return a Single including the CryptoObject as a success-value.

What's inside?

On Android P/Q (SDK >= 28) devices, the new BiometricPrompt API is used.

On devices running Android Marshmallow to Oreo (SDK 23..27), the FingerprintManagerCompat API is used in combination with a custom UI, which imitates the AndroidPie BiometricPrompt Bottom-Sheet.

On older devices, where Fingerprint Authentication is not supported by native Android SDKs, calling hasFingerprintHardware or hasFingerprintsEnrolled will always return false.

License

Copyright 2018-2021 Tailored Media GmbH

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.