Start using packagecloud in minutes

Join thousands of developers using packagecloud to distribute software securely, consistently, and affordably.

README

last updated: Thu 03/20/25 at 07:43:20 PM by lucas-yupistudios

BioPass ID Fingerprint SDK Android

Latest Version

March 20, 2025 - [v2.1.4]

Table of Contents

Quick Start Guide

First, you will need a license key to use the SDK. To get your license key contact us through our website BioPass ID.

Check out our official documentation for more in depth information on BioPass ID.

1. Prerequisites:

Attention: To use Fingerprint you will need a physical device, Fingerprint does not work on emulators.

- Java 17 or higher
- Kotlin 1.9.0 or highr
- Gradle 8.6 or higher
- Android Gradle Plugin 8.4.0 or higher
- A physical device with a camera
- License key
- Internet connection is required to verify the license

Before proceeding, you should add the following dependencies in your app/build.gradle file:

dependencies 
    implementation 'com.biopassid:dlibwrapper:1.0.0'
    implementation 'androidx.camera:camera-core:1.3.4'
    implementation 'androidx.camera:camera-camera2:1.3.4'
    implementation 'androidx.camera:camera-lifecycle:1.3.4'
    implementation 'androidx.camera:camera-view:1.3.4'

Then on your settings.gradle file:

repositories 
    maven 
        url "https://packagecloud.io/biopassid/dlibwrapper/maven2"


Change the minimum Android sdk version to 24 (or higher) in your app/build.gradle file.

minSdkVersion 24

2. Installation

With Gradle

The simplest and easiest way to install the plugin to your project, is to just add the following dependencies to your app/build.gradle:

dependencies 
    implementation 'com.biopassid:fingerprintsdk:2.1.4'

Then on your settings.gradle file:

repositories 
    maven 
        url "https://packagecloud.io/biopassid/FingerprintSDKAndroid/maven2"


With Local File

Another alternative to use Fingerprint SDK is to download and install the AAR file locally. Here you can find the latest releases and after downloading place the .aar file in any folder of your choice.

We will use Android Studio for the following steps:

  1. First, with your project open, go to File --> Project Structure --> Dependencies.
  2. Then in the Dependencies tab, select your app in the modules tab and click on the plus symbol to show the option to add a JAR/AAR dependency.
  3. On step 1 input the AAR file path, and select the implementation option on step 2.
  4. Just rebuild your project and should be ready to use.

3. How to use

Basic Example

By now you should have all the tools available to start using the lib in your own project. You can configure some settings like capture type, output type and the number of fingers to capture. You can launch Fingerprint using the View or Activity. Here is a code example showing how to use Fingerprint SDK.

Using View

1. Create the Person data class
package com.example.fingerprintdemo

import android.graphics.Bitmap

object Person 
    var fingers: List<Bitmap> = ArrayList()

2. In xml layout of your main activity
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnCapture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Finger Capture"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
3. In your main activity
package com.example.fingerprintdemo

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() 

    private val TAG = "FingerprintDemo"
    private lateinit var btnCapture: Button

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Button in your xml layout responsible for calling the Fingerprint SDK
        btnCapture = findViewById(R.id.btnCapture)

        // Register ActivityForResult
        val intentLauncher = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        )  result: ActivityResult ->
            if (result.resultCode == RESULT_OK) 
                Log.d(TAG, "Images: $Person.fingers")



        // Start CameraActivity
        btnCapture.setOnClickListener 
            val intent = Intent(this, CameraActivity::class.java)
            intentLauncher.launch(intent)



4. Create a xml layout for camera activity and add FingerprintView to it
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CameraActivity">

    <br.com.biopassid.fingerprintsdk.ui.view.FingerprintView
        android:id="@+id/fingerprintView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:licenseKey="your-license-key"
        app:numberFingersToCapture="4"
        app:textFontFamily="@font/fingerprintsdk_opensans_regular"
        app:overlayColor="#80000000"
        app:timeToCapture="5"
        app:captureCountdownEnabled="true"
        app:captureCountdownBackgroundColor="#50888888"
        app:captureCountdownProgressColor="#D6A262"
        app:captureCountdownTextColor="#FFFFFF"
        app:captureType="leftHandFingers"
        app:outputType="captureAndSegmentation"
        app:fingerEllipseEnabled="true"
        app:fingerEllipseColor="#80D6A262"
        app:distanceIndicatorEnabled="true"
        app:distanceIndicatorSelectedBarColor="#D6A262"
        app:distanceIndicatorUnselectedBarColor="#FFFFFF"
        app:distanceIndicatorArrowColor="#D6A262"
        app:distanceIndicatorTooCloseTextEnabled="true"
        app:distanceIndicatorTooCloseTextContent="Muito perto"
        app:distanceIndicatorTooCloseTextColor="#FFFFFF"
        app:distanceIndicatorTooCloseTextSize="14sp"
        app:distanceIndicatorTooFarTextEnabled="true"
        app:distanceIndicatorTooFarTextContent="Muito longe"
        app:distanceIndicatorTooFarTextColor="#FFFFFF"
        app:distanceIndicatorTooFarTextSize="14sp"
        app:helpTextEnabled="true"
        app:helpTextColor="#FFFFFF"
        app:helpTextSize="14sp"
        app:helpTextLeftHandMessage="Encaixe a mão esquerda (sem o polegar)\naté o marcador ficar centralizado."
        app:helpTextRightHandMessage="Encaixe a mão direita (sem o polegar)\naté o marcador ficar centralizado."
        app:helpTextThumbsMessage="Encaixe os polegares\naté o marcador ficar centralizado."
        app:backButtonEnabled="true"
        app:backButtonBackgroundColor="#00000000"
        app:backButtonPadding="0dp"
        app:backButtonWidth="56dp"
        app:backButtonHeight="56dp"
        app:backButtonIconEnabled="true"
        app:backButtonIconFile="@drawable/fingerprintsdk_ic_close"
        app:backButtonIconColor="#FFFFFF"
        app:backButtonIconWidth="32dp"
        app:backButtonIconHeight="32dp"
        app:backButtonLabelEnabled="false"
        app:backButtonLabelContent="Voltar"
        app:backButtonLabelColor="#FFFFFF"
        app:backButtonLabelSize="14sp" />

</androidx.constraintlayout.widget.ConstraintLayout>
5. Create camera activity
package com.example.fingerprintdemo

import android.graphics.Bitmap
import android.graphics.Rect
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import br.com.biopassid.fingerprintsdk.engine.FingerprintCaptureListener
import br.com.biopassid.fingerprintsdk.engine.FingerprintCaptureState
import br.com.biopassid.fingerprintsdk.ui.view.FingerprintView

class CameraActivity : AppCompatActivity() 

    private val TAG = "FingerprintDemo"
    private lateinit var fingerprintView: FingerprintView

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_camera)

        fingerprintView = findViewById(R.id.fingerprintView)

        // Defines a callback to handle capture events
        fingerprintView.captureListener = object : FingerprintCaptureListener 
            override fun onFingerCapture(images: List<Bitmap>, error: String?) 
                if (error != null) 
                    Log.d(TAG, "onFingerCapture error: $error")

                Person.fingers = images
                setResult(RESULT_OK)
                finish()


            override fun onFingerDetected(fingerRects: List<Rect>) 
                Log.d(TAG, "onFingerDetected: $fingerRects")


            override fun onStatusChanged(state: FingerprintCaptureState) 
                Log.d(TAG, "onStatusChanged: $state")



        // Initializes fingerprint capture
        fingerprintView.start()


Using only Activity

1. In xml layout of your main activity
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnCapture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Finger Capture"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
2. In your main activity
package com.example.fingerprintdemo

import android.graphics.Bitmap
import android.graphics.Rect
import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import br.com.biopassid.fingerprintsdk.Fingerprint
import br.com.biopassid.fingerprintsdk.config.FingerprintConfig
import br.com.biopassid.fingerprintsdk.engine.FingerprintCaptureListener
import br.com.biopassid.fingerprintsdk.engine.FingerprintCaptureState

class MainActivity : AppCompatActivity() 

    private val TAG = "FingerprintDemo"
    private lateinit var btnCapture: Button

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Button in your xml layout responsible for calling the Fingerprint SDK
        btnCapture = findViewById(R.id.btnCapture)

        // Instantiates Fingerprint config by passing your license key
        val config = FingerprintConfig(licenseKey = "your-license-key")

        // Defines a callback to handle capture events
        val callback = object : FingerprintCaptureListener 
            override fun onFingerCapture(images: List<Bitmap>, error: String?) 
                Log.d(TAG, "onFingerCapture: $error ?: images")


            override fun onFingerDetected(fingerRects: List<Rect>) 
                Log.d(TAG, "onFingerDetected: $fingerRects")


            override fun onStatusChanged(state: FingerprintCaptureState) 
                Log.d(TAG, "onStatusChanged: $state")



        // Initializes fingerprint capture
        btnCapture.setOnClickListener 
            Fingerprint.takeFingerprint(this, config, callback)



Example using Retrofit to call the BioPass ID API

For this example we used the Enroll from the Multibiometrics plan and Retrofit to make http requests.

First, add the Retrofit package. To install the Retrofit package, add it to the dependencies section of the app/build.gradle file.

dependencies 
    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'

Additionally, in your AndroidManifest.xml file, add the permissions.

<!-- Required to fetch data from the internet. -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- Required to save images to gallery. -->
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28" />

EnrollPersonRequest

Create the EnrollPersonRequest data class:

package com.example.fingerprintdemo

import com.google.gson.annotations.SerializedName

data class FingerPersonRequest(
    @SerializedName("Finger-1") val finger1: String? = null,
    @SerializedName("Finger-2") val finger2: String? = null,
    @SerializedName("Finger-3") val finger3: String? = null,
    @SerializedName("Finger-4") val finger4: String? = null,
    @SerializedName("Finger-5") val finger5: String? = null,
    @SerializedName("Finger-6") val finger6: String? = null,
    @SerializedName("Finger-7") val finger7: String? = null,
    @SerializedName("Finger-8") val finger8: String? = null,
    @SerializedName("Finger-9") val finger9: String? = null,
    @SerializedName("Finger-10") val finger10: String? = null,
)

data class PersonRequest(
    @SerializedName("CustomID") val customID: String,
    @SerializedName("Fingers") val fingers: List<FingerPersonRequest>
)

data class EnrollPersonRequest(
    @SerializedName("Person") val person: PersonRequest
)

EnrollPersonResponse

Create the EnrollPersonResponse data class:

package com.example.fingerprintdemo

import com.google.gson.annotations.SerializedName

data class PersonResponse(
    @SerializedName("ClientID") val clientID: String,
    @SerializedName("CustomID") val customID: String,
    @SerializedName("BioPassID") val bioPassID: String
)

data class EnrollPersonResponse(
    @SerializedName("Person") val person: PersonResponse,
    @SerializedName("Message") val message: String
)

BioPassIDApi

Here, you will need an API key to be able to make requests to the BioPass ID API. To get your API key contact us through our website BioPass ID.

Create the BioPassIDApi interface to make requests to the BioPass ID API:

package com.example.fingerprintdemo

import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST

interface BioPassIDApi 
    @Headers("Content-Type: application/json", "Ocp-Apim-Subscription-Key: your-api-key")
    @POST("multibiometrics/enroll")
    fun enrollPerson(@Body enrollPersonRequest: EnrollPersonRequest) : Call<EnrollPersonResponse>

Network

Create the Network class to make requests to the BioPass ID API:

package com.example.fingerprintdemo

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class Network 
    companion object 

        /** Returns a Client Retrofit Instance for Requests
         */
        fun getRetrofitInstance() : BioPassIDApi 
            return Retrofit.Builder()
                .baseUrl("https://api.biopassid.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(BioPassIDApi::class.java)



MediaStoreUtils

Create the MediaStoreUtils class to save images to gallery:

package com.example.fingerprintdemo

import android.content.ContentValues
import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
import java.text.SimpleDateFormat
import java.util.Locale

object MediaStoreUtils 
    fun saveImage(context: Context, bitmap: Bitmap) 
        val folderName = "Fingerprint"
        val date = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US)
            .format(System.currentTimeMillis())
        val fileName = "fingerprint_$date.png"
        val values = contentValues(bitmap.width, bitmap.height)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
            values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
            values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/$folderName")
            values.put(MediaStore.Images.Media.IS_PENDING, true)
            val uri: Uri? = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
            if (uri != null) 
                try 
                    saveImageToStream(bitmap, context.contentResolver.openOutputStream(uri))
                    values.put(MediaStore.Images.Media.IS_PENDING, false)
                    context.contentResolver.update(uri, values, null, null)
                 catch (e: Exception) 
                    e.printStackTrace()


         else 
            val directory = File("$Environment.getExternalStorageDirectory()/Pictures/$folderName")
            if (!directory.exists()) 
                directory.mkdirs()

            val file = File(directory, fileName)
            try 
                saveImageToStream(bitmap, FileOutputStream(file))
                values.put(MediaStore.Images.Media.DATA, file.absolutePath)
                context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
             catch (e: Exception) 
                e.printStackTrace()




    private fun contentValues(width: Int, height: Int) : ContentValues 
        val values = ContentValues()
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/png")
        values.put(MediaStore.Images.Media.WIDTH, width)
        values.put(MediaStore.Images.Media.HEIGHT, height)
        values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000)
        values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
        return values


    private fun saveImageToStream(bitmap: Bitmap, outputStream: OutputStream?) 
        if (outputStream != null) 
            try 
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
                outputStream.close()
             catch (e: Exception) 
                e.printStackTrace()




Using View

1. Create the AppConfig data class
package com.example.fingerprintdemo

import android.graphics.Bitmap
import br.com.biopassid.fingerprintsdk.config.FingerprintConfig

object AppConfig 
    var config = FingerprintConfig()
    var rightHandImages: List<Bitmap> = ArrayList()
    var leftHandImages: List<Bitmap> = ArrayList()
    var thumbsImages: List<Bitmap> = ArrayList()

2. In xml layout of your main activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnCaptureRightHand"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="Capture Right Hand" />

    <Button
        android:id="@+id/btnCaptureLeftHand"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="Capture Left Hand" />

    <Button
        android:id="@+id/btnCaptureThumbs"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="Capture Thumbs" />

</LinearLayout>
3. In your main activity
package com.example.fingerprintdemo

import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.util.Base64
import android.util.Log
import android.widget.Button
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import br.com.biopassid.fingerprintsdk.config.enums.FingerprintCaptureType
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.ByteArrayOutputStream
import java.io.IOException

class MainActivity : AppCompatActivity() 

    private val writePermission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE
    private var writePermissionGranted = false
    private lateinit var permissionsLauncher: ActivityResultLauncher<Array<String>>

    private lateinit var btnCaptureRightHand: Button
    private lateinit var btnCaptureLeftHand: Button
    private lateinit var btnCaptureThumbs: Button

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        permissionsLauncher =
            registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions())  permissions ->
                writePermissionGranted = permissions[writePermission] ?: writePermissionGranted

        updateOrRequestPermissions()

        // Button in your xml layout responsible for calling the Fingerprint SDK
        btnCaptureRightHand = findViewById(R.id.btnCaptureRightHand)
        btnCaptureLeftHand = findViewById(R.id.btnCaptureLeftHand)
        btnCaptureThumbs = findViewById(R.id.btnCaptureThumbs)

        // Set your license key
        AppConfig.config.licenseKey = "your-license-key"

        // Register ActivityForResult
        val intentLauncher = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        )  result: ActivityResult ->
            if (result.resultCode == RESULT_OK) 
                var rightThumb: String? = null
                var rightIndex: String? = null
                var rightMiddle: String? = null
                var rightRing: String? = null
                var rightLittle: String? = null
                var leftThumb: String? = null
                var leftIndex: String? = null
                var leftMiddle: String? = null
                var leftRing: String? = null
                var leftLittle: String? = null

                if (AppConfig.rightHandImages.isNotEmpty()) 
                    // Save images to gallery
                    AppConfig.rightHandImages.forEach  image ->
                        MediaStoreUtils.saveImage(this@MainActivity, image)


                    // Encode Bitmap to base64 string
                    rightLittle = bitmapToBas64(AppConfig.rightHandImages[1])
                    rightRing = bitmapToBas64(AppConfig.rightHandImages[2])
                    rightMiddle = bitmapToBas64(AppConfig.rightHandImages[3])
                    rightIndex = bitmapToBas64(AppConfig.rightHandImages[4])


                if (AppConfig.leftHandImages.isNotEmpty()) 
                    // Save images to gallery
                    AppConfig.leftHandImages.forEach  image ->
                        MediaStoreUtils.saveImage(this@MainActivity, image)


                    // Encode Bitmap to base64 string
                    leftLittle = bitmapToBas64(AppConfig.leftHandImages[1])
                    leftRing = bitmapToBas64(AppConfig.leftHandImages[2])
                    leftMiddle = bitmapToBas64(AppConfig.leftHandImages[3])
                    leftIndex = bitmapToBas64(AppConfig.leftHandImages[4])


                if (AppConfig.thumbsImages.isNotEmpty()) 
                    // Save images to gallery
                    AppConfig.thumbsImages.forEach  image ->
                        MediaStoreUtils.saveImage(this@MainActivity, image)


                    // Encode Bitmap to base64 string
                    leftThumb = bitmapToBas64(AppConfig.thumbsImages[1])
                    rightThumb = bitmapToBas64(AppConfig.thumbsImages[2])


                // Send images to API
                sendImages(
                    rightThumb = rightThumb,
                    rightIndex = rightIndex,
                    rightMiddle = rightMiddle,
                    rightRing = rightRing,
                    rightLittle = rightLittle,
                    leftThumb = leftThumb,
                    leftIndex = leftIndex,
                    leftMiddle = leftMiddle,
                    leftRing = leftRing,
                    leftLittle = leftLittle
                )



        // Start right hand capture
        btnCaptureRightHand.setOnClickListener 
            AppConfig.config.captureType = FingerprintCaptureType.RIGHT_HAND_FINGERS
            val intent = Intent(this, CameraActivity::class.java)
            intentLauncher.launch(intent)


        // Start left hand capture
        btnCaptureLeftHand.setOnClickListener 
            AppConfig.config.captureType = FingerprintCaptureType.LEFT_HAND_FINGERS
            val intent = Intent(this, CameraActivity::class.java)
            intentLauncher.launch(intent)


        // Start thumbs capture
        btnCaptureThumbs.setOnClickListener 
            AppConfig.config.captureType = FingerprintCaptureType.THUMBS
            val intent = Intent(this, CameraActivity::class.java)
            intentLauncher.launch(intent)



    // Helper method used to send images to API
    private fun sendImages(
        rightThumb: String? = null,
        rightIndex: String? = null,
        rightMiddle: String? = null,
        rightRing: String? = null,
        rightLittle: String? = null,
        leftThumb: String? = null,
        leftIndex: String? = null,
        leftMiddle: String? = null,
        leftRing: String? = null,
        leftLittle: String? = null
    ) 
        // Instantiate Enroll request
        val enrollPersonRequest = EnrollPersonRequest(
            PersonRequest(
                "your-customID",
                listOf(
                    FingerPersonRequest(
                        finger1 = rightThumb,
                        finger2 = rightIndex,
                        finger3 = rightMiddle,
                        finger4 = rightRing,
                        finger5 = rightLittle,
                        finger6 = leftThumb,
                        finger7 = leftIndex,
                        finger8 = leftMiddle,
                        finger9 = leftRing,
                        finger10 = leftLittle
                    )
                )
            )
        )

        // Get retrofit
        val retrofit = Network.getRetrofitInstance()

        // Execute request to the BioPass ID API
        val callback: Call<EnrollPersonResponse> =
            retrofit.enrollPerson(enrollPersonRequest)

        // Handle API response
        callback.enqueue(object : Callback<EnrollPersonResponse?> 
            override fun onResponse(
                call: Call<EnrollPersonResponse?>,
                response: Response<EnrollPersonResponse?>
            ) 
                Log.d(TAG, "code: $response.code()")
                if (response.isSuccessful) 
                    Log.d(TAG, "body: $response.body()")
                 else 
                    Log.d(TAG, "message: $response.message()")



            override fun onFailure(call: Call<EnrollPersonResponse?>, t: Throwable) 
                Log.e(TAG, "Error trying to call enroll person. ", t)

        )


    // Helper method used to convert Bitmap to Base64
    private fun bitmapToBas64(bitmap: Bitmap): String 
        val stream = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)
        val byteArray = stream.toByteArray()
        try 
            stream.close()
         catch (e: IOException) 
            e.printStackTrace()

        return Base64.encodeToString(byteArray, Base64.NO_WRAP)


    // Helper method used to request permissions
    private fun updateOrRequestPermissions() 
        val hasWritePermission = ContextCompat.checkSelfPermission(
            this,
            writePermission
        ) == PackageManager.PERMISSION_GRANTED
        val isMinSdk29 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q

        writePermissionGranted = hasWritePermission || isMinSdk29

        val permissionsToRequest = mutableListOf<String>()
        if (!writePermissionGranted) 
            permissionsToRequest.add(writePermission)

        if (permissionsToRequest.isNotEmpty()) 
            permissionsLauncher.launch(permissionsToRequest.toTypedArray())



    companion object 
        private const val TAG = "FingerprintDemo"


4. Create a xml layout for camera activity and add FingerprintView to it
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CameraActivity">

    <br.com.biopassid.fingerprintsdk.ui.view.FingerprintView
        android:id="@+id/fingerprintView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
5. Create camera activity
package com.example.fingerprintdemo

import android.graphics.Bitmap
import android.graphics.Rect
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import br.com.biopassid.fingerprintsdk.config.enums.FingerprintCaptureType
import br.com.biopassid.fingerprintsdk.engine.FingerprintCaptureListener
import br.com.biopassid.fingerprintsdk.engine.FingerprintCaptureState
import br.com.biopassid.fingerprintsdk.ui.view.FingerprintView

class CameraActivity : AppCompatActivity() 

    private lateinit var fingerprintView: FingerprintView

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_camera)

        fingerprintView = findViewById(R.id.fingerprintView)

        fingerprintView.config = AppConfig.config

        // Defines a callback to handle capture events
        fingerprintView.captureListener = object : FingerprintCaptureListener 
            override fun onFingerCapture(images: List<Bitmap>, error: String?) 
                Log.d(TAG, "onFingerCapture: $error ?: images")
                AppConfig.rightHandImages.clear()
                AppConfig.leftHandImages.clear()
                AppConfig.thumbsImages.clear()
                when (AppConfig.config.captureType) 
                    FingerprintCaptureType.RIGHT_HAND_FINGERS -> AppConfig.rightHandImages.addAll(images)
                    FingerprintCaptureType.LEFT_HAND_FINGERS -> AppConfig.leftHandImages.addAll(images)
                    else -> AppConfig.thumbsImages.addAll(images)

                setResult(RESULT_OK)
                finish()


            override fun onFingerDetected(fingerRects: List<Rect>) 
                Log.d(TAG, "onFingerDetected: $fingerRects")


            override fun onStatusChanged(state: FingerprintCaptureState) 
                Log.d(TAG, "onStatusChanged: $state")



        // Initializes fingerprint capture
        fingerprintView.start()


    companion object 
        private const val TAG = "FingerprintDemo"


Using only Activity

1. In xml layout of your main activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnCaptureRightHand"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="Capture Right Hand" />

    <Button
        android:id="@+id/btnCaptureLeftHand"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="Capture Left Hand" />

    <Button
        android:id="@+id/btnCaptureThumbs"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:text="Capture Thumbs" />

</LinearLayout>
2. In your main activity
package com.example.fingerprintdemo

import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.util.Base64
import android.util.Log
import android.widget.Button
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import br.com.biopassid.fingerprintsdk.Fingerprint
import br.com.biopassid.fingerprintsdk.config.FingerprintConfig
import br.com.biopassid.fingerprintsdk.config.enums.FingerprintCaptureType
import br.com.biopassid.fingerprintsdk.engine.FingerprintCaptureListener
import br.com.biopassid.fingerprintsdk.engine.FingerprintCaptureState
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.ByteArrayOutputStream
import java.io.IOException

class MainActivity : AppCompatActivity() 

    private val writePermission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE
    private var writePermissionGranted = false
    private lateinit var permissionsLauncher: ActivityResultLauncher<Array<String>>

    private lateinit var btnCaptureRightHand: Button
    private lateinit var btnCaptureLeftHand: Button
    private lateinit var btnCaptureThumbs: Button

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        permissionsLauncher =
            registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions())  permissions ->
                writePermissionGranted = permissions[writePermission] ?: writePermissionGranted

        updateOrRequestPermissions()

        // Button in your xml layout responsible for calling the Fingerprint SDK
        btnCaptureRightHand = findViewById(R.id.btnCaptureRightHand)
        btnCaptureLeftHand = findViewById(R.id.btnCaptureLeftHand)
        btnCaptureThumbs = findViewById(R.id.btnCaptureThumbs)

        // Instantiates Fingerprint config by passing your license key
        val config = FingerprintConfig(licenseKey = "your-license-key")

        // Initializes fingerprint capture
        btnCaptureRightHand.setOnClickListener 
            config.captureType = FingerprintCaptureType.RIGHT_HAND_FINGERS
            Fingerprint.takeFingerprint(this, config, object : FingerprintCaptureListener 
                override fun onFingerCapture(images: List<Bitmap>, error: String?) 
                    if (images.isNotEmpty()) 
                        // Save images to gallery
                        images.forEach  image ->
                            MediaStoreUtils.saveImage(this@MainActivity, image)


                        // Encode Bitmap to base64 string
                        val rightLittle = bitmapToBas64(images[1])
                        val rightRing = bitmapToBas64(images[2])
                        val rightMiddle = bitmapToBas64(images[3])
                        val rightIndex = bitmapToBas64(images[4])

                        // Send images to API
                        sendImages(
                            rightIndex = rightIndex,
                            rightMiddle = rightMiddle,
                            rightRing = rightRing,
                            rightLittle = rightLittle
                        )



                override fun onFingerDetected(fingerRects: List<Rect>) 

                override fun onStatusChanged(state: FingerprintCaptureState) 
            )


        btnCaptureLeftHand.setOnClickListener 
            config.captureType = FingerprintCaptureType.LEFT_HAND_FINGERS
            Fingerprint.takeFingerprint(this, config, object : FingerprintCaptureListener 
                override fun onFingerCapture(images: List<Bitmap>, error: String?) 
                    if (images.isNotEmpty()) 
                        // Save images to gallery
                        images.forEach  image ->
                            MediaStoreUtils.saveImage(this@MainActivity, image)


                        // Encode Bitmap to base64 string
                        val leftLittle = bitmapToBas64(images[1])
                        val leftRing = bitmapToBas64(images[2])
                        val leftMiddle = bitmapToBas64(images[3])
                        val leftIndex = bitmapToBas64(images[4])

                        // Send images to API
                        sendImages(
                            leftIndex = leftIndex,
                            leftMiddle = leftMiddle,
                            leftRing = leftRing,
                            leftLittle = leftLittle
                        )



                override fun onFingerDetected(fingerRects: List<Rect>) 

                override fun onStatusChanged(state: FingerprintCaptureState) 
            )


        btnCaptureThumbs.setOnClickListener 
            config.captureType = FingerprintCaptureType.THUMBS
            Fingerprint.takeFingerprint(this, config, object : FingerprintCaptureListener 
                override fun onFingerCapture(images: List<Bitmap>, error: String?) 
                    if (images.isNotEmpty()) 
                        // Save images to gallery
                        images.forEach  image ->
                            MediaStoreUtils.saveImage(this@MainActivity, image)


                        // Encode Bitmap to base64 string
                        val leftThumb = bitmapToBas64(images[1])
                        val rightThumb = bitmapToBas64(images[2])

                        // Send images to API
                        sendImages(rightThumb = rightThumb, leftThumb = leftThumb)



                override fun onFingerDetected(fingerRects: List<Rect>) 

                override fun onStatusChanged(state: FingerprintCaptureState) 
            )



    // Helper method used to send images to API
    private fun sendImages(
        rightThumb: String? = null,
        rightIndex: String? = null,
        rightMiddle: String? = null,
        rightRing: String? = null,
        rightLittle: String? = null,
        leftThumb: String? = null,
        leftIndex: String? = null,
        leftMiddle: String? = null,
        leftRing: String? = null,
        leftLittle: String? = null
    ) 
        // Instantiate Enroll request
        val enrollPersonRequest = EnrollPersonRequest(
            PersonRequest(
                "your-customID",
                listOf(
                    FingerPersonRequest(
                        finger1 = rightThumb,
                        finger2 = rightIndex,
                        finger3 = rightMiddle,
                        finger4 = rightRing,
                        finger5 = rightLittle,
                        finger6 = leftThumb,
                        finger7 = leftIndex,
                        finger8 = leftMiddle,
                        finger9 = leftRing,
                        finger10 = leftLittle
                    )
                )
            )
        )

        // Get retrofit
        val retrofit = Network.getRetrofitInstance()

        // Execute request to the BioPass ID API
        val callback: Call<EnrollPersonResponse> =
            retrofit.enrollPerson(enrollPersonRequest)

        // Handle API response
        callback.enqueue(object : Callback<EnrollPersonResponse?> 
            override fun onResponse(
                call: Call<EnrollPersonResponse?>,
                response: Response<EnrollPersonResponse?>
            ) 
                Log.d(TAG, "code: $response.code()")
                if (response.isSuccessful) 
                    Log.d(TAG, "body: $response.body()")
                 else 
                    Log.d(TAG, "message: $response.message()")



            override fun onFailure(call: Call<EnrollPersonResponse?>, t: Throwable) 
                Log.e(TAG, "Error trying to call enroll person. ", t)

        )


    // Helper method used to convert Bitmap to Base64
    private fun bitmapToBas64(bitmap: Bitmap): String 
        val stream = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)
        val byteArray = stream.toByteArray()
        try 
            stream.close()
         catch (e: IOException) 
            e.printStackTrace()

        return Base64.encodeToString(byteArray, Base64.NO_WRAP)


    // Helper method used to request permissions
    private fun updateOrRequestPermissions() 
        val hasWritePermission = ContextCompat.checkSelfPermission(
            this,
            writePermission
        ) == PackageManager.PERMISSION_GRANTED
        val isMinSdk29 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q

        writePermissionGranted = hasWritePermission || isMinSdk29

        val permissionsToRequest = mutableListOf<String>()
        if (!writePermissionGranted) 
            permissionsToRequest.add(writePermission)

        if (permissionsToRequest.isNotEmpty()) 
            permissionsLauncher.launch(permissionsToRequest.toTypedArray())



    companion object 
        private const val TAG = "FingerprintDemo"


4. FingerprintCaptureListener

You can set a custom listener to receive captured fingers as well as finger rectangles and monitor the current capture status, among other features. You can write you own listener following this example:

val listener = object : FingerprintCaptureListener 
    override fun onFingerCapture(images: List<Bitmap>, error: String?) 
        // monitor and handle fingers capture
        if (error != null) 
            Log.d("onFingerCapture", "Capture Error: $error")
         else 
            Log.d("onFingerCapture", "Capture: $images[0]")



    override fun onFingerDetected(fingerRects: List<Rect>) 
        // monitor and handle the current state of the capture


    override fun onStatusChanged(state: FingerprintCaptureState) 
        // monitor and handle finger rects


FingerprintCaptureState (enum)

| Name                                    |
| --------------------------------------- |
| FingerprintCaptureState.NO_DETECTION    |
| FingerprintCaptureState.MISSING_FINGERS |
| FingerprintCaptureState.TOO_CLOSE       |
| FingerprintCaptureState.TOO_FAR         |
| FingerprintCaptureState.OK              |
| FingerprintCaptureState.STOPPED         |
| FingerprintCaptureState.PROCESSING      |
| FingerprintCaptureState.MODEL_NOT_FOUND |

5. LicenseKey

First, you will need a license key to use the SDK. To get your license key contact us through our website BioPass ID.

To use BioPass ID Fingerprint you need a license key. To set the license key needed is simple as setting another attribute. Simply doing:

<br.com.biopassid.fingerprintsdk.ui.view.FingerprintView
    android:id="@+id/fingerprintView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:licenseKey="your-license-key" />

Configs

FingerprintConfig

| Variable name          | Type                                | Default value                                  |
| ---------------------- | ----------------------------------- | ---------------------------------------------- |
| licenseKey             | String                              | ""                                             |
| numberFingersToCapture | Int                                 | 4                                              |
| fontFamily             | Int                                 | R.font.fingerprintsdk_opensans_regular         |
| overlayColor           | Int                                 | Color.parseColor("#80000000")                  |
| timeToCapture          | Int                                 | 5                                              |
| captureType            | FingerprintCaptureType              | FingerprintCaptureType.LEFT_HAND_FINGERS       |
| outputType             | FingerprintOutputType               | FingerprintOutputType.CAPTURE_AND_SEGMENTATION |
| captureCountdown       | FingerprintCaptureCountdownOptions  |                                                |
| backButton             | FingerprintButtonOptions            |                                                |
| helpText               | FingerprintHelpTextOptions          |                                                |
| fingerEllipse          | FingerprintFingerEllipseOptions     |                                                |
| distanceIndicator      | FingerprintDistanceIndicatorOptions |                                                |

FingerprintCaptureType (enum)

| Name                                      |
| ----------------------------------------- |
| FingerprintCaptureType.RIGHT_HAND_FINGERS |
| FingerprintCaptureType.LEFT_HAND_FINGERS  |
| FingerprintCaptureType.THUMBS             |

FingerprintOutputType (enum)

| Name                                           |
| ---------------------------------------------- |
| FingerprintOutputType.ONLY_CAPTURE             |
| FingerprintOutputType.CAPTURE_AND_SEGMENTATION |

FingerprintCaptureCountdownOptions

| Name            | Type    | Default value               |
| --------------- | ------- | --------------------------- |
| enabled         | Boolean | true                        |
| backgroundColor | Int     | Color.GRAY                  |
| progressColor   | Int     | Color.parseColor("#D6A262") |
| textColor       | Int     | Color.WHITE                 |

FingerprintButtonOptions

| Name            | Type                   | Default value            |
| --------------- | ---------------------- | ------------------------ |
| enabled         | Boolean                | true                     |
| backgroundColor | Int                    | Color.TRANSPARENT        |
| buttonPadding   | Int                    | 0                        |
| buttonSize      | Size                   | Size(56, 56)             |
| iconOptions     | FingerprintIconOptions | FingerprintIconOptions() |
| labelOptions    | FingerprintTextOptions | FingerprintTextOptions() |

FingerprintIconOptions

| Name      | Type    | Default value                      |
| --------- | ------- | ---------------------------------- |
| enabled   | Boolean | true                               |
| iconFile  | Int     | R.drawable.fingerprintsdk_ic_close |
| iconColor | Int     | Color.WHITE                        |
| iconSize  | Size    | Size(32, 32)                       |

FingerprintTextOptions

| Name      | Type    | Default value |
| --------- | ------- | ------------- |
| enabled   | Boolean | true          |
| content   | String  | ""            |
| textColor | Int     | Color.WHITE   |
| textSize  | Int     | 14            |

FingerprintHelpTextOptions

| Name      | Type                        | Default value                 |
| --------- | --------------------------- | ----------------------------- |
| enabled   | Boolean                     | true                          |
| messages  | FingerprintHelpTextMessages | FingerprintHelpTextMessages() |
| textColor | Int                         | Color.WHITE                   |
| textSize  | Int                         | 14                            |

FingerprintHelpTextMessages

| Name             | Type   | Default value                                                               |
| ---------------- | ------ | --------------------------------------------------------------------------- |
| leftHandMessage  | String | "Encaixe a mão esquerda (sem o polegar)\naté o marcador ficar centralizado" |
| rightHandMessage | String | "Encaixe a mão direita (sem o polegar)\naté o marcador ficar centralizado"  |
| thumbsMessage    | String | "Encaixe os polegares\naté o marcador ficar centralizado."                  |

FingerprintFingerEllipseOptions

| Name         | Type    | Default value                 |
| ------------ | ------- | ----------------------------- |
| enabled      | Boolean | true                          |
| ellipseColor | Int     | Color.parseColor("#80D6A262") |

FingerprintDistanceIndicatorOptions

| Name               | Type                   | Default value                                   |
| ------------------ | ---------------------- | ----------------------------------------------- |
| enabled            | Boolean                | true                                            |
| selectedBarColor   | Int                    | Color.parseColor("#D6A262")                     |
| unselectedBarColor | Int                    | Color.WHITE                                     |
| arrowColor         | Int                    | Color.parseColor("#D6A262")                     |
| tooCloseText       | FingerprintTextOptions | FingerprintTextOptions(content = "Muito perto") |
| tooFarText         | FingerprintTextOptions | FingerprintTextOptions(content = "Muito longe") |

How to change font family

You can use the default font family or set one of your own. To set a font family, create a font folder under res directory. Download the font which ever you want and paste it inside font folder. All font names must be only: lowercase a-z, 0-9, or underscore. The structure should be some thing like below.

Then, just set the font family passing the reference of the font family file.

<br.com.biopassid.fingerprintsdk.ui.view.FingerprintView
    android:id="@+id/fingerprintView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:licenseKey="your-license-key"
    app:textFontFamily="@font/roboto_mono_bold_italic" />

How to change icon

You can use the default icons or define one of your own. To set a icon, download the icon which ever you want and paste it inside drawable folder. The structure should be some thing like below.

Then, just set the icon passing the reference of the icon file.

<br.com.biopassid.fingerprintsdk.ui.view.FingerprintView
    android:id="@+id/fingerprintView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:licenseKey="your-license-key"
    app:backButtonIconFile="@drawable/ic_baseline_photo_camera" />

Changelog

2.1.4

  • Documentation update;
  • Fixed crash error caused by OpenCV resize function.

2.1.3

  • Documentation update.
  • Refactor exposure compensation handling;
  • Add distorted image correction on Moto E7.

2.1.2

  • Documentation update;
  • Fixed validation of number of fingers in FingerprintView.

2.1.1

  • Documentation update;
  • Dlib has been removed and wrapped in an external lib to avoid conflicts with other BioPasss ID SDKs. Now the dlib wrapper is a dependency, see prerequisites section.

2.1.0

  • Documentation update;
  • Changed the minimum Android sdk version from 23 to 24;
  • Removed dependency on Mobile Vision, see prerequisites section;
  • Upgrade from Camera2 to CameraX, see prerequisites section;
  • Improvement in the fluidity of the distance indicator;
  • Added continuous autofocus;
  • Added new time to capture functionality;
  • Added countdown view.

2.0.2

  • Documentation update;
  • Changed the minimum Android sdk version from 21 to 23;
  • Upgrade to Gradle 8.6, see prerequisites section;
  • Upgrade to Android Gradle Plugin 8.4.0, see prerequisites section;
  • Upgrade to Java 17, see prerequisites section;
  • Upgrade to Kotlin 1.9.0, see prerequisites section.

2.0.1

  • Documentation update;
  • Bug fixes.

2.0.0

  • Documentation update;
  • All code rewritten using Kotlin as standard and no longer Java;
  • Updated Gradle Version to 7.5 and Android Gradle Plugin Version to 7.4.2;
  • Updated camera API to Camera2;
  • FingerprintConfig refactoring:
    • Removed showFingerEllipseView and fingerColor, they are now in a new configuration class called FingerprintFingerEllipseOptions;
    • Removed showDistanceIndicatorView, distanceIndicatorLineColor, distanceIndicatorHighlightColor, tooCloseText and tooFarText, now they are in a new configuration class called FingerprintDistanceIndicatorOptions.
  • Now, in order for the SDK to be initialized, it is necessary to call the start method of FingerprintView.
Quick install instructions for: