Fingerprint Login

Last Updated on : 2025-09-15 06:04:35download

Overview

The fingerprint login SDK is a secure login solution based on the Android Biometric API. It supports fingerprint biometric recognition and provides simple, easy-to-use interfaces, enabling you to quickly integrate biometric login functionality.

How to integrate

Add a dependency

Add the following dependency to your application module file build.gradle:

dependencies {
    implementation 'com.thingclips.smart:thingsmart-biometrics-login:1.0.0'
     // The latest stable App SDK for Android.
    implementation("com.thingclips.smart:thingsmart:6.7.3")
    implementation("androidx.biometric:biometric:1.1.0")
}

Add permissions

Add required permissions in AndroidManifest.xml.

<!-- Biometric permissions -->
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<!-- Network permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

API description

Get an SDK instance

val biometricSDK = ThingBiometricsLoginSDK.getInstance()

Check device support

fun isSupportBiometricLogin(context: Context): Boolean

API description

Check whether the device supports biometric login.

Parameter description

Parameter Description
context The context.

Return value

Return value Description
true The device supports biometric login.
false The device does not support biometric login.

Example

val isSupported = biometricSDK.isSupportBiometricLogin(context)
if (isSupported) {
    // The device supports biometric login, and related features can be enabled.
} else {
    // The device does not support biometric login, and a prompt appears.
}

Check user status

fun isBiometricLoginEnabled(uid: String): Boolean

API description

Check whether the specific user has enabled biometric login.

Parameter description

Parameter Description
uid The unique identifier of the user.

Return value

Return value Description
true The user has enabled biometric login.
false The user has not enabled biometric login.

Example

val isEnabled = biometricSDK.isBiometricLoginEnabled(userId)
if (isEnabled) {
    // Show biometric login options.
} else {
    // Show the guide to enable biometric login.
}

Enable biometric login

fun enableBiometricLogin(
    activity: FragmentActivity,
    uid: String,
    callback: IThingBiometricFingerCallback
)

API description

Enable biometric login for the specified user.

Parameter description

Parameter Description
activity The FragmentActivity instance.
uid The unique identifier of the user.
callback The callback interface that handles authentication results.

Example

biometricSDK.enableBiometricLogin(
    activity = this,
    uid = userId,
    callback = object : IThingBiometricFingerCallback {
        override fun onSuccess(user: User?) {
            // Biometric login was enabled successfully.
            showToast("Biometric login was enabled")
        }

        override fun onError(errorCode: String, errorMsg: String) {
            // Failed to enable biometric login.
            showToast("Failed: $errorMsg")
        }

        override fun onNegative() {
            // User canceled the operation.
            showToast("The enable operation was canceled")
        }

        override fun onFingerInfoInvalid() {
            // Fingerprint information is invalid, and it needs to be set again.
            showToast("Invalid fingerprint info, please set it again")
        }
    }
)

Disable biometric login

fun disableBiometricLogin(uid: String)

API description

Disable biometric login for the specified user.

Parameter description

Parameter Description
uid The unique identifier of the user.

Example

biometricSDK.disableBiometricLogin(userId)
showToast("Biometric login was disabled")

Perform biometric authentication

fun authenticate(
    activity: FragmentActivity,
    uid: String,
    accountName: String,
    countryCode: String,
    callback: IThingBiometricFingerCallback
)

API description

Perform biometric authentication login.

Parameter description

Parameter Description
activity The FragmentActivity instance.
uid The unique identifier of the user.
accountName The account name.
countryCode The country code.
callback The callback interface that handles authentication results.

Example

biometricSDK.authenticate(
    activity = this,
    uid = userId,
    accountName = "user@example.com",
    countryCode = "CN",
    callback = object : IThingBiometricFingerCallback {
        override fun onSuccess(user: User?) {
            // Authentication was successful. Execute login logic.
            performLogin(user)
        }

        override fun onError(errorCode: String, errorMsg: String) {
            // Authentication failed.
            showToast("Authentication failed: $errorMsg")
        }

        override fun onNegative() {
            // User canceled the authentication.
            showToast("Authentication was canceled")
        }

        override fun onFingerInfoInvalid() {
            // Fingerprint information is invalid, and it needs to be enabled again.
            showToast("Fingerprint information has expired, please re-enable biometric login")
        }
    }
)

Check fingerprint changes

fun hasBiometricChanged(uid: String): Boolean

API description

Check whether the user’s fingerprint has changed.

Parameter description

Parameter Description
uid The unique identifier of the user.

Return value

Return value Description
true The fingerprint has changed.
false The fingerprint has not changed.

Example

val hasChanged = biometricSDK.hasBiometricChanged(userId)
if (hasChanged) {
    // The fingerprint has changed. You need to re-enable biometric login.
    showDialog("Fingerprint information has changed. Please re-enable biometric login.")
} else {
    // The fingerprint has not changed. You can use it as expected.
}

Callback interface

IThingBiometricFingerCallback

public interface IThingBiometricFingerCallback {
    /**
     * Biometric operation was successful.
     * @param user User information (returned during authentication, null when enabled)
     */
    void onSuccess(@Nullable User user);

    /**
     * Biometric operation failed.
     * @param errorCode Error code from Android Biometric API (in string format).
     * @param errorMsg Error message provided by the Android system.
     */
    void onError(String errorCode, String errorMsg);

    /**
     * User canceled the operation.
     */
    void onNegative();

    /**
     * Biometric information is invalid.
     * This issue typically occurs when fingerprint changes or key becomes invalid.
     */
    void onFingerInfoInvalid();
}

Example

class BiometricLoginActivity : AppCompatActivity() {
    private lateinit var binding: ActivityBiometricLoginBinding
    private val biometricSDK = ThingBiometricsLoginSDK.getInstance()
    private val testUid = "XXXX"
    private val testAccountName = "XXXX"
    private val testCountryCode = "AZ"

    @RequiresApi(Build.VERSION_CODES.M)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityBiometricLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)

        initToolbar()
        initView()
    }

    private fun initToolbar() {
        supportActionBar?.title = "Biometric Login"
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
    }

    override fun onSupportNavigateUp(): Boolean {
        onBackPressed()
        return true
    }

    @RequiresApi(Build.VERSION_CODES.M)
    private fun initView() {
        // Set user information.
        binding.tvName.text = "Test User"

        // Set anti-repeat click events.
        binding.ivFingerPrint.preventRepeatedClick { fingerLogin() }
        binding.tvFingerPrint.preventRepeatedClick { fingerLogin() }

        // Add a click event for the button to enable biometric login.
        binding.tvEnableBiometric.preventRepeatedClick {
            enableBiometricLogin()
        }

        // Add a click event for the button to disable biometric login.
        binding.tvDisableBiometric.preventRepeatedClick {
            disableBiometricLogin()
        }

        // Check whether the device supports biometric login.
        checkBiometricSupport()
    }

    @RequiresApi(Build.VERSION_CODES.M)
    private fun checkBiometricSupport() {
        if (!biometricSDK.isSupportBiometricLogin(this)) {
            binding.tvEnableBiometric.isEnabled = false
            binding.tvDisableBiometric.isEnabled = false
            binding.ivFingerPrint.isEnabled = false
            binding.tvFingerPrint.isEnabled = false
            Toast.makeText(this, "The device does not support biometric login", Toast.LENGTH_LONG).show()
        }
    }

    @RequiresApi(Build.VERSION_CODES.M)
    private fun fingerLogin() {
        // Check whether the device supports biometric login.
        if (!biometricSDK.isSupportBiometricLogin(this)) {
            showErrorDialog("The device does not support biometric login")
            return
        }
        // Check whether biometric login is enabled.
        if (!biometricSDK.isBiometricLoginEnabled(testUid)) {
            showErrorDialog("Biometric login is not enabled")
            return
        }

        // Check whether the fingerprint has changed.
        if (biometricSDK.hasBiometricChanged(testUid)) {
            showErrorDialog("Fingerprint information has changed, please set it again")
            return
        }


        // Start biometric authentication.
        startBiometricAuthentication()
    }

    private fun disableBiometricLogin() {
        biometricSDK.disableBiometricLogin(testUid)
        Toast.makeText(this, "Biometric login is disabled", Toast.LENGTH_SHORT).show()
    }

    private fun enableBiometricLogin() {
        // Check whether the device supports biometric login.
        if (!biometricSDK.isSupportBiometricLogin(this)) {
            Toast.makeText(this, "The device does not support biometric login", Toast.LENGTH_SHORT).show()
            return
        }

        biometricSDK.enableBiometricLogin(
            this,
            testUid,
            object : IThingBiometricFingerCallback {
                override fun onSuccess(user: User?) {
                    runOnUiThread {
                        Toast.makeText(this@BiometricLoginActivity, "Biometric login is enabled", Toast.LENGTH_SHORT).show()
                    }
                }
                override fun onError(errorCode: String?, errorMsg: String?) {
                    runOnUiThread {
                        if (!TextUtils.isEmpty(errorCode) && !TextUtils.isEmpty(errorMsg)) {
                            when (errorCode) {
                                BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE.toString() -> {
                                    Toast.makeText(this@BiometricLoginActivity, "The device does not support biometric login", Toast.LENGTH_SHORT).show()
                                }
                                BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE.toString() -> {
                                    Toast.makeText(this@BiometricLoginActivity, "Biometric login is currently unavailable", Toast.LENGTH_SHORT).show()
                                }
                                BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED.toString() -> {
                                    Toast.makeText(this@BiometricLoginActivity, "Please enter your biometric information in the system settings first", Toast.LENGTH_LONG).show()
                                }
                                else -> {
                                    Toast.makeText(this@BiometricLoginActivity, errorMsg, Toast.LENGTH_SHORT).show()
                                }
                            }
                        }
                    }
                }

                override fun onNegative() {
                    runOnUiThread {
                        Toast.makeText(this@BiometricLoginActivity, "The user canceled the biometric settings", Toast.LENGTH_SHORT).show()
                    }
                }

                override fun onFingerInfoInvalid() {
                    runOnUiThread {
                        Toast.makeText(this@BiometricLoginActivity, "Invalid fingerprint information, please check the system fingerprint settings", Toast.LENGTH_SHORT).show()
                    }
                }
            }
        )
    }

    private fun startBiometricAuthentication() {
        // Disable all interactions.
        setViewsClickable(false)

        biometricSDK.authenticate(
            this,
            testUid,
            testAccountName,
            testCountryCode,
            object : IThingBiometricFingerCallback {
                override fun onSuccess(user: User?) {
                    runOnUiThread {
                        if (!isFinishing) {
                            // Enable all interactions.
                            setViewsClickable(true)
                            Toast.makeText(this@BiometricLoginActivity, "Biometric login was successful", Toast.LENGTH_SHORT).show()
                            // In practical applications, navigate to the homepage here.
                        }
                    }
                }
                override fun onError(errorCode: String?, errorMsg: String?) {
                    runOnUiThread {
                        // Enable all interactions.
                        setViewsClickable(true)
                        if (!TextUtils.isEmpty(errorCode) && !TextUtils.isEmpty(errorMsg)) {
                            when (errorCode) {
                                BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE.toString() -> {
                                    showErrorDialog("The device does not support biometric login")
                                }
                                BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE.toString() -> {
                                    Toast.makeText(this@BiometricLoginActivity, "Biometric login is currently unavailable", Toast.LENGTH_SHORT).show()
                                }
                                BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED.toString() -> {
                                    Toast.makeText(this@BiometricLoginActivity, "Please enter your biometric information in the system settings first", Toast.LENGTH_LONG).show()
                                }
                                else -> {
                                    Toast.makeText(this@BiometricLoginActivity, errorMsg, Toast.LENGTH_SHORT).show()
                                }
                            }
                        }
                    }
                }

                override fun onNegative() {
                    runOnUiThread {
                        // Enable all interactions.
                        setViewsClickable(true)
                    }
                }

                override fun onFingerInfoInvalid() {
                    runOnUiThread {
                        // Enable all interactions.
                        setViewsClickable(true)
                        // 1. A new fingerprint was added.  2. Fingerprint exists in the system, but the lock screen password is not enabled (fingerprint inactive).
                        Toast.makeText(
                            this@BiometricLoginActivity,
                            "The fingerprint information is invalid, please check the system fingerprint settings.",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                }
            }
        )
    }

    private fun setViewsClickable(clickable: Boolean) {
        binding.ivFingerPrint.isClickable = clickable
        binding.tvFingerPrint.isClickable = clickable
        binding.tvEnableBiometric.isClickable = clickable
        binding.tvDisableBiometric.isClickable = clickable
    }

    private fun showErrorDialog(tips: String) {
        AlertDialog.Builder(this)
            .setTitle("Tips")
            .setMessage(tips)
            .setPositiveButton("Got It") { dialog, _ ->
                dialog.dismiss()
                // In practical applications, navigate to the account and password login page.
                Toast.makeText(this, "Please log in using another method", Toast.LENGTH_SHORT).show()
            }
            .setCancelable(false)
            .show()
    }
}

Error codes

The SDK delivers standard error codes from the Android Biometric API. Common error codes are listed in the table below:

Error code Description Recommended action
BIOMETRIC_ERROR_HW_UNAVAILABLE Biometric hardware is unavailable. Prompt the user to try again later.
BIOMETRIC_ERROR_HW_NOT_PRESENT The device lacks biometric hardware (The fingerprint module is unavailable). Hide the biometric functionality.
BIOMETRIC_ERROR_NONE_ENROLLED User has not set up biometric credentials. Guide the user to set up fingerprints.
BIOMETRIC_ERROR_NO_HARDWARE The device lacks biometric hardware (No fingerprint module exists). Hide the biometric functionality.
BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED A security update is required. Prompt the user to update the system.
BIOMETRIC_ERROR_UNSUPPORTED Unsupported biometric type. Hide related functionality.
BIOMETRIC_ERROR_TIMEOUT Authentication timed out. Prompt the user to try again.
BIOMETRIC_ERROR_UNABLE_TO_PROCESS Unable to process the authentication request. Prompt the user to try again.
BIOMETRIC_ERROR_INSUFFICIENT Insufficient biometric information. Guide the user to reconfigure.
BIOMETRIC_ERROR_LOCKOUT Biometric authentication is locked. Prompt the user to try again later.
BIOMETRIC_ERROR_VENDOR A vendor-specific error occurs. Check specific error message.
BIOMETRIC_ERROR_LOCKOUT_PERMANENT Biometric authentication is permanently locked. It needs to be reset.
BIOMETRIC_ERROR_USER_CANCELED User canceled the operation. Handle it as usual.
BIOMETRIC_ERROR_NO_BIOMETRICS No biometric credentials are available. Guide the user to set up the credentials.
BIOMETRIC_ERROR_HW_NOT_PRESENT Hardware does not exist. Hide the biometric login functionality.

The specific meaning of error codes might vary depending on the Android version and device. It is recommended to handle them accordingly based on the error information.

Best practices

  • Permission check: Always verify device support before using biometric functionality.
  • Network check: Check network connectivity before performing biometric operations.
  • State management: Properly manage the enabled/disabled status of biometric login.
  • Error handling: Implement complete error handling logic with user-friendly prompts.
  • Security considerations: Immediately clear relevant data when biometric information changes.
  • User experience: Provide clear guidance and feedback to avoid user confusion.
  • Offline handling: Develop fallback solutions for when the network is unavailable.

Considerations

  • Android version: Requires Android 6.0 (API 23) or later.
  • Hardware requirements: The device must support biometric hardware.
  • User setup: Users must configure biometric credentials in system settings.
  • Permission declaration: Ensure necessary permissions are declared in AndroidManifest.xml.
    • Biometric permissions:
      • USE_BIOMETRIC
      • USE_FINGERPRINT
    • Network permissions:
      • INTERNET
      • ACCESS_NETWORK_STATE
      • ACCESS_WIFI_STATE
  • Network connection: A stable network connection is required for user authentication and key management.
  • Lifecycle management: Cancel ongoing biometric operations before activity destruction.
  • Thread safety: Callback methods execute on the main thread — ensure proper UI updates.

References

If you encounter any issues, refer to the following resources first: