Capture SDK Guide 

The purpose of the Integration Guide is to give developers everything they need to set up and work with a minimally viable application using the Capture SDK.

Introduction 

The Capture SDK (sometimes seen as Morpho Bio SDK in older documentation or code pieces) is targeted to developers who want to use IDEMIA technologies within their mobile apps.

The main features are:

  • Biometric captures
  • Biometric coding
  • Biometric authentication and identification
  • Identity documents reading

Adding the SDK to your project 

Gradle

Configure repository:

XML
1buildscript {
2 repositories {
3 maven {
4 url "$repositoryUrlMI"
5 credentials {
6 username "$artifactoryUserMI"
7 password "$artifactoryPasswordMI"
8 }
9 }
10 ...
11 }
12 ...
13}

repositoryUrlMI: Mobile Identity artifactory repository url

artifactoryUserMI: Mobile Identity artifactory username

artifactoryPasswordMI: Mobile Identity artifactory password

These properties can be obtained through portal and should be stored in local gradle.properties file. In such case credentials will not be included in source code. Configuration of properties:

XML
1artifactoryUserMI=artifactory_user
2artifactoryPasswordMI=artifactory_credentials
3repositoryUrlMI=https://mi-artifactory.otlabs.fr/artifactory/smartsdk-android-local

More about gradle properties can be found here.

For biometric features the dependency is:

Groovy
1implementation ("morpho.mph_bio_sdk.android:SmartBio:version")

For document features the dependency is:

Groovy
1implementation ("morpho.mph_bio_sdk.android:SmartDoc:version")

For all features the dependency is:

Groovy
1implementation ("morpho.mph_bio_sdk.android:SmartSDK:version")

Version: artifact version

Components

The SDK comprises six distinct components:

  1. BioCaptureHandler: Handles the capture of the biometrics through the camera of the device.
  2. BioMatcherHandler: Handles the biometric coding and matching.
  3. DocumentCaptureHandler: Handles the document reading features (like reading MRZ documents).
  4. BioStoreDB: Repository to store biometric templates. (This component is optional, in case you don't want to implement your own database.)
  5. ImageUtils: Handles the image format conversion, in case the integrator must change the image format or import an image.
  6. LicenseManager: Handles the license management. Refer to License Manager for more details.

Access to BioCaptureHandler, BioMatcherHandler and DocumentCaptureHandler is through the Biometric Capture SDK entry points. To learn how to use DocumentCaptureHandler, refer to the DocumentCaptureHandler section for more details.

Design considerations 

  • User permissions must be handled by the integrator. You must check that the app permissions are granted by the user if the Android version is higher than 23 (as detailed here).

  • Remember: You must always have a valid license before using any method of this SDK. You can activate it through LicenseManager. Refer to License Manager for more details.

  • Note: If your app is to run in low memory devices, you must add android:largeHeap="true" to your application.

  • If you find that your project requires other native libraries, you must add in your gradle.properties file the following filter:

XML
1android.useDeprecatedNdk=true

And in your build.gradle add filters for the desired ABI. For now, the SDK supports armeabi-v7a and arm64-v8a:

XML
1defaultConfig {
2 ....
3 ndk.abiFilters 'armeabi-v7a','arm64-v8a'
4 }

Prerequisites 

Skills required

The integration tasks should be done by developers with knowledge of:

  • Android Studio
  • Java for Android
  • Android OS

Resources required

Integration may be performed on computers running Windows, Linux, or macOS.

The tools required are:

  • Android studio 1 or above
  • Android SDK tools: preferred latest version (release 24 or above)
  • JDK: preferred latest version (7 or above)
  • Android device (emulator is not supported)
  • Minimum SDK version is 21

Licenses required

Depending on which implementation of the library is used, the licenses required are:

  • Biometry + Document:

    • MORPHOFACS
    • VERIF
    • IDENT
    • MIMA
    • MSC_CORE
    • MSC_LIVENESS
  • Biometry:

    • MORPHOFACS
    • VERIF
    • IDENT
    • MIMA
    • MSC_CORE
    • MSC_LIVENESS
  • Document:

    • MIMA
    • MSC_CORE

Note: To enable the video dump feature, you will also need MSC_DUMP.

Licenses are not automatically updated from the server though the apps when licenses are updated on the server side. This responsibility lies with the app when you receive an invalid exception error.

Changes 

  • Added passive liveness mode for face capture

Biometric capture SDK structure 

The SDK's structure is displayed below.

Intro_BioSDKStructure

Tips 

App size optimization

After adding the SDK to your project you will observe that the size of application has grown significantly. This is because the SDK now includes native libraries for two ABIs: armeabi-v7a and arm64-v8a. What is generated is an .apk file that deploys to Google Play. Your application will contain both application binary interfaces even if one is not used.

Android App Bundle is the solution for this issue. Instead of generating an .apk, it is possible to generate a bundle (.aab). When a user installs the application from the store that contains the bundle, only the required components for the user's specific device will be downloaded.

Additionally, the maximum size of the bundle increases to 150 MB (100 MB is still maximum size for .apk files).

No changes on Google Play are required - just upload .aab instead of .apk. Also, no development in the application project is required.

It is recommended that the bundle options be declared inside the Gradle file, for example:

XML
1android {
2 ...
3 bundle {
4 density {
5 enableSplit true
6 }
7 abi {
8 enableSplit true
9 }
10 language {
11 enableSplit false
12 }
13 }
14}

More about app bundles can be found here.

License manager 

The purpose of this section is to show the API of the license management portion of the SDK, and expose the objects involved.

License manager 

The License manager is the main entry point to use the SDK. You can manage licenses through LicenseManager.

Note: A valid license is required before using any feature of the SDK.

provideLicenseManager

This method provides an instance of LicenseManager with a predefined LKMS profile. Operetion with LicenseManager should be executed before starting capture.

Kotlin
1LicenseManager manager = LicenseManager.provideLicenseManager(LkmsProfileId, LkmsApiKey, lkmsUrl)

Activating license

This function fetches the license if it's not locally stored and activates it. Additionally, in cases where the license has expired, the function retrieves a new license. This process is crucial and must occur each time the application starts.

Method handles license management on calling thread.

Callback solution:

Kotlin
1val activationResult = manager.activate(
2 object: LicenseActivationListener {
3 override fun onLicenseActivated() {
4 //License fetched and activated with success.
5 }
6
7 override fun onLicenseActivationFailed(licenseActivationError: LicenseActivationError) {
8 //Failed to fetch or activate the license.
9 }
10 },
11 applicationContext
12 )

Coroutines solution: It returns LicenseActivationResult

Kotlin
1val activationResult = manager.activate(applicationContext)
2 when(activationResult) {
3 is LicenseActivationSuccess -> {
4 //License fetched and activated with success.
5 }
6 is LicenseActivationError -> {
7 //Failed to fetch or activate the license.
8 }
9 }

LicenseActivationResult

This is information of result from activation license using coroutines solution. Instance might be type of:

LicenseActivationError

This is the information about why license can not be activated.

Attribute
Description
type ActivationErrorTypeThe type of error why license activation failed
message StringThe activation failure reason.

ActivationErrorType

Attribute
Description
PROFILE_EXPIREDProfile expired, all licenses won’t work anymore. (Contact with support)
ACTIVATION_COUNT_EXCEEDEDNo more licenses can be consumed. (Contact with support)
AUTHENTICATION_ISSUECredentials and/or profile information are wrong.
CONNECTION_ISSUEConnection issue. Make sure that your internet connection is stable.
UNKNOWNUnknown issue.

Getting started 

This guide illustrates the required steps to configure a minimally viable project for capturing biometrics using the Biometric Capture SDK.

Downloadable sample apps are here:

Creating your app 

  1. Add the SDK library to your app's build.gradle:
Groovy
1implementation ("morpho.mph_bio_sdk.android:SmartBio:version")

If you do not have configured repository for the SDK yet, see introduction that explains how to do that.

  1. Add the correct plugin dependency if you use face capture.

Plugins are special extensions to the SDK that might add or change its features. In this way, users can save memory and increase performance by picking plugins they need.

For face capture there are three plugins to choose from. There should be only one plugin selected during the build. If more than one for a specific flavor is selected, it will cause a MultipleFaceInitPluginsException.

Available plugins

  • plugin-face-normal should be used when WebBioServer is not used and there is need for strong security during local liveness challenges.

  • plugin-face-lite should be used when WebBioServer is used because it can reduce the size of an application significantly.

  • plugin-face-cr2dmatching should be used for local usage with additional security feature for FaceLiveness.ACTIVE mode.

Example plugin dependency for face capture:

Groovy
1implementation 'com.idemia.smartsdk:plugin-face-normal:version'

Plugins for face matching 

If you use the finger only variant you can skip this section because the proper plugin is already attached to that version.

For face matching there are three options to choose from. Keep in mind that these algorithms are not compatible.

Stored templates will not be successfully matched against templates from another algorithm.

  • plugin-algorithm-f5-4-low75: This has been improved to perform better with default compression. If a previous SDK has been used before and there is a user base with stored templates already, then full migration will be required. All templates must be generated again with the new plugin in use.

  • plugin-algorithm-f5-0-vid81: This is the default algorithm that is compatible with previous SDK versions.

  • plugin-algorithm-fingerv9: This provides only finger matching.

  • plugin-algorithm-f6-5-low70: Recommended algorithm for face matching, introduced in SDK version 4.44.0. There is no compatibility in the template level with other plugins.

Remember to attach only one matching plugin per flavor, otherwise a MultipleInitBlockPluginsException will occur.

More about plugins

  1. Add the CaptureView to the layout where you handle the biometric capture:
XML
1<com.idemia.smartsdk.preview.CaptureView
2 android:id="@+id/captureView"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent" />
  1. On your activity or fragment get a reference to this view:
Java
1CaptureView cameraPreview = (CaptureView) findViewById(R.id.captureView);
  1. Activate your license. This can be done in the onCreate(Bundle savedInstanceState) or in a previous stage of your app. This must be done only once.
Java
1LicenseManager manager = LicenseManager.provideLicenseManager(LkmsProfileId, LkmsApiKey, lkmsUrl)
2 val activationResult = manager.activate(applicationContext)
3 when(activationResult) {
4 is LicenseActivationSuccess -> {
5 //License fetched and activated with success.
6 }
7 is LicenseActivationError -> {
8 //Failed to fetch or activate the license.
9 }
10 }

For security reasons it is good to consider storing LKMS credentials outside source code (for example gradle properties).

  1. Prepare capture settings. For face capture, you should use FaceCaptureOptions.
Java
1FaceCaptureOptions captureOptions = new FaceCaptureOptions(FaceLiveness.PASSIVE);
2 captureOptions.setCamera(Camera.FRONT);
3 captureOptions.setCaptureTimeout(120);
4 captureOptions.setOverlay(Overlay.OFF);
5 captureOptions.setTorch(Torch.OFF);
  1. In the onResume() method of your activity or fragment, obtain a valid reference to the IBioCaptureHandler using the previously created capture options.
Java
1protected void onResume() {
2 //Create handler
3 BioSdk.createFaceCaptureHandler(this, captureOptions, new MscAsyncCallbacks<IFaceCaptureHandler>() {
4 @Override
5 public void onPreExecute() {
6 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
7 }
8 @Override
9 public void onSuccess(IFaceCaptureHandler result) {
10 // Indicates that initialization succeeded, the returned handler can be used to start the capture.
11 faceCaptureHandler = result;
12 }
13 @Override
14 public void onError(BioCaptureHandlerError e) {
15 // An error has occurred during the initialization
16 }
17 });
18 super.onResume();
19 }
  1. Add the listeners for the events to the handler:
Java
1faceCaptureHandler.setFaceCaptureResultListener(new FaceCaptureResultListener() {
2 @Override
3 public void onCaptureSuccess(@NotNull FaceImage image) {
4 //Successfully captured image
5 }
6
7 @Override
8 public void onCaptureFailure(@NotNull CaptureError captureError,
9 @NotNull IBiometricInfo biometricInfo,
10 @NotNull Bundle extraInfo) {
11 //Capture failure
12 );
13 }
14 });
15 faceCaptureHandler.setFaceCaptureFeedbackListener(new FaceCaptureFeedbackListener() {
16 @Override
17 public void onCaptureInfo(FaceCaptureInfo captureInfo) {
18 //Face capture feedback info, like move your face to the right
19 }
20 });
21 faceCaptureHandler.setFaceTrackingListener(new FaceCaptureTrackingListener() {
22 @Override
23 public void onTracking(List<FaceTracking> trackingInfo) {
24 //Tracking info to know where the face is.
25 }
26 });
  1. Initialize the preview and capture to start receiving events. It should happen after creating the capture handler. The most common place for this would be onResume:
1 faceCaptureHandler.startPreview(new PreviewStatusListener() {
2 @Override
3 public void onStarted() {
4 try {
5 captureHandler.startCapture();
6 } catch (MSCException e) {
7 // handle exception
8 }
9 }
10
11 @Override
12 public void onError(PreviewError error) {
13 // Preview initialization failed and can not be started
14 }
15 });
  1. Destroy the handler when onPause() is invoked:
Java
1@Override
2 protected void onPause() {
3 if(captureHandler!=null) {
4 faceCaptureHandler.stopCapture();
5 faceCaptureHandler.stopPreview();
6 faceCaptureHandler.destroy();
7 }
8 super.onPause();
9 }

Declare permissions and providers in Manifest file 

  1. In your manifest, you must add:
XML
1<!--Declare new permissions-->
2 <permission
3 android:name="your.new.permission.NEW_READ_LKMS_LICENSE_PROVIDER"
4 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
5 <permission
6 android:name="your.new.permission.NEW_WRITE_LKMS_LICENSE_PROVIDER"
7 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
8 <permission
9 android:name="your.new.permission.NEW_READ_MPH_BIO_SDK_PROVIDER"
10 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
11 <permission
12 android:name="your.new.permission.NEW_WRITE_MPH_BIO_SDK_PROVIDER"
13 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
XML
1<!--The provider must be defined by the implementing app so as to allow multiple apps-->
2 <!--Bio store provider provider-->
3 <provider
4 android:name="com.morpho.mph_bio_sdk.android.sdk.content_provider.BioStoreProvider"
5 android:authorities="your.new.authority"
6 android:readPermission="your.new.permission.NEW_READ_MPH_BIO_SDK_PROVIDER"
7 android:writePermission="your.new.permission.NEW_WRITE_MPH_BIO_SDK_PROVIDER"
8 tools:replace="android:authorities, android:readPermission, android:writePermission">
9 </provider>
XML
1<!--The provider must be defined by the implementing app so as to allow multiple apps-->
2 <!--License provider-->
3 <provider
4 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider"
5 android:authorities="your.new.authority"
6 android:readPermission="your.new.permission.NEW_READ_LKMS_LICENSE_PROVIDER"
7 android:writePermission="your.new.permission.NEW_WRITE_LKMS_LICENSE_PROVIDER"
8 tools:replace="android:authorities, android:readPermission, android:writePermission">
9 </provider>

This step is crucial to make SDK working correctly and to avoid collision with other apps using same SDK. Improper configuration might end up with crash due to illegal (legacy/default) names of providers or permissions or due to lack of declaration of providers.

Analytics 

Capture SDK offers a logging mechanism that collects analytics data about SDK usage, and sends this data to IDEMIA's server. This data helps IDEMIA to improve Capture SDK and the likelihood of integrator success within the app. It is strongly recommended to activate the analytics mechanism.

  • You can enable or disable sending analytics data.
  • You can choose to send analytics data only when you are connected to a Wi-Fi network, so as not to not use your cellular connection.
  • Analytics data that IDEMIA collects contains only technical data.
  • No sensitive personal data is collected.
  • IDEMIA does not collect any images.

Analytics data that we collect include following information:

  • Application name, bundle id, version
  • Capture SDK and RemoteLogger libraries versions
  • Device model and operating system version
  • Technical information about performed face, finger, and document capture (such as: capture mode used; timestamp; reason of error; time needed to perform a capture; quality of captured image; and light condition)
  • Technical information about performed authentication and identification events (such as: used threshold, duration, and obtained score)
  • Other technical information (such as: image compression, occurred errors, and SDK performance) that does not contain personal data

You can disable analytics reporting using the appropriate SDK method.

Capture SDK plugins 

Plugins have been introduced to give even more flexibility than variants of the SDK. Every integrator might have different needs and size requirements. A new plugin mechanism allows for greater flexibility. Plugins are split to two groups: feature and algorithm.

Feature plugins 

Provides various SDK functionalities such as: face capture, document capture, and optical character recognition (OCR).

Algorithm plugins 

Provides for extracting biometric data from images, matching this data, and storing it as templates.

How it works 

Capture SDK still has previous variants with predefined plugins in the dependency list that are still required. However, some features might be different, like the matching algorithm or face capture challenge behavior. In such cases, these features might be configured via adding specific plugins.

All that must be done to add a plugin is to put the proper dependency to a project's module that will be using the plugin (How to use them).

Benefits 

The obvious benefit is reducing the number of SDK variants which makes it easier to pick the proper SDK dependency. It also brings flexibility to the product, namely, the ability to mix or replace features in the future or even extend SDK possibilities by implementing your own plugins.

How to use them 

Plugins are just ordinary dependencies. All that must be done is to add the proper dependency for the plugins that are needed. Read carefully about allowed combinations and predefined plugins in SDK variants.

Here is a snippet with all available plugins:

Gradle
1//Feature plugins
2implementation 'com.idemia.smartsdk:plugin-finger:$version'
3implementation 'com.idemia.smartsdk:plugin-face:$version'
4implementation 'com.idemia.smartsdk:plugin-face-normal:$version'
5implementation 'com.idemia.smartsdk:plugin-face-lite:$version'
6implementation 'com.idemia.smartsdk:plugin-face-cr2dmatching:$version'
7implementation 'com.idemia.smartsdk:plugin-face:$version'
8implementation 'com.idemia.smartsdk:plugin-improved-pdf417-detection:$version'
9
10//Algorithm plugins
11implementation 'com.idemia.smartsdk:plugin-algorithm-f5-0-vid81:$version'
12implementation 'com.idemia.smartsdk:plugin-algorithm-f5-4-low75:$version'
13implementation 'com.idemia.smartsdk:plugin-algorithm-f6-0-idd80:$version'
14implementation 'com.idemia.smartsdk:plugin-algorithm-f6-5-low70:$version'
15implementation 'com.idemia.smartsdk:plugin-algorithm-fingerv9:$version'

Allowed combinations 

Here are all possible combinations of plugins for specific use cases.

As mentioned above, the SDK variants have predefined plugins dependency, so that only a few must be defined.

See what predefined plugins has which variant of the SDK you use.

Face capture
plugin-face
plugin-face-lite
plugin-face-normal
plugin-face-cr2dmatching
Available algorithm plugins
plugin-algorithm-f5-4-low75
plugin-algorithm-f5-0-vid81
plugin-algorithm-f6-5-low70
plugin-algorithm-f6-0-idd80
Finger capture
plugin-finger
Available algorithm plugins
plugin-algorithm-f5-4-low75
plugin-algorithm-f5-0-vid81
plugin-algorithm-f6-0-idd80
plugin-algorithm-f6-5-low70
plugin-algorithm-fingerv9
Document capture
plugin-improved-pdf417-detection

Warning: Only one of: plugin-face-lite, plugin-face-normal, plugin-face-cr2dmatching can be used at a time. The integrator must pick one of them. A MultipleFaceInitPluginsException will occur if more than one has been picked.

SDK variants and their plugins 

Each SDK plugin variant delivers something different - check carefully what each plugin variant contains. Plugin variants should not be added in a module that uses this specific variant. As can be seen below, no document-related plugins must be added for variants that deliver this feature. In other words, variants contain all plugins that are required and have no alternatives.

Capture SDK
plugin-face
plugin-finger

Plugins that might be added for a Capture SDK variant:

  • One of: plugin-face-normal, plugin-face-lite, plugin-face-cr2dmatching
  • One of: plugin-algorithm-f5-4-low75, plugin-algorithm-f5-0-vid81, plugin-algorithm-f6-0-idd80, *plugin-algorithm-f6-5-low70, plugin-algorithm-fingerv9 (this one is not recommended if face matching will be performed)
Biometric Capture SDK
plugin-face
plugin-finger

Plugins that can be added for the Biometric Capture SDK variant:

  • One of: plugin-face-normal, plugin-face-lite, plugin-face-cr2dmatching
  • One of: plugin-algorithm-f5-4-low75, plugin-algorithm-f5-0-vid81, plugin-algorithm-f6-0-idd80, plugin-algorithm-f6-5-low70 plugin-algorithm-fingerv9 (this one is not recommended if face matching is going to be performed)
SmartFinger
plugin-finger
plugin-algorithm-fingerv9

There are no plugins for the SmartFinger variant.

SmartFace
plugin-face

Plugins that can be added for the SmartFace variant:

  • One of: plugin-face-normal, plugin-face-lite, plugin-face-cr2dmatching
  • One of: plugin-algorithm-f5-4-low75, plugin-algorithm-f5-0-vid81, plugin-algorithm-f6-0-idd80, plugin-algorithm-f6-5-low70
SmartFaceDoc
plugin-face
plugin-face-lite

Plugins that can be added for the SmartFaceDoc variant:

  • One of: plugin-algorithm-f5-4-low75, plugin-algorithm-f5-0-vid81, plugin-algorithm-f6-0-idd80, plugin-algorithm-f6-5-low70

However, this variant is meant to be used with WebBioServer which performs matching operations (no need to do that locally).

For SDK variants with document plugin-improved-pdf417-detection may be added in order to improve capture of barcodes.

Feature plugins descriptions 

plugin-face

Basic plugin needed for face capture. Usually it is predefined in every SDK variant that delivers face capture functionality.

plugin-face-normal

Should be used for face capture when WebBioServer is not used and there is a need for strong security during local liveness challenges.

plugin-face-lite

Should be used when WebBioServer is used for liveness check during face capture, because it can reduce the size of application significantly.

plugin-face-cr2dmatching

Should be used for local usage (without WebBioServer) when additional security feature for FaceLiveness.ACTIVE mode is needed.

plugin-finger

Plugin needed for finger capture. Usually it is predefined in every SDK variant that delivers finger capture functionality.

plugin-improved-pdf417-detection

Plugin that can be used to speed up barcode capture.

Algorithm plugins descriptions 

plugin-algorithm-f6-0-idd80

It is more accurate than f5-4-low75 and much smaller than f5-0-vid81.

plugin-algorithm-f5-4-low75

Improved to perform better with default compression. If a previous SDK has been used before and there is a user base with stored templates already, then full migration of the user's biometrics will be required. All templates must be generated again with the new plugin in use.

plugin-algorithm-f5-0-vid81

This is the default algorithm that is compatible with previous SDK versions.

plugin-algorithm-f6-5-low70

Recommended algorithm for face capture. It is more accurate than f6-0-idd80. If a previous SDK has been used before and there is a user base with stored templates already, then full migration of the user's biometrics will be required. All templates must be generated again with the new plugin in use.

plugin-algorithm-fingerv9

Provides only finger matching feature. It is best to pick this one when only finger matching will be performed.

WARNING

The algorithms are NOT compatible with each other. The templates generated by one of the algorithms cannot be processed with the other one; that is, it is not possible to match a template generated with F6_0_IDD80 against a template generated with F5_4_LOW75 or F5_0_VID81. If an integrator wants to change the algorithm in their solution, all the stored templates must be recreated with the new algorithm.

SDK size 

This is the estimated size of an SDK variant with all its dependencies, like predefined plugins (see Plugins section). The UI-extension is not included in size as it is not a predefined dependency.

SDK variant
Size
CaptureFace24.16 MB
CaptureDocument16.82 MB
CaptureFinger17.19 MB
CaptureBiometry28.65 MB
CaptureBiometry_document43.26 MB
CaptureFace_document38.76 MB

Plugins size 

Plugin
Size
plugin-face7.59 KB
plugin-face-normal6.75 MB
plugin-face-lite4.79 MB
plugin-face-cr2dmatching6.75 MB
plugin-finger794.64 KB
plugin-algorithm-f5-4-low7512.30 MB
plugin-algorithm-f5-0-vid814.08 MB
plugin-algorithm-f6-5-low707.45 MB
plugin-algorithm-fingerv91.51 KB
plugin-improved-pdf417-detection8.81MB

Integration guide 

The purpose of this document is to show the API of the SDK and expose all of its involved objects.

Use cases 

Capture biometrics

Below is the generic execution flow to perform a biometric capture (Get Picture), and get information about the biometry. For example, getting a picture and moving your head to the left.

capture_images

Capture timeout

Below is the generic execution flow to be followed when a capture timeout occurs.

capture_timeout

Capture enroll

Below is the generic execution flow to perform a biometric capture (Get Picture). After that, the biometrics template is extracted from the image returned by the capture component. The biometric template is linked to one user using the userUUID. The UUID of this template and the userUUID are stored in a database.

capture_enrol

Capture authenticate

Below is the generic execution flow to perform a biometric capture (Get Picture). The biometrics template is then extracted from the image and returned by the capture component. These are the candidate templates that you must use to create an IBiometricCandidate.

After the IBiometricCandidate is created, a list of reference templates must be extracted. These will then be used to create an IBiometricReference object with which to match against the IBiometricCandidate and authenticate that the candidate templates belong to the user.

There are two ways to extract a list of template references: the first is to retrieve them from the database used during the enrollment process; the second is to extract the templates from another image with detectBiometrics(...).

capture_verify

Capture identify

Below is the generic execution flow to perform a biometric capture (Get Picture). The biometrics template is then extracted from the image and returned by the capture component. These are the candidate templates which you must use to create an IBiometricCandidate.

After the IBiometricCandidate is created, a list of reference templates must be extracted. These will then be used to create an IBiometricReference object with which to match against the IBiometricCandidate and authenticate that the candidate templates belong to the user.

capture_identify

Creating BioMatcherHandler

Below is the generic execution flow to retrieve and release a BioMatcherhandler.

create

Authenticating

Below is the generic execution flow to perform a generic verification process which involves extracting the biometrics template from an image. These are the candidate templates which you must use to create an IBiometricCandidate.

After the IBiometricCandidate is created, a list of reference templates must be extracted. These will then be used to create an IBiometricReference object with which to match against the IBiometricCandidate and authenticate that the candidate templates belong to the user.

There are two ways to extract a list of template references: the first is to retrieve them from the database used during the enrollment process; the second to is extract the templates from another image with detectBiometrics(...).

verify

Identifying

Below is the generic execution flow to perform a generic identification process which involves extracting the biometrics template from an image. These are the candidate templates which you must use to create an IBiometricCandidate.

After the IBiometricCandidate is created, a list of reference templates must be extracted. These will then be used to create an IBiometricReference object with which to match against the IBiometricCandidate and authenticate that the candidate templates belong to the user.

identify

Detect biometrics

This describes detecting the biometrics in an IImage. This function is intended to be used to extract all the biometric templates contained in an image; for example, all the faces that are in an image.

detect_biometric

Create capture options from configuration file

The integrator can load options from a configuration file to create capture handlers. Such a file contains predefined settings delivered by the CaptureSDK team that can not be changed. Configuration contains a signature and any change to file will cause the exception, SignatureVerificationException, during its loading by the SDK. The configuration file should be located in the assets directory. Every ICaptureOptions instance (that is, FaceCaptureOptions, FingerCaptureOptions, and DocumentCaptureOptions) has a static method, createFromConfigurationFile, that provides the options of its instance, if that file contains it. Otherwise a FeatureConfigurationMissingException will be thrown.

add_template
capture_enrol
capture_identify
capture_images
capture_timeout
capture_verify
create
detect_biometric
identify
list_template_by_user_id_and_modality
list_template_by_user_id
remove_template_by_template_id
remove_template_by_user_id
retrieve_template
update_template
add_template
capture_enrol
capture_identify
capture_images
capture_timeout
capture_verify
create
detect_biometric
identify
list_template_by_user_id_and_modality
add_template
capture_enrol
capture_identify
capture_images
capture_timeout
capture_verify
create
detect_biometric
identify
list_template_by_user_id_and_modality
list_template_by_user_id
remove_template_by_template_id
remove_template_by_user_id
retrieve_template
update_template

Finger capture 

Overview 

Finger ridges have tiny minutiae that makes them difficult to alter. They are unique to each individual and durable over a lifetime. The probability of two people having the same fingerprints is approximately 1 in 64,000,000,000. This makes finger ridges the ideal long-term markers for human identity.

The Capture SDK applies this characteristic for easy authentication and identification using any modern Android or iOS smartphone equipped with a standard camera. Capture SDK is a software library used for scanning fingerprints.

Capture SDK features

  • Fingerprint acquisition results in raw images of finger ridges.

    Note: The conversion into worldwide WSQ1 format with a built-in converter is possible.

  • Biometric data extraction.

  • Biometric data storage.

  • Biometric data comparison to authenticate (1:1) or identify (1

    )

    Note: Once the biometric data is extracted, you can utilize the fast authentication mode. This reduces the process to encompass fingerprint acquisition and authentication only.

Dependencies

Implement a dependence with either a predefined or custom configuration:

Predefined:

XML
1implementatation "morpho.mph_bio_sdk.android:SmartFinger:$smartSdkVersion"

Custom:

XML
1implementation "morpho.mph_bio_sdk.android:SmartSDK:$smartSdkVersion"
2 implementation "com.idemia.smartsdk:plugin-algorithm-fingerv9:$smartSdkVersion"

More details about plugin dependencies can be found here

Description

There are four main components that can be used together or separately, depending on the use case: FingerCaptureHandler, BioMatcherHandler, ImageUtils, BioStoreDB.

SmartFinger architecture

FingerCaptureHandler is an extension of BioCaptureHandler which is a part of Biometric Capture SDK. It can capture, check liveness, and authenticate an user's fingerprints.

There are three available modes:

  • FINGERS, THUMB - captures fingerprint images (fingers or thumb, respectively) and optionally checks liveness.

  • AUTHENTICATION - captures fingerprint images, checks liveness, and determines whether the captured data matches with the chosen template.

BioMatcherHandler extracts templates with biometric data from images and also compare them. As a result of the comparison, score is returned. The score value determines if both templates belong to the same user or not. Read more about BioMatcherHandler

ImageUtils uses various conversion types; read section about ImageUtils.

BioStoreDB persists the templates when implemented by the integrator. Use of this component is optional. More about BioStoreDB

Summary

  1. To create a FingerCaptureHandler instance you must declare the FingerCaptureOptions.

    Regardless of the capture mode, set the basic configuration:

    • specify capture mode
    • whether a UI overlay be visible during capture
    • which of smartphone's cameras should be used to perform capture
    • what level of liveness check should be performed
    • declare timeout to define capture's duration

    When you choose FINGERS mode you can set which fingers are missing to capture. Default is zero amputated fingers. When you choose THUMB you can only scan a thumb.

  2. When the FingerCaptureOptions configuration completes, create FingerCaptureHandler.

  3. Register the listener with result callbacks.

  4. To perform a capture, start the camera preview and then start the capture.

  5. After the time declared in the FingerCaptureOptions passes, the result callback is returned.

For code examples, recommended configuration, and more detailed description, check the page dedicated to a specific capture option.

Fast authentication 

Fast Authentication is a special mode to authenticate fingerprints right after capture. There is one mode that can be used:

  • AUTHENTICATION for fingers

To use this mode you should have a list of MorphoTemplate templates from fingerprints that have been saved from previous captures during enrollment. These templates will be used to compare with current fingerprints from the current captures.

This mode returns IAuthenticationResult.

Flow

  1. Create LicenseMangager.
  2. Retrieve the license.
  3. Activate the license.
  4. Get a list of templates from MorphoTemplate.
  5. Create a BiometricReference.
  6. Create the FingerCaptionOptions with added BiometricReference and threshold.
  7. Create the FingerCaptureHandler.
  8. Set the listener, setAuthenticationListener.
  9. Start the capture.
  10. On callback, process the result.
  11. Stop the capture.

Below is the sequence diagram of that flow.

fast_authentication

Creating fast authentication use case

  1. Create a biometric reference.

Get the user instance form BioStoreDB and choose MorphoTemplate for the finger. From the BioStoreDB get the list of MorphoTemplate templates and create IBiometricReference.

Kotlin
1BioStoreDB.listUsers(
2 this@FingerCameraActivity,
3 object : DataBaseAsyncCallbacks<List<IUser>> {
4 override fun onPreExecute() {}
5 override fun onSuccess(iUsers: List<IUser>) {
6 if (iUsers.isNotEmpty()) {
7 val user = iUsers[0]
8 BioStoreDB.listTemplates(
9 this@FingerCameraActivity,
10 user.uuid,
11 BiometricModality.FRICTION_RIDGE,
12 object : DataBaseAsyncCallbacks<List<IMorphoTemplate>> {
13 override fun onPreExecute() {}
14
15 override fun onSuccess(references: List<IMorphoTemplate>) {
16 ...
17 //reference candidates
18 val reference = BiometricReference(user.uuid, BiometricModality.FRICTION_RIDGE)
19 reference.addTemplates(references)
20 ...
21 }
22
23 override fun onError(e: Exception) {}
24 })
25 }
26 }
27
28 override fun onError(e: Exception) {}
29})
  1. Add to FingerCaptureOptions the IBiometricReference with a threshold and create the FingerCaptureHandler.

Create FingerCaptureOptions with the added threshold and biometricRefernece. Then create FingerCaptureHandler.

Kotlin
1val fingerCaptureOptions = FingerCaptureOptions(BioCaptureMode.FINGERS, Hand.RIGHT)
2captureOptions.liveness = FingerLiveness.LOW
3captureOptions.bioCaptureMode = BioCaptureMode.FINGERS
4captureOptions.camera = Camera.REAR
5captureOptions.overlay = Overlay.ON
6captureOptions.captureTimeout = 10
7fingerCaptureOptions.biometricReference = reference
8fingerCaptureOptions.threshold = 3000
9fingerCaptureOptions.uhdResolutionEnabled = true
10createFingerCaptureHandler(fingerCaptureOptions)
11
12BioSdk.createFingerCaptureHandler(this, captureOptions, object : MscAsyncCallbacks<IFingerCaptureHandler> {
13 override fun onPreExecute() {}
14 override fun onSuccess(result: IFingerCaptureHandler) {
15 onFingerCaptureInitialized(result)
16 }
17
18 override fun onError(e: BioCaptureHandlerError) {}
19})
  1. Add the listener to the FingerCaptureHandler responsible for the fast authentication result.

To create a FingerCaptureHandler, add the callback responsible for Fast Authentication. In this callback, process the result. The next step will vary based on individual business workflows.

Kotlin
1fingerCaptureHandler.setAuthenthicationListener{ authenticationResult ->
2 if(authenticationResult.status == AuthenticationStatus.SUCCESS){
3 onAuthenticationSuccess(authenticationResult)
4 } else {
5 onAuthenticationFailure(authenticationResult)
6 }
7};

Results

IAuthenticationResult

This is the interface that represents an authentication result.

Parameter
Description
score longThe authentication score (between 0 and 50000).
authenticationStatus AuthenticationStatusThe authentication status.
AuthenticationStatus

This is the enum class that represents whether the authentication is successful or not.

The authentication is successful when the score is greater than the threshold.

Parameter
Description
SUCCESSAuthentication was successful.
FAILUREAuthentication was not successful.

Capture errors 

Errors returned when finger capture fails.

Name
When
Why
CAPTURE_TIMEOUTUsed time for captureFingers were not captured properly in time
CAPTURE_DELAYEDFailing captures repeatedlyPrevent spoofing
BAD_CAPTURE_FINGERSCapture of fingers failedCouldn't find fingerprints on captured image
BAD_CAPTURE_HANDCapture of hand failedWrong hand scanned
LIVENESS_CHECKLiveness check failedFingerprints do not belong to a living person

BioStore 

With the BioStore component you can save biometric templates in a device's memory. Usage of this component is optional, depending on the integrator's needs.

BioStore allows operations for a specific user like: listing templates, adding new templated, updating templates, removing templates.

A more detailed description about BioStore can be found here

Usage

The most common use case for BioStore is to save a template and restore it later to do matching against a new capture. To do this, there must be at least one user added.

Add new user
1IUser user = new User();
2user.setName("Name");
3BioStoreDB.addUser(context, user, new DataBaseAsyncCallbacks<UUID>() {
4 @Override
5 public void onPreExecute() {
6 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
7 }
8
9 @Override
10 public void onSuccess(UUID result) {
11 //User saved
12 }
13
14 @Override
15 public void onError(Exception e) {
16 // An error has occurred
17 }
18});
Listing saved templates for the finger

This lists the templates stored in the repository and filters them by user and BiometricModality.

1BioStoreDB.listTemplates(context, userId, BiometricModality.FRICTION_RIDGE, new DataBaseAsyncCallbacks<List<IMorphoTemplate>>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(List<IMorphoTemplate> result) {
9 //The list of templates that match the criteria
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred
15 }
16});
Save templates for the finger

Store a template in the repository. If there is a previous template with the same user UUID, the biometric location and biometric modality will be updated and their UUID returned.

Note: There cannot be two templates with the same configuration.

1BioStoreDB.addTemplate(context, morphoTemplate, new DataBaseAsyncCallbacks<UUID>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(UUID result) {
9 //The template has been added, and template's uuid is returned as a parameter
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred
15 }
16});

Finger matching 

The Capture SDKs can match biometric templates with the same biometric modality to get the IAuthenticationResult, which is based on a similarity score.

An example of such a comparison follows.

Matching flow

BioMatcherHandler creation
1IBioMatcherHandler matcherHandler = null;
2IBioMatcherSettings bioMatcherSettings = new BioMatcherSettings();
3 //To configure finger print template format
4 bioMatcherSettings.setFingerprintTemplate(MorphoFingerTemplateFormat.PKCOMPV2);
5 BioSdk.createBioMatcherHandler(this, bioMatcherSettings, new BioMatcherAsyncCallbacks<IBioMatcherHandler>() {
6 @Override
7 public void onPreExecute() {
8 // Optional hook on the builtin Android AsyncTask call-back `onPreExecute`
9 }
10
11 @Override
12 public void onSuccess(IBioMatcherHandler result) {
13 // Indicates that initialization succeeded, the returned handler can be used to perform the matching and identify operations.
14 matcherHandler = result;
15 }
16
17 @Override
18 public void onError(Exception e) {
19 // An error has occurred
20 }
21 });
Authentication
Requirements
  • Create a BioMatcherHandler. More about MatcherHandler.

  • Obtain candidate fingerprints' templates. In most use cases they are acquired during the enrollment process.

  • Obtain reference templates for matching. It is possible to match templates stored in a database or other persistence solution, but in most cases a reference is acquired from a previous finger capture during the authentication process.

  • Before matching, authentication options must be created. Such options contain the threshold that must be exceeded by the matching score to have a successful authentication.

  • Once those items are complete, the biometric candidate can be matched against the reference. As a result the IAuthenticationResult object will be returned. It has two fields: status - indicating if the authentication is successful or not and score which might be in the range 0 – 50000.

1//Authentication options
2IAuthenticationOptions authenticationOptions = new AuthenticationOptions();
3authenticationOptions.setThreshold(3500);
4
5//Biometric candidate
6IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FRICTION_RIDGE);
7//We add all the templates for this candidate
8biometricCandidate.addTemplates(candidates);
9
10//Biometric references
11IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FRICTION_RIDGE);
12//We add all the templates for this user
13biometricReference.addTemplates(references);
14
15matcherHandler.authenticate(authenticationOptions, biometricCandidate, biometricReference, new BioMatcherAsyncCallbacks<IAuthenticationResult>() {
16 @Override
17 public void onPreExecute() {
18 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
19 }
20
21 @Override
22 public void onSuccess(IAuthenticationResult result) {
23 //The result of the authentication
24 long resultScore = result.getScore();
25 //authentication status (FAILURE, SUCCESS...)
26 AuthenticationStatus authenticationStatus = authenticationResult.getStatus();
27 }
28
29 @Override
30 public void onError(Exception e) {
31 // An error has occurred
32 }
33});

Parameters

Parameter
Description
authenticationOptions IAuthenticationOptionsThe options used to perform the authentication. This object holds the threshold that the score must exceed to accept the candidate.
biometricCandidate IBiometricCandidateContains the list of templates to match against.
biometricReference IBiometricReferenceContains the list of templates for reference; each of one has the userUUID to which they belong.

Passive capture 

Passive capture captures fingerprints without any challenges performed by the user.

There are two BioCaptureMode values available for finger capture:

  • FINGERS for scans of 1 to 4 fingers.
  • THUMB` for scans of one finger

Parameters

Parameter
Short description
Recommended value
BioCaptureModeCapture modes that are described earlierBioCaptureMode.FINGERPRINT_RIGHT_CAPTURE
OverlayIntuitive rectangles that help the user properly place their fingers during a captureOverlay.ON
CameraSmartphone's camera that will be used during the captureCamera.REAR
LivenessLevel of challenge that the fingers image must pass to be considered aliveFingerLiveness.MEDIUM
TimeoutDuration of capture in seconds~10
amputeeFingersInformation about which fingers are missing with BioCaptureMode.FINGERS
handInformation about which hand will be scanned

Capture flow

Sequence diagram

CaptureSequenceDiagram
  1. After the activation of license, create the handler with the necessary defined capture options.

  2. Register the listener to get the result callbacks.

  3. When it finishes, use the handler to start the camera preview and capture respectively.

Note: After the capture is finished, remember to stop the preview and the capture. When you finish, destroy the capture.

Note that diagram represents abstract BioCapture flow. FingerCapture differs with its capture result listener. More information is in listeners.

  • The capture starts just after the camera preview is started.

  • The capture lasts as long as the timeout duration previously set.

The user must fit and stabilize their fingers inside a preview screen during the capture process. It is recommended to turn on the overlay in the capture settings that displays an intuitive UI.

Capture screen with overlay

FingerSampleApp
Capture options configuration
Kotlin
1val options = FingerCaptureOptions()
2 options.bioCaptureMode = BioCaptureMode.FINGERS
3 options.overlay = Overlay.ON
4 options.camera = Camera.REAR
5 options.captureTimeout = 10
6 options.liveness = FingerLiveness.MEDIUM

The smartphone's camera is on by default as it is recommended for better capture performance. However, it can be turned off if needed.

Listeners

FingerCaptureResultListener has two methods: onCaptureSuccess and onCaptureFailure. These return result data on a successful capture and a capture error on a capture with errors.

Kotlin
1val handler = BioSdk.createFingerCaptureHandler(context, options)
2 handler.setFingerCaptureResultListener(object : FingerCaptureResultListener {
3 override fun onCaptureFailure(
4 captureError: CaptureError,
5 biometricInfo: IBiometricInfo,
6 extraInfo: Bundle
7 ) {
8 // handle capture failure
9 }
10
11 override fun onCaptureSuccess(
12 images: MutableList<MorphoImage>,
13 captureResult: FingerCaptureResult
14 ) {
15 // handle capture success
16 }
17 }
Result

On a successful capture:

  • A list of five images of the type MorphoImage is returned, where one image contains all of the fingers and four gray-scale fingerprint images that represents separate fingers compressed with a WSQ algorithm.

  • FingerCaptureResult, where its data should be considered only if FingerLiveness has a value other than FingerLiveness.NONE. It consists of a score value that represents the confidence of liveness recognition and the FingerLivenessResult that holds the decision on whether the captured fingers belongs to a real person or not.

Document capture 

Getting started 

The guide illustrates the necessary steps to configure and use a minimally viable project to read documents using the Biometric Capture SDK.

Downloadable sample apps are at Document autocapture.

To create your own app:

  1. Add the SDK library to your app's build.gradle:
Java
1implementation ("morpho.mph_bio_sdk.android:SmartDoc:version")
  1. Add the CaptureView to the layout where you handle the biometric capture.
XML
1<com.idemia.smartsdk.preview.CaptureView
2 android:id="@+id/captureView"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent" />
  1. On your activity or fragment, get a reference to this view:
Java
1CaptureView cameraPreview = (CaptureView) findViewById(R.id.captureView);
  1. Activate your license. You can do that in the onCreate(Bundle savedInstanceState), or in a previous stage of your app.
Kotlin
1LicenseManager manager = LicenseManager.provideLicenseManager(LkmsProfileId, LkmsApiKey, lkmsUrl)
2 val activationResult = manager.activate(applicationContext)
3 when(activationResult) {
4 is LicenseActivationSuccess -> {
5 //License fetched and activated with success.
6 }
7 is LicenseActivationError -> {
8 //Failed to fetch or activate the license.
9 }
10 }
  1. In the onResume() method of your activity or fragment, you must obtain a valid reference of the IDocumentCaptureHandler.
Java
1protected void onResume() {
2 //Sample configuration
3 //The activate process was OK.
4 // Populate a CaptureOptions object
5 IDocumentCaptureOptions captureOptions = new DocumentCaptureOptions(
6 new DocumentCaptureModeConfiguration {
7 public DocumentMode provideCaptureMode() {
8 return DocumentMode.READ_MRZ
9 }
10 });
11 captureOptions.setDocumentCaptureMode();
12 captureOptions.setCamera(Camera.REAR);
13 captureOptions.setTorch(Torch.OFF);
14 captureOptions.setOverlay(Overlay.ON);
15 captureOptions.setCaptureTimeout(120);
16 BioSdk.createDocumentCaptureHandler(activity, captureOptions, new MscAsyncCallbacks<IDocumentCaptureHandler>() {
17 @Override
18 public void onPreExecute() {
19 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
20 }
21 @Override
22 public void onSuccess(IDocumentCaptureHandler result) {
23 // Indicates that initialization succeeded, the returned handler can be used to start the capture.
24 }
25 @Override
26 public void onError(BioCaptureHandlerError e) {
27 // An error has occurred during the initialization
28 }
29 });
30 super.onResume();
31 }
  1. Add the listeners for the events to the handler.
Java
1//MRZ callbacks
2captureHandler.setDocumentCaptureListener(new DocumentCaptureListener() {
3 @Override
4 public void onCaptureImageDocument(DocumentImage image) {
5 //If rectification is enabled we will receive several callbacks to this method (One per image, DATA_PAGE, PORTRAIT…)
6 //Document image captured
7 try {
8 byte[] jpegImage = image.getJPEGImage(); Bitmap documentImage = BitmapFactory.decodeByteArray(jpegImage, 0, jpegImage.length);
9 //show the document image
10 }
11 catch (Exception e){
12 Log.e(TAG, "", e);
13 }
14 //If rectification is disabled and we want to get all the images encoded into the location coordinates of the image
15 List<DocumentImage> croppedImages = ImageUtils.extractImages(image);
16 }
17 @Override
18 public void onCaptureFieldImageDocument(DocumentImage image, String labelName) {
19 //A field has been coded
20 }
21 @Override
22 public void onMRZDocumentRead(List<IMRZLine> mrzLines, IMrzRecord mrzRecord) {
23 //MRZ captured
24 }
25 @Override
26 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {
27 //Capture failed
28 }
29 @Override
30 public void onCaptureFinish() {
31 //Capture finished
32 }
33});
34//Barcode callbacks
35captureHandler.setBarcodeListener(new BarcodeListener() {
36 @Override
37 public void onBarcodeRead(List<String> capture) {
38 //Barcode captured
39 }
40 @Override
41 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {
42 //Capture failed
43 }
44 @Override
45 public void onCaptureFinish() {
46 //Capture finished
47 }
48});
49//Capture feedback listener
50captureHandler.setDocCaptureFeedbackListener(new DocumentCaptureFeedbackListener() {
51 @Override
52 public void onCaptureInfo(DocCaptureInfo docCaptureInfo) {
53 //Document captures info
54 }
55});
56//Tracking listener
57captureHandler.setDocumentTrackingListener(new DocumentCaptureTrackingListener() {
58 @Override
59 public void onTracking(List<MorphoDocumentRegion> trackingInfo) {
60 //Tracking info
61 }
62});
  1. Initialize the preview and capture to start the receive events.
1 captureHandler.startPreview(new PreviewStatusListener() {
2 @Override
3 public void onStarted() {
4 try {
5 captureHandler.startCapture();
6 } catch (MSCException e) {
7 // handle exception
8 }
9 }
10
11 @Override
12 public void onError(PreviewError error) {
13 // Preview initialization failed and can not be started
14 }
15 });
  1. Destroy the handler when onPause() is invoked.
Java
1@Override
2 protected void onPause() {
3 if(captureHandler!=null) {
4 captureHandler.destroy();
5 }
6 super.onPause();
7 }
  1. If you must force a document capture:
Java
1if(captureHandler!=null){
2 //Force a document capture
3 captureHandler.forceCapture();
4}
  1. In your manifest you must add:
XML
1<!--Declare new permissions-->
2 <permission
3 android:name="your.new.permission.NEW_READ_LKMS_LICENSE_PROVIDER"
4 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
5 <permission
6 android:name="your.new.permission.NEW_WRITE_LKMS_LICENSE_PROVIDER"
7 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
8 <permission
9 android:name="your.new.permission.NEW_READ_MPH_BIO_SDK_PROVIDER"
10 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
11 <permission
12 android:name="your.new.permission.NEW_WRITE_MPH_BIO_SDK_PROVIDER"
13 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
XML
1<!--Remove old permissions-->
2 <permission
3 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider.READ_MPH_BIO_SDK_PROVIDER"
4 tools:node="remove" />
5 <permission
6 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider.WRITE_MPH_BIO_SDK_PROVIDER"
7 tools:node="remove" />
8 <permission
9 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider.WRITE_LKMS_LICENSE_PROVIDER"
10 tools:node="remove"
11 />
12 <permission
13 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider.READ_LKMS_LICENSE_PROVIDER"
14 tools:node="remove"
15 />
XML
1<!--The provider must be defined by the implementing app so as to allow multiple apps-->
2<!--Bio store provider provider-->
3<provider
4 android:name="com.morpho.mph_bio_sdk.android.sdk.content_provider.BioStoreProvider"
5 android:authorities="your.new.authority"
6 android:readPermission="your.new.permission.NEW_READ_MPH_BIO_SDK_PROVIDER"
7 android:writePermission="your.new.permission.NEW_WRITE_MPH_BIO_SDK_PROVIDER"
8 tools:replace="android:authorities, android:readPermission, android:writePermission">
9</provider>
XML
1<!--The provider must be defined by the implementing app so as to allow multiple apps-->
2<!--License provider-->
3<provider
4 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider"
5 android:authorities="your.new.authority"
6 android:readPermission="your.new.permission.NEW_READ_LKMS_LICENSE_PROVIDER"
7 android:writePermission="your.new.permission.NEW_WRITE_LKMS_LICENSE_PROVIDER"
8 tools:replace="android:authorities, android:readPermission, android:writePermission">
9</provider>
  1. You must also set to landscape the orientation of the activity that will read MRZ:
XML
1<activity android:name="YOUR_ACTIVITY_NAME"
2 android:screenOrientation="landscape">
3</activity>

Integration guide 

The purpose of this section is to show the API of the SDK and expose its objects.

Use cases

In order to get informations from capture, proper listeners have to be applied to DocumentCaptureHandler.

All use cases can retrieve data from:

  • DocumentCaptureFeedbackListener - provides information about capture conditions like: glare, too far/close to document etc.
  • DocumentCaptureTrackingListener - provides document coordinates on preview (coordinates are relative to preview frame size - not display size).
Read MRZ

This use case is used when the integrator wants to read the MRZ area of a document, such as those found on passports, but without retrieving the document. In such case listener: DocumentCaptureListener should be applied as it provides MRZ value read during capture.

capture_mrz
Read MRZ with document image

This use case is used when the integrator wants to read the MRZ area of a document, such as those found on passports. It also retrieves an image of the document.

In such case listener: DocumentCaptureListener should be applied as it provides MRZ value read during capture and document image itself.

capture_mrz_image.png
Capture a document image

This use case is used when the integrator wants to retrieve an image of the document.

In such case listener: DocumentCaptureListener should be applied as it provides document image that has been captured. If capture did not finish successfully before timeout, it returns best frame from acquisition attempt.

capture_document_image
Read a QR code

This use case is used when the integrator wants to read a QR Code.

To get QR code or PDF417 data use listeners:

  • BarcodeListener - to get data as String
  • BarcodeRawDataListener - to get data as ByteArray
capture_barcode

New document API 

Introduction 

In order to make integration easier and more intuitive - new API has been delivered. It is based on use cases that are self-explaining which provide specific information depending on given use case. This allows to focus on working with data provided by SDK rather than on SDK configuration. What is more, some use cases allows to capture whole document (front and back sides) in single capture session - camera opens only once. More about use cases can be found here.

Integration 

Integration with new API is simple and consists of three steps.

  1. License activation and camera permission. In order to use SDK proper license has to be activated. Getting started section shows how to handle license and permissions.

  2. Add DocumentCaptureView to the layout. This will be not only capture preview but also entry point to the SDK.

XML
1<com.idemia.capture.document.api.DocumentCaptureView
2 android:id="@+id/captureView"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent" />

This view implements interface DocumentCapture which might be called to manage capture. It contains four methods: setUp(useCase: CaptureUseCase, lifecycle: Lifecycle), start(), stop(), destroy() .

Setting up is described below. Methods start, stop and destroy are similar to old API's methods to manage capture. However if Lifecycle instance has been passed during setup - there is no need to use these three methods - starting, stoping and destroying will be handled automatically.

  1. Use case creation. In order to start capture, specific use case instance needs to be created. Each use case have sessionInfo property that contains session configuration and set of listeners that might be applied in order to receive data from capture.

Once these three steps are satisfied, setUp method on CaptiveView might be called, passing use case instance as paramerer. If Lifecycle instance is also passed - there is no need to handle lifecycle methods of CaptureView (start/stop/destroy). Listeners attached to use case that has been previously created will provide data from capture.

Use cases 

Capture settings of DocumentCaptureSDK are done by using proper, predefined configuration designed for specific use case. In this way capture configuration is more intuitive and less confusing. Every use case take parameters only for this exact use case needs. In most cases it will be timeout value and listeners for capture feedback/result.

RemoteUseCase

This use case performs document capture with backend communication in order to allow manual verification of the document captured. In order to provide correct flow, FeedbackListener, RemoteListener and SessionInfo must be provided during RemoteUseCase initialization. FeedbackListener is mandatory to instruct user to properly place device during capture and also when to flip document if both sides are required for verification. RemoteListener informs about whole flow result and provides images of document captured. These images have to be approved in order to proceed with the process more detailed description might be found in listeners section. SessionInfo provides information about document capture session on IDEMIA Identity and Verification service for SDK needs to continue the flow.

It also contains field feedbackSamplingTime which can be used to define time between showing feedbacks for the capture.

SessionInfo field
Description
sessionId StringLive capture session id created with: v1/identities/{identityId}/id-documents/live-capture-session
apiKey StringApiKey for authorization on DocServer.
baseUrl StringUrl of document server - for example: https://idproofing-api.environment.idemia.io/doc-server/
Kotlin
1captureView.setUp(
2 RemoteUseCase(
3 feedbackListener,
4 adjudicationListener,
5 sessionInfo,
6 timeoutListener
7 ),
8 lifecycle
9)

Listeners 

Listeners available for specific use cases within new API for document capture.

RemoteListener

Listener dedicated to remote use cases. Two methods needs to be implemented to provide correct flow to the user.

  1. onDocumentCaptured(images: List<DocumentImage>, captureFinalizer: CaptureFinalizer) - this method is being called when document has been captured. List of images (front, back or both sides images) is returned. CaptureFinalizer instance allows to retry capture, cancel whole flow (Failure instance of Result will be returned on onResult method) or approve images which continues remote flow. Notice that CaptureFinalizer can retry capture which means that whole remote flow (including displaying captured document) must be performed on the same Activity where DocumentCaptureView is attached.

  2. onResult(result: Result) - returns result of remote flow. No other callback will occur after this method. Result might be type of Success or Failure.

Kotlin
1private val remoteListener = object : RemoteListener {
2 override fun onDocumentCaptured(
3 images: List<DocumentImage>,
4 captureFinalizer: CaptureFinalizer
5 ) {
6 //Handle captured document
7 }
8
9 override fun onResult(result: Result) {
10 when (result) {
11 is Failure -> //Handle failure result
12 is Success -> //Handle success result
13 }
14 }
15}

FeedbackListener

Returns feedback about current capture. Feedback should be displayed to user. Only one function to implement: onFeedback(feedback: CaptureFeedback), where CaptureFeedback is an enum telling about capture condition like: document is too far/too close to camera.

Kotlin
1private val feedbackListener = object : FeedbackListener {
2 override fun onFeedback(feedback: CaptureFeedback) {
3 //Present feedback to the user
4 }
5}

Time between feedbacks is defined (in seconds) by feedbackSamplingTime property of CaptureUseCase. By default it is 2 seconds.


CaptureTimeoutListener

Returns images in case of document capture timeout. Those images can be shown with associated _DocumentImageQualityIndicators to make another capture easeier. NOTE: _DocumentImageQualityIndicators from Failure are applicable ONLY for the last image returned on this callback!

Kotlin
1private val timeoutListener = CaptureTimeoutListener { documentImages ->
2 // Show images to the user
3 }

This listener is optional.

Errors 

For every flow there is possibility to receive Failure type from method onCaptureFinish in CaptureStateListener. It means that something went wrong during the capture or backend communication. Fortunately, Error object contains a lot of useful informations that help to handle failed flow.

Failure

Parameter
Description
type FailureTypeType of an error. High level information what goes wrong. Find types description below.
code IntSpecial code dedicated for particular case. Very helpful in L2, L3 troubleshooting.
message StringMessage with error description.
qualityIndicators DocumentImageQualityIndicators?Contains information what went wrong if document was not captured before timeout.

FailureType

Type
Description
CONNECTION_ISSUEGeneral issue with connection. See message and error code for more informations.
AUTHENTICATIONBackend authentication failed. Probably wrong credentials has been used for the given environment.
INVALID_SESSIONSession ID is not correct. Most probably session expired or has been finished.
TIMEOUTTimeout occured during the flow.
BAD_CAPTURECapture failed. Face was not detected or liveness check did not pass.
UNKNOWNUnknow type of exception. Also used as default type for few cases.
CANCELEDFlow has been canceled. Can be triggered by integrator or automatically when Lifecycle has been passed to setUp method.
INVALID_LICENSELicense validation failed. Make sure that it has been activated with [LicenseManager](https://experience.idemia.com/identity-proofing/develop/capture-sdk/android/4_x/integration-guide #license-manager)

DocumentImageQualityIndicators

This object contains failure reasons of the capture.

Parameter
Description
badFraming BooleanIndicates if there was a problem with detecting entire document
blur BooleanIndicates if document was blurred
glare BooleanIndicates if reflections were detected
tooClose BooleanIndicates if document was too close from the camera
tooFar BooleanIndicates if document was too far from the camera
notStraight BooleanIndicates if document was straight
lowLight BooleanIndicates if lightning conditions were good enough
badConsistency BooleanIndicates if enough consecutive good frames were detected for document
pdf417BadDecoding Boolean?Indicates if pdf417 was detected. null if pdf417 is not mandatory for the document
mrzBadDecoding Boolean?Indicates if mrz was detected. null if mrz is not mandatory for the document
qrCodeBadDecoding Boolean?Indicates if QR code was detected. null if QR code is not mandatory for the document

Biocapture SDK 

This is the main entry point that allows you to use the SDK.

Note: You must always have a valid license before using any method of this SDK.

getInfo

This method allows the integrator to retrieve information about the SDK.

An example snippet is shown:

Java
1IBioSdkInfo sdkInfo= BioSdk.getInfo();

Get debug data

You can save some captured data on a device's memory. In some cases, those files might help to solve some issues. Data can be found on the SD card in the SmartSDK_debug_data directory.

An example on how to configure the debug data options is shown in the snippet:

Java
1[...]
2 DebugSettingsBuilder debugSettingsBuilder = new DebugSettingsBuilder();
3 debugSettingsBuilder.logLevel(logLevel)
4 .storingType(DataStoringType.LAST_SESSION_ONLY)
5 .recordRtv(DebugOption.DISABLED)
6 .recordPostMortemRtv(DebugOption.DISABLED)
7 .saveCapturedImages(DebugOption.DISABLED);
8 captureOptions.setDebugDataSettings(debugSettingsBuilder.build());

DataStoringType can have two values: LAST_SESSION_ONLY and MULTIPLE_SESSIONS. The first one overwrites data in a single directory. The second makes a separate directory per capture.

There is also an option to store a special .rtv file that helps you understand what is happening during the capture.

Note: These files take a lot of space. LogLevel describes what part of the logs will be saved to a file. If needed, the integrator can also save captured images by enabling the saveCapturedImages option.

Returns

This is an object with the information about the SDK (refer to IBioSdkInfo).

enableAnalytics

This method turns on the reporting and sending analytics report. It also changes the analytics server and its API key.

NOTE: The server is set to Europe by default.

Parameter
Description
network NetworkPreferred network type that will be used to send the report.
analyticsConfigurationData AnalyticsConfigurationDataClass that allows the setting of SERVER URL and API KEY.

disableAnalytics

This turns off the reporting and sending analytics report.

Note: By default, the analytics mechanism is turned on and the server is set to Europe.

Create a DocumentCaptureHandler

This retrieves a capture handler to perform all the document capture operations. You must first configure the capture options.

  • Check the use case named Read MRZ.

  • Also, check all the features provided by this handler.

Java
1// Get activity from application
2 Activity activity = ...
3 // Populate a CaptureOptions object
4 IDocumentCaptureOptions captureOptions = new DocumentCaptureOptions(
5 new DocumentCaptureModeConfiguration {
6 public DocumentMode provideCaptureMode() {
7 return DocumentMode.READ_MRZ
8 }
9 });
10 captureOptions.setCamera(Camera.REAR);
11 captureOptions.setTorch(Torch.OFF);
12 captureOptions.setOverlay(Overlay.ON);
13 captureOptions.setCaptureTimeout(120);
14 captureOptions.enableSingleShootCapture();
15 captureOptions.setUhdResolutionEnabled(true);
16 BioSdk.createDocumentCaptureHandler(activity, captureOptions, new MscAsyncCallbacks<IDocumentCaptureHandler>() {
17 @Override
18 public void onPreExecute() {
19 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
20 }
21 @Override
22 public void onSuccess(IDocumentCaptureHandler result) {
23 // Indicates that initialization succeeded, the returned handler can be used to start the capture.
24 }
25 @Override
26 public void onError(DocumentCaptureHandlerError e) {
27 // An error has occurred during the initialization
28 }
29 });
Parameter
Description
activity ActivityThe Android activity.
options IDocumentCaptureOptionsThe capture options to configure the document capture handler.
callbacks MscAsyncCallbacksCallbacks to be executed depending on the result.

Errors

Error code
Description
MSC_ERR_APPLINOTAVAILABLEThe application parameter is not available.
MSC_ERR_GRAPH_INITIALISATION_FAILEDThe graph initialization failed.
MSC_ERR_INITInitialization failed.
MSC_ERR_PARAMETERSThe parameters are invalid.
MSC_ERR_PARAMETER_NOT_FOUNDThe parameter is missing.
MSC_ERR_PARAMETER_SIZEThe parameter size is incorrect.
MSC_ERR_PARAMETER_UNKNOWNOne of the parameters is unknown.
MSC_ERR_INVALID_HANDLEThe handle is invalid.
LIBS_NOT_FOUNDThe java libraries are not found.
NO_CONTEXT_SETThe java context is not set.
NOT_EXECUTEDThe java is unable to execute.
MSC_ERR_LICENSEThe license is invalid.
MSC_ERR_MEMALLOCThe memory allocation issue.
MSC_ERR_PROFILENOTAVAILABLEDocumentCapture profile is not available.
MSC_ERR_SUBPROFILENOTAVAILABLEDocumentCapture sub-profile is not available.
MSC_ERR_TYPE_MISMATCHDocumentCapture type mismatch .
UNKNOWNUnknown error.

Document capture handler

You must retrieve the capture handler through Create DocumentCaptureHandler.

Document capture listener

This sets the listener to receive the captures.

The events of the capture process are reported to the integrator app through this listener, as shown in the snippet below:

Java
1captureHandler.setDocumentCaptureListener(new DocumentCaptureListener() {
2 @Override
3 public void onCaptureImageDocument(DocumentImage image) {
4 //Document image captured
5 try {
6 byte[] jpegImage = image.getJPEGImage();
7 Bitmap documentImage = BitmapFactory.decodeByteArray(jpegImage, 0, jpegImage.length);
8 //show the document image
9 }catch (Exception e){
10 Log.e(TAG, "", e);
11 }
12 }
13 @Override
14 public void onCaptureFieldImageDocument(DocumentImage image, String labelName) {
15 //A field has been coded
16 }
17 @Override
18 public void onMRZDocumentRead(List<IMRZLine> mrzLines) {
19 //MRZ captured
20 }
21 @Override
22 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {
23 //Capture failed
24 }
25 @Override
26 public void onCaptureFinish() {
27 //Capture finished
28 }
29 });

Barcode capture listener

This sets the listener to receive the barcode captures. The events of the capture process are reported to the integrator app through this listener.

There are two types of listeners: text data and raw data.

Java
1//Barcode callbacks for text data
2 captureHandler.setBarcodeListener(new BarcodeListener(){
3 @Override
4 public void onBarcodeRead(List<String> capture){
5 //Barcode captured
6 }
7 @Override
8 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {
9 //Capture failed
10 }
11 @Override
12 public void onCaptureFinish() {
13 //Capture finished
14 }
15 });
Java
1//Barcode callbacks for raw data
2 captureHandler.setBarcodeListener(new BarcodeListener(){
3 @Override
4 public void onBarcodeRead(RTBuffer capture){
5 //Barcode captured
6 }
7 @Override
8 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {
9 //Capture failed
10 }
11 @Override
12 public void onCaptureFinish() {
13 //Capture finished
14 }
15 });

Only one listener can be active at a time.

Feedback listener

This sets the listener to receive feedback, like moving a face to the right.

Java
1captureHandler.setDocCaptureFeedbackListener(new DocumentCaptureFeedbackListener() {
2 @Override
3 public void onCaptureInfo(DocCaptureInfo docCaptureInfo) {
4 //Document captures info
5 }
6 });

VideoRecordingReadyForGenerationListener

This sets the listener for a document to get VideoRecording. This listener is called when recording is enabled. It is called on successful and failed capture.

Set callback as shown in the snippet:

Java
1captureHandler.setVideoRecordingReadyForGenerationListener(new VideoRecordingReadyForGenerationListener() {
2
3 @Override
4 public void videoRecordingReadyForGeneration(VideoRecording videoRecording) {
5 //Video recording object to generate video
6 }
7 });

Callback returns VideoRecording object to generate video from capture.

Start preview

Asynchronously starts the camera preview.

It is recommended to start the capture once the preview has been initialized, as shown in the snippet:

1handler.startPreview(new PreviewStatusListener() {
2 @Override
3 public void onStarted() {
4 try {
5 captureHandler.startCapture();
6 } catch (MSCException e) {
7 // handle exception
8 }
9 }
10
11 @Override
12 public void onError(PreviewError error) {
13 // Preview initialization failed and can not be started
14 }
15 });

Stop preview

This stops the camera preview as shown in the snippet:

Java
1handler.stopPreview()

Start capture

This starts the biometric capture as shown in the snippet.

Java
1handler.startCapture();

Stop capture

This stops the biometric capture as shown in the snippet:

Java
1handler.stopCapture();

Switch camera

This switches between different cameras as shown in the snippet:

Java
1handler.switchCamera(Camera.FRONT); // Use front camera
2handler.switchCamera(Camera.REAR); // Use rear camera

Destroy

This releases all the handler resources as shown in the snippet:

Java
1handler.destroy();

Overlay

This sets the overlay option as shown in the snippet:

Java
1handler.setOverlay(Overlay.OFF); // Disable preview's overlay
2handler.setOverlay(Overlay.ON); // Enable preview's overlay

Torch

This sets the torch option as shown in the snippet:

Java
1handler.setTorch(Torch.OFF); // Disable the torch
2handler.setTorch(Torch.ON); // Enable the torch

CaptureOptions

This retrieves the capture options used in this handler, as shown in the snippet:

Java
1IDocumentCaptureOptions options = handler.getCaptureOptions();

Force capture

This forces a capture as shown in the snippet:

Java
1handler.forceCapture();

Request partial video

This dumps a video that starts when startCapture is invoked and finishes at the moment that this function is invoked, as shown in the snippet:

Java
1handler.requestPartialDumpVideo();

Note: You must first enable the feature in the settings and also configure the path to save the videos.

Capture handler status

This retrieves the status of the capture handler as shown in the snippet:

Java
1CaptureHandlerStatus captureHandlerStatus = handler.getCaptureStatus();

Note: Refer to CaptureHandlerStatus.

Helper objects 

This section explains the helper objects that are necessary to use the Biometric Capture SDK.

IBioSdkInfo

This object exposes information about the SDK.

Parameter
Description
version StringThe version of the SDK.

DocumentCaptureOptions

This object is used to configure the behavior of the DocumentCapture.

Attribute
Description
captureMode DocumentCaptureModeThe app enum option to configure the capture.
camera CameraThe app camera option to configure the capture.
torch TorchSets the torch value.
overlay OverlaySets the overlay value.
captureTimeout LongCaptures the timeout in seconds (default value 120).
captureImageTimeout LongSets the image capture timeout. This timeout is used to force the capture of an image in the time given or fail. (-1 disables it, by default it is disabled).
logLevel LogLevelSets the log level.
DebugDataSettings Debug DataSets the debug data options that stores key information about a capture on the device's memory.
ocr OCR(OBSOLETE) Sets OCR recognition. Enabled by default.
rectification RectificationSets image rectification. Enabled by default.
acquisitionMode AcquisitionModeSets the speed/quality balance during a document capture.
minDPI intMinimum resolution in dpi of the datapage captured. Possible value from 1 to 400.
stillShootEnable BooleanWhen enabled, the document image is taken with a single shot with higher resolution. If not, best image from video stream is taken.
videoRecordingOptions VideoRecordingOptionsWhen enabled, CaptureSDK returns VideoRecording to generate video from the taken capture. (By default video recording is disabled.)
uhdResolutionEnabled BooleanWhen enabled, the document capture will be started in UltraHD resolution. Otherwise FullHD will be used. Enabled by default.
feedbackSamplingTime Long

IImage

This is the image interface that the SDK image objects extend.

Parameter
Description
buffer byte[]The image.
stride intThe stride of the biometric.
width longThe width of the image.
height longThe height of the image.
colorSpace ColorSpaceThe ColorSpace of the image.
resolution floatThe resolution of the image.
imageQuality intImage quality if available, otherwise -1. Currently only available for fingerprint images.
labelLabel associated with this image, if any. It can be 'null'
toJPEG byte[]Retrieves the image as a JPEG image. Default quality for that document is 70%. The created JPEG for the document will contain capture maker note data inside EXIF metadata, containing information such as the SDK version used for capturing the image.
toJPEG(float quality)Retrieves the image as a JPEG image with quality valued from '0' to '1'

IDocumentImage

This is the document image interface that the SDK document image objects extend. It extends from IImage, but getImageQuality() method of IImage will always return -1 for document image.

Parameter
Description
documentRegions ListA list of the different regions with their coordinates of the document within the image. It can be null or empty. You only receive them if you select READ_MRZ_DOCUMENT_IMAGE_HIGH and rectification is DISABLE.
documentLocation DocumentLocationZone in the document to locate specific data, such as a photo or MRZ.
codedMode CodedModeIndicates how this image was triggered.
docLevel DocLevelGives information concerning the confidence of the information returned.

DocumentImageQualityIndicators

This object contains failure reasons of the capture.

Parameter
Description
blur BooleanIndicates if document was blurred
glare BooleanIndicates if reflections were detected
tooClose BooleanIndicates if document was too close from the camera
tooFar BooleanIndicates if document was too far from the camera
notStraight BooleanIndicates if document was straight
lowLight BooleanIndicates if lightning conditions were good enough
badConsistency BooleanIndicates if enough consecutive good frames were detected for document
pdf417BadDecoding DocumentImageQualityIndicatorIndicates if pdf417 was detected
mrzBadDecoding DocumentImageQualityIndicatorIndicates if mrz was detected

MorphoDocumentRegion

This object contains the coordinates of the document.

Parameter
Description
point1 PointFPoint 1 (Top left)
point2 PointFPoint 2 (Top right)
point3 PointFPoint 3 (Bottom right)
point4 PointFPoint 4 (Bottom left)
documentLocation DocumentLocationZone in the document to locate specific data, such as a photo or MRZ.
previewRect RectThe original preview size to which the coordinates are referred.

IMrzRecord

The MRZ record that interfaces with the SDK MRZ record objects that are extended.

Parameter
Description
morphoMrzDocumentCode MorphoMrzDocumentCodeThe document code.
morphoMrzDocumentFormat MorphoMrzDocumentFormatThe document format.
morphoMrzSex MorphoMrzSexGender
code1 charMRZ code 1
code2 charMRZ code 2
issuingCountry StringIssuing country
documentNumber StringDocument number
surname StringSurname
surname StringSurname
givenNames StringGiven names
dateOfBirth CalendarDate of birth
expirationDate CalendarExpiration date

IMrzFrenchIdCardRecord

The MRZ record interface for French identity cards. It extends IMrzRecord.

Parameter
Description
optional StringOptional data

IMrzMRPRecord

The MRZ record interface for MRP cards. It extends IMrzRecord.

Parameter
Description
personalNumber StringPersonal number

IMrzMrtdTd1Record

The MRZ record interface for MRTD TD1 cards. It extends IMrzRecord.

Parameter
Description
optional StringOptional data
optional2 StringOptional data

IMrzMrtdTd2Record

The MRZ record interface for MRTD TD2 cards. It extends IMrzRecord.

Parameter
Description
optional StringOptional data

IMrzMrvARecord

The MRZ record interface for MRV A cards. It extends IMrzRecord.

Parameter
Description
optional StringOptional data

IMrzMrvBRecord

The MRZ record interface for MRV B cards. It extends IMrzRecord.

Parameter
Description
optional StringOptional data

IMrzSlovackId2_34Record

The MRZ record interface for Slovakian identity cards. It extends IMrzRecord.

Parameter
Description
optional StringOptional data

GenericDocumentCaptureListener

This is a generic capture listener.

onDocumentCaptureFailure

This is invoked if DocumentCaptureHandler fails to do a capture. Check DocumentCaptureError.

Function
Java
1void onDocumentCaptureFailure(@NonNull DocumentCaptureError captureError, @Nullable DocumentImageQualityIndicators indicators)
Arguments
Parameter
Description
captureError DocumentCaptureErrorAn error
indicators DocumentImageQualityIndicatorsContains information about document integrity, sharpness, lightning and reflections. May be null.

onCaptureFinish

This is invoked by DocumentCaptureHandler when it finishes the capture process.

Function
Java
1void onCaptureFinish()

DocumentCaptureListener

This is the document capture listener that extends GenericDocumentCaptureListener.

onCaptureImageDocument

This is invoked if a successful document image has been captured. Check DocumentImage.

Function
Java
1void onCaptureImageDocument(DocumentImage image);
Arguments
Parameter
Description
image DocumentImageThe document image.

onCaptureFieldImageDocument

This is invoked if a document field has been captured. Check DocumentImage.

Function
Java
1void onCaptureFieldImageDocument(DocumentImage image, String labelName);
Arguments
Parameter
Description
image DocumentImageThe document image.
labelName StringThe name of the label detected. The label depends on the document detected.

onMRZDocumentRead

This is invoked by DocumentCaptureHandler when it finishes reading all the lines of an MRZ document. Check IMRZLine.

Function
Java
1void onMRZDocumentRead(List<IMRZLine> mrzLines, IMrzRecord mrzRecord)
Arguments
Parameter
Description
mrzLines ListA list of MRZ lines read.
mrzRecord IMrzRecordThe MRZ lines parsed in an object that helps to extract the information. It could be null, if the MRZ lecture doesn't follow the standards.

BarcodeListener

This is the barcode capture listener that extends GenericDocumentCaptureListener.

onBarcodeRead

This is invoked if a successful barcode has been read.

Function
Java
1void onBarcodeRead(List<String> capture)
Arguments
Parameter
Description
capture ListA list of lines read.
Function
Java
1void onBarcodeRead(RTBuffer capture)
Arguments
Parameter
Description
capture RTBufferRaw data of a barcode.

DocumentCaptureFeedbackListener

This is the capture feedback listener. This listener enables the app to receive feedback about the document captures, such as image blur.

onCaptureInfo

This is invoked multiple times by DocumentCapture to send feedback about the capture process to the app.

Function

An example snippet is shown:

Java
1void onCaptureInfo(DocCaptureInfo docCaptureInfo);
Arguments
Parameter
Description
docCaptureInfo DocCaptureInfoThe feedback.

DocumentCaptureTrackingListener

Tracking listener

This sets the listener to receive tracking information, such as where the biometric is located.

Java
1captureHandler.setDocumentTrackingListener(new DocumentCaptureTrackingListener() {
2 @Override
3 public void onTracking(List<MorphoDocumentRegion> trackingInfo) {
4 //Tracking info to know where the document is.
5 }
6 });

IMRZLine

This interface represents a basic MRZ line.

Parameter
Description
lineNumber intThe line number of the MRZ read.
consorank intThe rank number of the MRZ read.
Text StringThe MRZ text line.
docLevel DocLevelGives information concerning the confidence of the information returned.

VideoRecording

This object is used to generate video in MP4 format. On success, it return the path to the video. You can generate one video.

Java
1videoRecording.generateVideo(new VideoProgressListener() {
2
3
4 @Overide
5 void onFinish(String path) {
6 //When creating video comlete with success return path to video
7 }
8
9 @Overide
10 void progress(int progress) {
11 //Showing progress of generating video from 0 to 100
12 }
13
14 @Overide
15 void onError(VideoError error) {
16 //It's call when generating video failed or another video is current generating
17 }
18});

If you do not want to generate video from the previous capture, use:

Java
1videoRecording.clean()

Enums 

ColorSpace

This is the colorspace enum.

Attribute
Description
Y8Grayscale 8bpp image.
Y16LEGrayscale 16bpp image (Little Endian).
BGR24Colour 24bpp BGR image (BMP like memory layout).
RGB24Colour 24bpp RGB image (reversed memory layout compared to RT_COLORSPACE_BGR24).

Camera

This is the enum used to configure the camera for DocumentCapture.

Attribute
Description
FRONTFront camera
REARRear camera

Torch

This is the enum used to configure the torch for DocumentCapture.

Attribute
Description
OFFTorch off
ONTorch on

Overlay

This is the enum used to configure the overlay for DocumentCapture.

Attribute
Description
OFFOverlay off
ONOverlay on

OCR (OBSOLETE)

This is the enum used to configure the optical character recognition for DocumentCapture (obsolete).

Attribute
Description
DISABLEOCR off
ENABLEOCR on

Rectification

This is the enum used to configure the rectification for DocumentCapture.

Attribute
Description
DISABLERectification off
ENABLERectification on

DocumentCaptureMode

This is the enum used to configure the mode for DocumentCapture.

Attribute
Description
READ_MRZReads MRZ lines.
READ_MRZ_DOCUMENT_IMAGE_MEDIUMAllows the capture of an image at the device's best video resolution after MRZ reading.
QR_CODEReads a QR Code.
QR_CODE_PDF_417Reads PDF417.
CAPTURE_DOCUMENT_IMAGE_VERY_LOW_IDCaptures an image at the device's best video resolution of ID1, ID2, and ID3 documents.
CAPTURE_DOCUMENT_IMAGE_VERY_LOW_A4Captures an image at the device's best video resolution of an A4 document.
CAPTURE_DOCUMENT_IMAGE_BARCODE_VERY_LOW_ID1Captures an image and read a barcode at the device's best video resolution of ID1 documents.
CAPTURE_DOCUMENT_IMAGE_VERY_LOW_ID1Captures an image at the device's best video resolution of ID1 documents.

AcquisitionMode

This enum is used for configure document capture quality mode

Attribute
Description
LOWLow quality high speed
MEDIUMMedium quality medium speed
HIGHHigh quality low speed

DocumentCaptureError

This enum reports why the document capture fails.

Attribute
Description
UNKNOWNUnknown error
INVALID_MRZInvalid MRZ line read
CAPTURE_TIMEOUTCapture timeout
BAD_CAPTURE_BARCODEBarcode capture failed
BAD_CAPTURE_DOCUMENTDocument capture failed
BAD_CAPTURE_DOCUMENT_IMAGEDocument image capture failed

LogLevel

This enum controls the log level.

Attribute
Description
ERRORError log level or above
DEBUGDebug log level or above
WARNINGWarning log level or above
INFOInfo log level or above
DISABLEDisables logs

DocCaptureInfo

This enum reports the document capture information.

Attribute
Description
BADFRAMINGBad framing detected.
BLURBlur detected.
ENDSTILLPoint and shoot capture done.
STARTSTILLStart point and shoot capture.
SHAKINGShaking detected.
HOLD_STRAIGHTHold document straight.
REFLECTIONReflection detected.
TOO_FARThe document is too far.
TOO_CLOSEThe document is too close.
OKEverything is OK.
DOCUMENT_NOT_DETECTEDDocument not detected within an internal timeout.

DocumentLocation

This enum shows biometric locations.

Attribute
Description
DOC_MRZMRZ zone
DOC_DATAPAGEData page zone
DOC_PHOTOPhoto zone
DOC_REFLECTReflect zone
UNKNOWNUnknown

CaptureHandlerStatus

This enum retrieves the status of the capture handler.

Attribute
Description
STOPThe handler is stopped.
PREVIEWThe handler is in preview mode.
CAPTUREThe handler is in capture mode.

MorphoMrzDocumentCode

This enum retrieves the MRZ document code.

Attribute
Description
CREW_MEMBERCrew member code
MIGRANTMigrant code
PASSPORTPassport code
TYPE_ATYPE_A code
TYPE_CTYPE_C code
TYPE_ITYPE_I code
TYPE_VTYPE_V code

MorphoMrzDocumentFormat

This enum retrieves the MRZ document format.

Attribute
Description
FRENCH_IDFrench identity card
MRTD_TD1MRTD TD1
MRTD_TD2MRTD TD2
MRV_VISA_AMRV Visa A
MRV_VISA_BMRV Visa B
PASSPORTPassport
SLOVAK_ID_234Slovak identity card

MorphoMrzSex

This enum retrieves the MRZ document gender.

Attribute
Description
MALEMale gender
FEMALEFemale gender
UNSPECIFIEDUnspecified gender

Century

This enum helps parse the year of the MRZ documents; only the last two digits of the year are provided.

Attribute
Description
NONENo century used for extracting the year
NINETEENNineteenth century used for extracting the year
TWENTYTwentieth century used for extracting the year
TWENTY_ONETwenty-first century used for extracting the year
TWENTY_TWOTwenty-second century used for extracting the year

CodedMode

This enum shows document image capture modes. These indicate how the image has been triggered.

Attribute
Description
NOMINALAll video quality criteria have been fulfilled and the best image is returned.
FORCEForce capture trigger has been used
TIMEOUTBest image returned on timeout

DocLevel

This enum gives information concerning the confidence of the information returned.

Attribute
Description
VERY_LOWCan be obtained with all profiles
LOWCan be obtained with high, medium, or low profiles
MEDIUMCan be obtained with high or medium profiles
HIGHCan be obtained with high profiles

Integrity

This enum gives information if the image integrity is acceptable.

Attribute
Description
OKDocument integrity is ok
NOT_OKDocument integrity is invalid

Sharpness

This enum gives information if the sharpness integrity is acceptable.

Attribute
Description
OKDocument image is sharp
NOT_OKDocument image is not sharp

Reflections

This enum gives information if reflections on the document were detected.

Attribute
Description
NOT_DETECTEDNo reflections on document image
DETECTEDReflections on document image

Lighting

This enum gives information about lightning condition.

Attribute
Description
OKImage captured in good lightning conditions
BADLightning conditions were not good enough for the capture

DocumentImageQualityIndicator

This enums gives information about quality indicator

Attribute
Description
TRUEGiven indicator is not acceptable
FALSEGiven indicator is acceptable
NOT_APPLICABLEIndicator is not applicable for current capture mode

Compression recommendations

The recommendations for document images are:

  • Send non-segmented images.
  • Compression is JPEG92
  • Size of image will be about 1 MB

An example snippet is shown:

Java
1val JPEG_COMPRESSION_LEVEL = 92
2private fun prepareImage(image: ByteArray): ByteArray {
3 val byteArrayOutStream = ByteArrayOutputStream()
4 val documentBitmap = BitmapFactory.decodeByteArray(image, 0, image.size)
5 val result = documentBitmap.compress(Bitmap.CompressFormat.JPEG, JPEG_COMPRESSION_LEVEL, byteArrayOutStream)
6 documentBitmap.recycle()
7
8 return byteArrayOutStream.toByteArray()
9}

Biometric capture 

This is the main entry point that will allow you to use the SDK.

Remember: You must always have a valid license before using any method of this SDK.

getInfo

The purpose of this method is to allow the integrator to retrieve information about the SDK.

Java
1IBioSdkInfo sdkInfo= BioSdk.getInfo();

Returns

An object with the information about the SDK.

enableAnalytics

This enables reporting and sending of analytics data. This method also changes the analytics server and its API key. By default, the server is set on Europe.

Parameter
Description
network NetworkPreferred network type that will be used to send report.
analyticsConfigurationData AnalyticsConfigurationDataClass that allows set SERVER URL and API KEY.

disableAnalytics

This disables reporting and sending of analytics data. By default, the analytics mechanism is enabled and the server is set on Europe.

Creating a BioCapture handler

These instructions will help you create a BioCapture handler.

  1. Retrieve a capture handler to perform all the biometric capture operations. You must first configure the capture options. For projects that use Kotlin there are handlers from com.idemia.smartsdk.capture that support initializing capture preview with suspend method.

BioCaptureMode is now deprecated and should not be used during capture configuration because it will be removed in a future release.

  • Review the use cases named Capture biometrics.

  • Review all the features provided by the BioCaputureHandler handler here.

1 val captureOptions = FaceCaptureOptions(FaceLiveness.PASSIVE).apply {
2 camera = Camera.FRONT
3 captureTimeout = 120
4 overlay = Overlay.OFF
5 torch = Torch.OFF
6 }
7 val captureHandler = FaceCaptureHandler(context, captureOptions)
Parameter
Description
activity ActivityThe Android activity.
options IFaceCaptureOptionsThe capture options to configure the bio capture handler.
callbacks BioCaptureAsyncCallbacksCallbacks to be executed depending on the result.

Errors 

Error code
Description
MSC_ERR_APPLINOTAVAILABLEThe application parameter is not available.
MSC_ERR_GRAPH_INITIALISATION_FAILEDThe graph initialization failed.
MSC_ERR_INITInitialization failed.
MSC_ERR_PARAMETERSParameters are invalid.
MSC_ERR_PARAMETER_NOT_FOUNDParameter is missing.
MSC_ERR_PARAMETER_SIZEParameter size is incorrect.
MSC_ERR_PARAMETER_UNKNOWNOne of the parameters is unknown.
MSC_ERR_INVALID_HANDLEHandle is invalid.
LIBS_NOT_FOUNDJava libraries are not found.
NO_CONTEXT_SETJava context is not set.
NOT_EXECUTEDJava is unable to execute.
MSC_ERR_LICENSELicense is invalid.
MSC_ERR_MEMALLOCMemory allocation issue.
MSC_ERR_PROFILENOTAVAILABLEBioCapture profile is not available.
MSC_ERR_SUBPROFILENOTAVAILABLEBioCapture sub-profile is not available.
MSC_ERR_TYPE_MISMATCHBioCapture type mismatch.
UNKNOWNUnknown error

Creating a BioMatcher Handler

This allows you to retrieve a handler to perform all the matching, identifying, and template coding operations.

Java
1IBioMatcherSettings bioMatcherSettings = new BioMatcherSettings();
2 bioMatcherSettings.setLogLevel(LogLevel.DISABLE);
3 bioMatcherSettings.setDumpFileEnable(false);
4 bioMatcherSettings.setDumpFileFolder(null);
5 //To configure finger print template format
6 bioMatcherSettings.setFingerprintTemplate(MorphoFingerTemplateFormat.PKCOMPV2);
7 BioSdk.createBioMatcherHandler(this, bioMatcherSettings, new BioMatcherAsyncCallbacks<IBioMatcherHandler>() {
8 @Override
9 public void onPreExecute() {
10 // Optional hook on the builtin Android AsyncTask call-back `onPreExecute`
11 }
12
13 @Override
14 public void onSuccess(IBioMatcherHandler result) {
15 // Indicates that initialization succeeded. The returned handler can be used to perform the matching and identify operations.
16 }
17
18 @Override
19 public void onError(Exception e) {
20 // An error has occurred.
21 }
22 });
Parameter
Description
context ContextThe Android context.
settings IBioMatcherSettingsThe settings to configure the matcher.
callbacks BioMatcherAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Handlers 

This section discusses the BioCapture handler, FaceCapture handler, FingerCapture handler, and BioMatcher handler.

BioCapture handler

You must retrieve the capture handler through the Biometric Capture SDK entry point.

Face listener

This sets the listener to receive feedback (such as when a user moves their face to the right) as shown in the snippet:

Java
1captureHandler.setFaceTrackingListener(new FaceCaptureTrackingListener() {
2 @Override
3 public void onTracking(List<FaceTracking> trackingInfo) {
4 //Tracking info to know where the face is.
5 }
6 });

Finger listener

This sets the listener to receive feedback (where the fingers are located) as shown in the snippet:

Java
1captureHandler.setFingerTrackingListener(new FingerCaptureTrackingListener() {
2 @Override
3 public void onTracking(List<FingerTracking> trackingInfo) {
4 //Tracking info to know where the fingers are.
5 }
6 });

Start preview

This asynchronously starts the camera preview. It is recommended to start the capture once the preview has been initialized, as shown in the snippet:

Java
1handler.startPreview(new PreviewStatusListener() {
2 @Override
3 public void onStarted() {
4 try {
5 captureHandler.startCapture();
6 } catch (MSCException e) {
7 // handle exception
8 }
9 }
10
11 @Override
12 public void onError(PreviewError error) {
13 // Preview initialization failed and can not be started
14 }
15 });
Kotlin
1coroutineScope.launch {
2 documentHandler.startPreview()
3 documentHandler.startCapture()
4}

Stop preview

This stops the camera preview as shown in the snippet:

Java
1handler.stopPreview()

Start capture

This starts the biometric capture as shown in the snippet.

Java
1handler.startCapture();

Stop capture

This stops the biometric capture as shown in the snippet:

Java
1handler.stopCapture();

Switch camera

This switches between different cameras as shown in the snippet:

Java
1handler.switchCamera(Camera.FRONT); // Use front camera
2handler.switchCamera(Camera.REAR); // Use rear camera

Destroy

This releases all the handler resources as shown in the snippet:

Java
1handler.destroy();

Overlay

This sets the overlay option.

Java
1handler.setOverlay(Overlay.OFF); // Disable preview's overlay
2handler.setOverlay(Overlay.ON); // Enable preview's overlay

Torch

This sets the torch option as shown in the snippet:

Java
1handler.setTorch(Torch.OFF); // Disable the torch
2handler.setTorch(Torch.ON); // Enable the torch

CaptureOptions

This retrieves the capture options used in this handler as shown in the snippet:

Java
1ICaptureOptions options = handler.getCaptureOptions();

Force capture

This forces a capture as shown in the snippet:

Java
1handler.forceCapture();

Request partial video

Note: You must first enable the feature in the settings and also configure the path to save the videos for this to work.

This dumps a video that starts when startCapture is invoked and finishes at the moment that this function is invoked, as shown in the snippet:

Java
1handler.requestPartialDumpVideo();

Capture handler status

Note: Check CaptureHandlerStatus.

This retrieves the status of the capture handler as shown in the snippet:

Java
1CaptureHandlerStatus captureHandlerStatus = handler.getCaptureStatus();

FaceCapture handler

Note: It extends from BioCaptureHandler.

You must retrieve the capture handler through the Biometric Capture SDK entry point for BioCaptureHandler, as shown in the snippet:

Java
1// Get activity from application
2Activity activity = ...
3// Populate a CaptureOptions object
4IFaceCaptureOptions captureOptions = new FaceCaptureOptions(FaceLiveness.PASSIVE);
5captureOptions.setFaceLivenessSecurityLevel(FaceLivenessSecurityLevel.HIGH);
6captureOptions.setCamera(Camera.FRONT);
7captureOptions.setCaptureTimeout(120);
8captureOptions.setOverlay(Overlay.OFF);
9captureOptions.setTorch(Torch.OFF);
10BioSdk.createFaceCaptureHandler(activity, captureOptions, new MscAsyncCallbacks<IFaceCaptureHandler>() {
11 @Override
12 public void onPreExecute() {
13 // Optional hook on the builtin Android AsyncTask call-back `onPreExecute`
14 }
15
16 @Override
17 public void onSuccess(IFaceCaptureHandler handler) {
18 // Indicates that initialization succeeded, the returned handler can be used to start the capture.
19 faceCaptureHandler = result;
20 //handler.setTotalNumberOfCapturesBeforeDelay(-1); to disable delays between face capture failures.
21 }
22
23 @Override
24 public void onError(BioCaptureHandlerError e) {
25 // An error has occurred during the initialization
26 }
27});

Capture result listener

This sets the listener to receive the face captures. The face image callback will be fired whenever the capture is finished, as shown in the snippet:

Java
1faceCaptureHandler.setFaceCaptureResultListener(new FaceCaptureResultListener() {
2 @Override
3 public void onCaptureSuccess(@NotNull FaceImage image) {
4 }
5
6 @Override
7 public void onCaptureFailure(@NotNull CaptureError captureError,
8 @NotNull IBiometricInfo biometricInfo,
9 @NotNull Bundle extraInfo) {
10 }
11 });
onCaptureSuccess
Called when captured is finished successfully
image FaceImageCapture face image
FaceImage
getLivenessResult FaceLivenessResultResolution of capture liveness: LIVE,FAKE, or NO_DECISION
getMetadata MetadataLow level data needed for verification or debug

FaceImage extends IImage, so it is possible to call getImageQuality() on it. However it is not recommended, as imageQuality is only available for finger capture and this method will always return -1 for FaceImage.

onCaptureFailure
Called when capture failed
captureError CaptureErrorReason of capture failure
biometricInfo IBiometricInfoBiometric information about location and classification
extraInfo BundleHolds capture extra info: capture delay date

VideoRecordingReadyForGenerationListener (Only for Face capture and RemoteFace capture)

This sets the listener for the document to get a VideoRecording. This listener is called when recording is enabled. It is called on successful and failed capture.

Setting callback

Java
1captureHandler.setVideoRecordingReadyForGenerationListener(new VideoRecordingReadyForGenerationListener() {
2 @Override
3 public void videoRecordingReadyForGeneration(VideoRecording videoRecording) {
4 //Video recording object to generate video
5 }
6 });

Callback returns VideoRecording object to generate video from capture.

Use CR2D challenges

This is another type of challenges which contains target points and points controlled by the user. To use it, pass FaceLiveness.ACTIVE to the FaceCaptureOptions constructor.

This example sets CR2D in capture options as shown in the snippet:

Java
1FaceCaptureOptions options = new FaceCaptureOptions(FaceLiveness.ACTIVE);

Use passive liveness challenge

Passive mode checks for liveness without user interaction (no head movement required). As in default mode, it requires only to show the face in front of the camera so that an image can be acquired. Special algorithms estimate if a user is a real person or not. To use this mode, pass FaceLiveness.PASSIVE to FaceCaptureOptions constructor.

This example sets Passive in the capture options as shown in the snippet"

Java
1FaceCaptureOptions options = new FaceCaptureOptions(FaceLiveness.PASSIVE);

Set Total Number of Captures Before Delay

This function sets the maximum number of liveness attempts before a delay. It must be invoked before startCapture. Set it to -1 to disable it. An example is shown in the snippet:

Java
1((FaceCaptureHandler)handler).setTotalNumberOfCapturesBeforeDelay(1);

Get total number of captures before delay

This returns the total number of attempts before blocking the authentication process. This only works if liveness is enabled. An example is shown in the snippet:

Java
1handler.getTotalNumberOfCapturesBeforeDelay();

Get debug data

You can save some capture data on the user device's memory. In some cases, keeping those files might help to solve issues.

Below is an example of how to configure the debug data options. The data can be found on the SD card in the SmartSDK_debug_data directory. An example is shown in the snippet:

Java
1[...]
2 DebugSettingsBuilder debugSettingsBuilder = new DebugSettingsBuilder();
3 debugSettingsBuilder.logLevel(logLevel)
4 .storingType(DataStoringType.LAST_SESSION_ONLY)
5 .recordRtv(DebugOption.DISABLED)
6 .recordPostMortemRtv(DebugOption.DISABLED)
7 .saveCapturedImages(DebugOption.DISABLED);
8 captureOptions.setDebugDataSettings(debugSettingsBuilder.build());

Note: DataStoringType might have two values: LAST_SESSION_ONLY or MULTIPLE_SESSIONS. The first overwrites data in a single directory. The second makes a separate directory per capture.

An option exists to store special .rtv files that help you understand what is happening during a capture.

Note: Storing these files takes a lot of space. LogLevel describes what part of the logs will be saved to a file. If needed, the integrator can also save captured images by enabling saveCapturedImages option.

Set maximum captures before delay

This field sets the maximum number of captures before preventing a capture.

Values less than or equal to 0 disable the functionality. Values greater than 0 set the number of attempts before blocking.

The default value is 5 as shown in the snippet:

Java
1((FaceCaptureHandler)handler).setMaxCapturesBeforeDelay(5);

There is also a getter for this value as shown in the snippet:

Java
1((FaceCaptureHandler)handler).getMaxCapturesBeforeDelay();

Set capture delay time array

This sets the array list with capture delay for failed attempts that will happen after maxCapturesBeforeDelay.

Delay for the next attempt is taken from the arrays as timeCaptureDelayArray[n maxCapturesBeforeDelay].

For all the attempts after the array length, the last item is taken as shown in the snippet:

Java
1List<Long> delayTimes = Arrays.asList(1L, 5L, 10L, 30L, 60L);
2((FaceCaptureHandler)captureHandler).setTimeCaptureDelayArray(delayTimes);

Get time to unlock capture

This provides information about the delay time before the user can retry (specified in seconds). A return value of 0 means that the capture is not blocked.

An example request is shown in the snippet:

Java
1((FaceCaptureHandler)handler).timeToUnlock();

Get liveness captures attempts left before delay

This provides information about the number of captures that can be completed before delay is initialized.

It returns the number of attempts before the capture will be blocked, as shown in the snippet:

Java
1handler.captureAttemptsLeft();

It returns 0 if the capture is blocked, and Int.MAX_VALUE if the capture delays are turned off.

VideoRecordingReadyForGenerationListener

This sets the listener for a document to get VideoRecording. This listener is called when recording is enabled. It is called on successful and failed capture.

Setting callback

Java
1captureHandler.setVideoRecordingReadyForGenerationListener(new VideoRecordingReadyForGenerationListener() {
2 @Override
3 public void videoRecordingReadyForGeneration(VideoRecording videoRecording) {
4 //Video recording object to generate video
5 }
6 });

Callback returns VideoRecording object to generate video from capture.

Use CR2D challenges

This is another type of challenge that contains target points and points controlled by the user. To use it, pass FaceLiveness.ACTIVE to the FaceCaptureOptions constructor.

This example sets CR2D in capture options as shown in the snippet:

Java
1FaceCaptureOptions options = new FaceCaptureOptions(FaceLiveness.ACTIVE);

Use passive liveness challenge

Passive mode checks liveness without user interaction (no head movement required). As in default mode, it requires only to show the face in front of the camera so that an image can be acquired. Special algorithms estimate if a user is a real person or not. To use this mode, pass FaceLiveness.PASSIVE to FaceCaptureOptions constructor.

This example sets Passive in the capture options as shown in the snippet"

Java
1FaceCaptureOptions options = new FaceCaptureOptions(FaceLiveness.PASSIVE);

Liveness security levels

In IFaceCaptureOptions you can set the liveness security strength. It is configured via the FaceLivenessSecurityLevel enum.

The liveness security levels are:

  • LOW
  • MEDIUM
  • HIGH recommended

Get debug data

You can save some capture data on the user device's memory. In some cases, keeping those files might help to solve issues.

Below is an example of how to configure the debug data options. The data can be found on the SD card in the SmartSDK_debug_data directory. An example is shown in the snippet:

Java
1[...]
2 DebugSettingsBuilder debugSettingsBuilder = new DebugSettingsBuilder();
3 debugSettingsBuilder.logLevel(logLevel)
4 .storingType(DataStoringType.LAST_SESSION_ONLY)
5 .recordRtv(DebugOption.DISABLED)
6 .recordPostMortemRtv(DebugOption.DISABLED)
7 .saveCapturedImages(DebugOption.DISABLED);
8 captureOptions.setDebugDataSettings(debugSettingsBuilder.build());

Note: DataStoringType can have two values: LAST_SESSION_ONLY or MULTIPLE_SESSIONS. The first overwrites data in a single directory. The second makes a separate directory per capture.

An option exists to store special .rtv files that help you understand what happens during a capture.

Note: Storing these files take a lot of space. LogLevel describes what part of the logs will be saved to a file. If needed, the integrator can also save captured images by enabling saveCapturedImages option.

FingerCapture handler

You must retrieve the capture handler through the Biometric Capture SDK entry point for BioCaptureHandler as shown in the snippet:

Java
1// Get activity from application
2 Activity activity = ...
3 // Populate a CaptureOptions object
4 IFingerCaptureOptions captureOptions = new FingerCaptureOptions();
5 captureOptions.setBioCaptureMode(BioCaptureMode.ONE_FINGER);
6 captureOptions.setLiveness(Liveness.MEDIUM);
7 captureOptions.setCamera(Camera.FRONT);
8 captureOptions.setCaptureTimeout(120);
9 captureOptions.setOverlay(Overlay.OFF);
10 //////////////////////////////////
11 //Get the biometric reference
12 IBiometricReference biometricReference = ...
13 captureOptions.setBiometricReference(biometricReference);
14 //////////////////////////////////
15 BioSdk.createFingerCaptureHandler(activity, captureOptions, new MscAsyncCallbacks<IFingerCaptureHandler>() {
16 @Override
17 public void onPreExecute() {
18 // Optional hook on the builtin Android AsyncTask call-back `onPreExecute`
19 }
20
21 @Override
22 public void onSuccess(IFingerCaptureHandler result) {
23 // Indicates that initialization succeeded, the returned handler can be used to start the capture.
24 fingerCaptureHandler = result;
25 }
26 public void onError(BioCaptureHandlerError e) {
27 // An error has occurred during the initialization
28 }
29});

Note: It extends from BioCaptureHandler.

Capture result listener

This sets the listener to receive the finger captures. Hand and fingerprints images callback will be fired when the capture finishes.

Java
1fingerCaptureHandler.setFingerCaptureResultListener(new FingerCaptureResultListener() {
2 @Override
3 public void onCaptureSuccess(@NotNull List<MorphoImage> images,
4 @NotNull FingerCaptureResult captureResult) {
5 }
6 public void onCaptureFailure(@NotNull CaptureError captureError,
7 @NotNull IBiometricInfo biometricInfo,
8 @NotNull Bundle extraInfo) {
9 }
10 });
onCaptureSuccess
Called when captured successfully finishes
images List<MorphoImage>List of captured fingerprints images
captureResult FingerCaptureResultHolds information about the capture, like liveness
FingerCaptureResult
getLivenessResult FingerLivenessResultResolution of capture liveness: LIVE,FAKE,NO_DECISION
getScore doubleDeprecated Finger capture liveness score
onCaptureFailure
Called when capture fails
captureError CaptureErrorReason of capture failure
biometricInfo IBiometricInfoBiometric information about location and classification
extraInfo BundleHolds capture extra info: capture delay date

setAuthenthicationListener

This is the listener to receive the callbacks related to the authentication process.

This is only compatible with AUTHENTICATION.

An example snippet is shown.

Java
1fingerCaptureHandler.setAuthenthicationListener(new BioCaptureAuthenticationListener() {
2 @Override
3 public void onAuthenticationResult(IAuthenticationResult authenticationResult) {
4 String message = getString(R.string.authentication_process);
5 message +="\n" + getString(R.string.score)+ " " +authenticationResult.getScore();
6 message +="\n" + getString(R.string.status)+ " " +authenticationResult.getStatus();
7 Toast.makeText(this, message, Toast.LENGTH_LONG).show();
8 }
9 });

Indication of optimal fingerprint distance

Methods described below may be used to improve user experience of fingerprint acquisition. They works only with specific, calibrated devices.

getCaptureDistanceRange

Returns CaptureDistanceRangeResult, which may be one of the following:

CaptureDistanceRangeSuccess
Returned if the device is calibrated for finger distance management feature
captureDistanceRange CaptureDistanceRangeContains optimal distance ranges between the fingers and the lens
CaptureDistanceRangeUnavailable
Returned if the device is not calibrated for finger distance management feature or any other error has occurred
reason StringThe reason of the distance range unavailibility, e.g. "The device is not calibrated for this feature"
CaptureDistanceRange
rangeMin floatMinimum value that may be returned in _FingerCaptureCurrentDistanceListener. Should be equal to 0.0
optimalMin floatLower boundary of optimal distance between the phone and the fingers
optimalMax floatUpper boundary of optimal distance between the phone and the fingers
rangeMax floatMaximum value that may be returned in FingerCaptureCurrentDistanceListener. Should be equal to 1.0

setFingerCaptureCurrentDistanceListener

To receive the feedback about current distance between the fingers and the phone lens (e.g in order to create your own optimal distance indicator on UI), you should register listener as shown in the snippet:

1 captureHandler.setFingerCaptureCurrentDistanceListener(new FingerCaptureCurrentDistanceListener() {
2 @Override
3 public void onCurrentCaptureDistance(@NonNull CurrentCaptureDistance currentCaptureDistance) {
4 //handle currentCaptureDistance
5 }
6 });
onCurrentCaptureDistance
Called when the distance between the fingers and the phone lens changes
currentCaptureDistance CurrentCaptureDistanceContains the distance between the phone lens and the fingers
CurrentCaptureDistance
value floatValue of the distance between the phone lens and the fingers. This value is between rangeMin and rangeMax from CaptureDistanceRange. To indicate the correctness of the distance between the fingers and the phone camera you should check if it is between optimalMin and optimalMax.

setFingerCaptureFeedbackListener

Returns feedback associated with finger capture (for example if the distance between the phone lens and the fingers is optimal). Snippet below shows how to register the listener:

1 captureHandler.setFingerCaptureFeedbackListener(new FingerCaptureFeedbackListener() {
2 @Override
3 public void onCurrentCaptureDistance(@NonNull captureInfo: FingerCaptureInfo) {
4 //handle captureInfo
5 }
6 });
onCaptureInfo
captureInfo FingerCaptureInfo_Information whether the distance between the fingers and the phone lens is correct. It may be OPTIMAL, TOO_CLOSE or TOO_FAR

BioMatcher handler

This interface provides all the necessary helper methods to perform all the matching, identifying, and template coding operations.

Authenticate

This verifies a list of candidate templates against a list of reference templates. This method can be used to authenticate users.

Note: Review the use cases named Authenticate.

An example snippet is shown:

Java
1//Authentication options
2IAuthenticationOptions authenticationOptions = new AuthenticationOptions();
3authenticationOptions.setThreshold(3500);
4
5//Biometric candidate
6IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FACE);
7//We add all the templates for this candidate
8biometricCandidate.addTemplates(candidates);
9
10//Biometric references
11IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FACE);
12//We add all the templates for this user
13biometricReference.addTemplates(references);
14
15matcherHandler.authenticate(authenticationOptions, biometricCandidate, biometricReference, new BioMatcherAsyncCallbacks<IAuthenticationResult>() {
16 @Override
17 public void onPreExecute() {
18 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
19 }
20
21 @Override
22 public void onSuccess(IAuthenticationResult result) {
23 //The result of the authentication
24 long resultScore = result.getScore();
25 //authentication status (FAILURE, SUCCESS...)
26 AuthenticationStatus authenticationStatus = authenticationResult.getStatus();
27 }
28
29 @Override
30 public void onError(Exception e) {
31 // An error has occurred
32 }
33});

Function

Java
1void authenticate(IAuthenticationOptions authenticationOptions, IBiometricCandidate biometricCandidate, IBiometricReference biometricReference, BioMatcherAsyncCallbacks<IAuthenticationResult> callbacks);
Parameter
Description
authenticationOptions IAuthenticationOptionsThe options used to perform the authentication.
biometricCandidate IBiometricCandidateIt contains the list of templates that you want to match.
biometricReference IBiometricReferenceIt contains the list of templates that you want to use as reference, each of one has the userUUID to which they belong.
callbacks BioMatcherAsyncCallbacksCallbacks to be executed depending on the result; refer to IAuthenticationResult.

Errors

You will receive an exception reporting the error.

Authenticate synchronous

This verifies a list of candidate templates against a list of reference templates. This method can be used to authenticate users.

Note: This function must be executed in a different thread than the UI. Check the use cases named Authenticate.

An example snippet is shown:

Java
1//Authentication options
2IAuthenticationOptions authenticationOptions = new AuthenticationOptions();
3authenticationOptions.setThreshold(3500);
4
5//Biometric candidate
6IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FACE);
7//We add all the templates for this candidate
8biometricCandidate.addTemplates(candidates);
9
10//Biometric references
11IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FACE);
12//We add all the templates for this user
13biometricReference.addTemplates(references);
14
15IAuthenticationResult result = matcherHandler.authenticate(authenticationOptions, biometricCandidate, biometricReference);
16/The result of the authentication
17long resultScore = result.getScore();
18//authentication status (FAILURE, SUCCESS...)
19AuthenticationStatus authenticationStatus = authenticationResult.getStatus();

Function

An example snippet is shown.

Java
1IAuthenticationResult authenticate(IAuthenticationOptions authenticationOptions, IBiometricCandidate biometricCandidate, IBiometricReference biometricReference);
Parameter
Description
authenticationOptions IAuthenticationOptionsThe options used to perform the authentication.
biometricCandidate IBiometricCandidateContains the list of templates that you want to match.
biometricReference IBiometricReferenceContains the list of templates that you want to use as reference; each has the userUUID to which they belong.

Errors

You will receive an exception reporting the error.

Identify

This method can be used to identify users. It identifies the user from the list of candidate templates that are matched against the list of reference templates.

Note: Check the use case named Identify.

An example snippet is shown:

Java
1//Identification options
2IIdentificationOptions identificationOptions = new IdentificationOptions();
3
4//Biometric candidate
5IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FACE);
6//We add all the templates for this candidate
7biometricCandidate.addTemplates(candidates);
8
9//We create the list of references
10ArrayList<IBiometricReference> biometricReferences = new ArrayList<IBiometricReference>();
11//Biometric reference for one user
12IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FACE);
13//We add all the templates for this user
14biometricReference.addTemplates(references);
15
16//We add the user to the list
17biometricReferences.add(biometricReference);
18
19matcherHandler.identify(identificationOptions, biometricCandidate, biometricReferences, new BioMatcherAsyncCallbacks<IIdentificationResult>() {
20 @Override
21 public void onPreExecute() {
22 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
23 }
24
25 @Override
26 public void onSuccess(IIdentificationResult result) {
27 //The identification result
28 List<IIdentificationCandidate> candidates = result.getIdentificationCandidateList();
29 if(candidates.size()>0){
30 IIdentificationCandidate candidate = candidates.get(0);
31 UUID userUUID = candidate.getUuid();
32 long candidateScore = candidate.getScore();
33 }
34
35 }
36
37 @Override
38 public void onError(Exception e) {
39 // An error has occurred
40 }
41});

Function

An example snippet is shown.

Java
1void identify(IIdentificationOptions identificationOptions, IBiometricCandidate biometricCandidate, List<IBiometricReference> biometricReferences, BioMatcherAsyncCallbacks<IIdentificationResult> callbacks);
Parameter
Description
identificationOptions IIdentificationOptionsThe options used to perform the identification
biometricCandidate IBiometricCandidateContains the list of templates that you want to match
biometricReferences List<IBiometricReference>Contains the list of references against you will identify your candidate—check IBiometricReference
callbacks BioMatcherAsyncCallbacksCallbacks to be executed depending on the result—check IIdentificationResult

Errors

You will receive an exception reporting the error.

Identify synchronous

This method can be used to identify users.

It identifies the user from the list of candidate templates that are matched against a list of reference templates.

Note: This function must be executed in a different thread than UI. Check the use case named Identify.

An example snippet is shown.

Java
1//Identification options
2IIdentificationOptions identificationOptions = new IdentificationOptions();
3
4//Biometric candidate
5IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FACE);
6//We add all the templates for this candidate
7biometricCandidate.addTemplates(candidates);
8
9//We create the list of references
10ArrayList<IBiometricReference> biometricReferences = new ArrayList<IBiometricReference>();
11//Biometric reference for one user
12IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FACE);
13//We add all the templates for this user
14biometricReference.addTemplates(references);
15
16//We add the user to the list
17biometricReferences.add(biometricReference);
18
19IIdentificationResult result = matcherHandler.identify(identificationOptions, biometricCandidate, biometricReferences)
20//The identification result
21List<IIdentificationCandidate> candidates = result.getIdentificationCandidateList();
22if(candidates.size()>0){
23 IIdentificationCandidate candidate = candidates.get(0);
24 UUID userUUID = candidate.getUuid();
25 long candidateScore = candidate.getScore();
26}

Function

An example snippet is shown.

Java
1IIdentificationResult identify(IIdentificationOptions identificationOptions, IBiometricCandidate biometricCandidate, List<IBiometricReference> biometricReferences);
Parameter
Description
identificationOptions IIdentificationOptionsThe options used to perform the identification.
biometricCandidate IBiometricCandidateContains the list of templates that you want to match.
biometricReferences List<IBiometricReference>Contains the list of references against which you will identify your candidate; refer to IBiometricReference

Errors

You will receive an exception reporting the error.

Detect biometrics

This allows you to detect the biometrics in a MorphoImage.

This function extracts all the biometric templates contained in an image (such as, all the faces that are in an image).

Note: Check the use case named Detect Biometric.

Java
1//Create a populate options
2 IDetectBiometricOptions detectBiometricsOptions = new DetectBiometricsOptions();
3 detectBiometricsOptions.setBiometricLocation(BiometricLocation.FACE_FRONTAL);
4 detectBiometricsOptions.setBiometricModality(BiometricModality.FACE);
5
6 bioMatcherHandler.detectBiometric(detectBiometricsOptions, image, new BioMatcherAsyncCallbacks<List<IMorphoTemplate>>() {
7 @Override
8 public void onPreExecute() {
9 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
10 }
11
12 @Override
13 public void onSuccess(List<IMorphoTemplate> result) {
14 //A List of templates extracted from the image
15 }
16
17 @Override
18 public void onError(Exception e) {
19 // An error has occurred
20 }
21 });

Function

An example snippet is shown.

Java
1public void detectBiometric(final IDetectBiometricOptions detectBiometricsOptions, final IImage image, BioMatcherAsyncCallbacks<List<IMorphoTemplate>> callbacks)
Parameter
Description
detectBiometricsOptions IDetectBiometricOptionsThe options used during the detection process.
image IImageThe image.
callbacks BioMatcherAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Detect biometric synchronous

This allows you to detect the biometrics in a MorphoImage.

This function extracts all the biometric templates contained in an image (such as, all the faces that are in an image).

Note: This function must be executed in a different thread than the UI. Check the use case named Detect Biometric.

An example snippet is shown.

Java
1/Create a populate options
2IDetectBiometricOptions detectBiometricsOptions = new DetectBiometricsOptions();
3detectBiometricsOptions.setBiometricLocation(BiometricLocation.FACE_FRONTAL);
4detectBiometricsOptions.setBiometricModality(BiometricModality.FACE);
5
6List<IMorphoTemplate> templates = bioMatcherHandler.detectBiometric(detectBiometricsOptions, image)
7/A List of templates extracted from the image

Function

An example snippet is shown.

Java
1public List<IMorphoTemplate> detectBiometric(final IDetectBiometricOptions detectBiometricsOptions, final IImage image)
Parameter
Description
detectBiometricsOptions IDetectBiometricOptionsThe options to use during the detection process.
image IImageThe image.

Errors

You will receive an exception reporting the error.

Destroy

This releases all the handler resources as shown in the snippet:

Java
1handler.destroy();

Image utils 

The image utility performs all the format conversions needed to implement an app.

Converting Morpho Image Y800 to ARGB8888 

This function converts a Morpho Image encoded in Y800 to a bitmap encoded in ARGB888.

Java
1ImageUtils.morphoImageY800ToARGB8888(getApplicationContext(), morphoImage, new ImageUtilsAsyncCallbacks<Bitmap>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(Bitmap bitmap) {
9 //The image in ARGB8888
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred
15 }
16 });

Function

Java
1public static void morphoImageY800ToARGB8888(final Context context, final MorphoImage image, ImageUtilsAsyncCallbacks<Bitmap> callbacks);
Parameter
Description
context ContextThe Android context.
image MorphoImageThe image.
callbacks ImageUtilsAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Converting Bitmap to Morpho Image Y800 

This function converts a bitmap into a Morpho Image encoded in Y800.

Note: It is the developer's responsibility to fill in the properties for BiometricLocation and BiometricModality.

Java
1ImageUtils.bitmapToMorphoImageY800(getApplicationContext(), bitmap, new ImageUtilsAsyncCallbacks<MorphoImage>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(MorphoImage image) {
9 //Remember to configure the Morpho Image
10 image.setBiometricModality(BiometricModality.FACE);
11 image.setBiometricLocation(BiometricLocation.FACE_FRONTAL);
12 }
13
14 @Override
15 public void onError(Exception e) {
16 // An error has occurred
17 }
18 });

Function

Java
1public static void bitmapToMorphoImageY800(final Context context, final Bitmap image, ImageUtilsAsyncCallbacks<MorphoImage> callbacks);
Parameter
Description
context ContextThe Android context.
image BitmapThe image.
callbacks ImageUtilsAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You receive an exception reporting the error.

Compressing bitmap to a maximum desired size 

This function converts a bitmap to a desired size in kilobytes (KB). Although you can convert the bitmap into the maximum size, you are not required to. This function works if you convert to less than the maximum size.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1//Maximum size 500 KB
2 Bitmap compressed = ImageUtils.compressBitmap(bitmap, 500);

Function

Java
1public static Bitmap compressBitmap(Bitmap srcBitmap, int maxSize) throws IllegalArgumentException;
Parameter
Description
srcBitmap BitmapThe image.
maxSize intThe maximum size desired in KB.

Errors

You receive an exception reporting the error.

Resize a bitmap to a maximum side length 

This converts a bitmap to a desired length in pixels. Although you can convert the bitmap into the maximum desired side length, you are not required to. This function works if you convert to less than the maximum side length.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1//Maximum size 500 px
2 Bitmap resized = ImageUtils.resizeBitmap(bitmap, 500);

Function

Java
1public static Bitmap resizeBitmap(Bitmap srcBitmap, int maxSideLengthInPixels) throws IllegalArgumentException;
Parameter
Description
srcBitmap BitmapThe image.
maxSideLengthInPixels intMaximum side length in pixels.

Errors

You receive an exception reporting the error.

Compress and resize an IImage 

This function compresses and resizes an image to a desired size in kilobytes (KB) and a maximum length in pixels. The resizing keeps the aspect ratio. You can use this to compress and resize the image to a size less than your previously determined maximum size. The returned data will be a JPEG image as a byte[].

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1//Maximum pixel length is 3000 pixels
2 //Maximum size 500 KB
3 byte[] jpegImage = ImageUtils.resizeAndCompressToByteArray(image, 3000, 500); //returned image in jpeg format as byte[]

Function

Java
1public static byte[] resizeAndCompressToByteArray(IImage image, int maxSideLengthInPixels, int maxSizeInKB) throws Exception;
Parameter
Description
image IImageThe image.
maxSideLengthInPixels intMaximum side length desired in pixels.
maxSizeInKB intThe maximum size desired in KB.

Errors

You receive an exception reporting the error.

Cropping an IImage 

This function crops an image. The returned data will be the same kind of IImage as the source image.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1IImage iImage = ImageUtils.doCrop(image, documentRegion.getPoint1().x, documentRegion.getPoint1().y, documentRegion.getPoint3().x, documentRegion.getPoint3().y);

Function

Java
1public static IImage doCrop(IImage srcImage, double topLeftX, double topLeftY, double bottomRightX, double bottomRightY) throws Exception;
Parameter
Description
srcImage IImageThe image.
topLeftX doubleThe top left position X coordinate.
topLeftY doubleThe top left position Y coordinate.
bottomRightX doubleThe bottom right position X coordinate.
bottomRightY doubleThe bottom right position Y coordinate.

Errors

You receive an exception reporting the error.

Rotating an IImage 

This function rotates an image. The returned data will be the same kind of IImage as the source image.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1IImage iImage = ImageUtils.doRotation(image, 90);

Function

Java
1public static IImage doRotation(IImage srcImage, float degrees) throws Exception;
Parameter
Description
srcImage IImageThe image.
degrees floatThe degrees to rotate.

Errors

You receive an exception reporting the error.

Flipping an IImage 

This function flips an image. The returned data will be the same kind of IImage as the source image.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1IImage iImage = ImageUtils.doFlip(image, FlipType.LI_F_BOTH);

Function

Java
1public static IImage doFlip(IImage srcImage, FlipType flipType) throws Exception;
Parameter
Description
srcImage IImageThe image.
flipType FlipTypeThe flip type.

Errors

You receive an exception reporting the error.

Converting raw images to JPEG 2000 

This function converts raw images to JPEG 2000. The returned data will be the same kind of IImage as the source image.

Only fingerprint images should be used in this method.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1IImage iImage = ImageUtils.toJPG2000(image, false);

Function

Java
1public static IImage toJPG2000(IImage srcImage, boolean isLatent) throws Exception;
Parameter
Description
srcImage IImageThe image in raw format.
isLatent booleanFalse for Rolled, Flat, Slap (Card scan, Live scan, Mobile ID credential, and palm). True for Latent.

Errors

You receive an exception reporting the error.

Converting Raw Images to JPEG 2000 with Maximum Size 

This function converts raw images to JPEG 2000. The returned data will be the same kind of IImage as the source image.

Only fingerprint images should be used in this method.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1IImage iImage = ImageUtils.toJPG2000(image, 102400);

Function

Java
1public static IImage toJPG2000(IImage srcImage, int outputMaximumSizeInBytes) throws Exception;
Parameter
Description
srcImage IImageThe image in raw format.
outputMaximumSizeInBytes intMaximum size (in bytes) of the output compressed buffer.

Errors

You receive an exception reporting the error.

Converting raw images to WSQ 

This function will convert raw images to WSQ. The returned data will be the same kind of IImage as the source image.

Required for this function:

  • Resolution of the image must be 500 dpi.
  • Number of rows in the image must be between 64 and 20000.
  • Number of columns in the image must be between 64 and 20000.

Only fingerprint images should be used in this method.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1IImage iImage = ImageUtils.toWSQ(srcImage, 15, (byte) 0, (byte) 0xff);

Function

Java
1public static IImage toWSQ(IImage srcImage, float compressionRatio, byte scannerBlack, byte scannerWhite) throws java.lang.Exception;
Parameter
Description
srcImage IImageThe image in raw format.
compressionRatio floatMaximum size (in bytes) of the output compressed buffer.
scannerBlack byteBLACK calibration value (if unknown, use 0)
scannerWhite byteWHITE calibration value (if unknown, use 255)

Errors

You receive an exception reporting the error.

Extracting images 

This method extracts the images encoded by the location coordinates of a DocumentImage, if rectification is disabled during a capture. The returned data will be a list of cropped images from the original image.

This function is intended to be used if Rectification is disabled during the capture of a document.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1List<DocumentImage> iImages = ImageUtils.extractImages(srcImage);

Function

Java
1public static List<DocumentImage> extractImages(DocumentImage srcImage) throws java.lang.Exception;
Parameter
Description
srcImage IImageThe image in raw format that contains the location coordinates (areas to be cropped).

Errors

You receive an exception reporting the error.

Resizing bitmap to IDEMIA standards 

This method eases integration with IDEMIA servers. The returned data is an image scaled to the proper format, depending on the input parameters.

This function is intended to be used before an image is send to IDEMIA servers.

Note: This function should be executed in a different window or thread than the UI as it can consume substantial resources.

Java
1Bitmap result = ImageUtils.resizeBitmap(srcImage, UseCase.BIOMETRIC, DocumentType.SELFIE, false);

Function

Java
1public static Bitmap resizeBitmap(Bitmap srcBitmap, UseCase useCase, DocumentType documentType, boolean isCropped) throws IllegalArgumentException;
Parameter
Description
srcImage BitmapThe source image to resize.
useCase UseCaseThe use case.
documentType DocumentTypeThe type of document.
isCropped booleanTrue the document has been cropped, false otherwise.

Errors

You receive an exception reporting the error.

Helper objects 

This section describes the helper objects that are necessary to use the Biometric Capture SDK.

IBioSdkInfo

This object exposes information about the SDK.

Parameter
Description
version StringThe version of the SDK

IBioMatcherSettings

This object is used to configure the behavior of BioMatcher.

Attribute
Description
debugDataSettings DebugDataSettingsSets options used for preparing debug data dump
fingerTemplateFormat MorphoFingerTemplateFormatFinger template format, only used for fingerprints—default format is PKLITE

ICaptureOptions

This object is used to configure the behavior of Capture.

Attribute
Description
camera CameraThe app camera option to configure BioCapture.
torch TorchSets the torch value.
overlay OverlaySets the overlay value.
captureTimeout LongCapture timeout in seconds (default value 120).
logLevel LogLevelSets the log level.
DebugDataSettings Debug DataSets debug data options that stores key information about capture on the device's memory.

FaceCaptureOptions

This object used to configure the behavior of FaceCapture. It extends from CaptureOptions.

Attribute
Description
seed intFor CR2D sets dots seed
liveness FaceLivenessSet challenge for face
securityLevel FaceLivenessSecurityLevelSet liveness security
videoRecordingOptions VideoRecordingOptionsWhen enabled, CaptureSDK returns VideoRecording to generate video from a taken capture. (By default video recording is turned off)

FingerCaptureOptions

This object is used to configure the behavior of FingerCapture. It extends from CaptureOptions.

Attribute
Description
biometricReference IBiometricReferenceThe biometric reference to use during the finger authentication. Only compatible with capture mode AUTHENTICATION. Check IBiometricReference.
threshold longSet threshold for finger capture with success
crossMatchingVerificationThreshold longDeprecated Used for verification mechanism to set threshold
liveness FingerLivenessSet liveness security
bioCaptureMode BioCaptureModeSet capture mode for finger
numberOfFingers intSet how many fingers need be to captured. Only compatible with FINGERS. Obsolete
amputeeFingers AmputeeFingersSet which fingers Person does not have. Only compatible with FINGERS.
hand HandSet which hand will be scanned
UHDResolutionEnabled booleanEnables or disables capture in 4K (Feature for testing. Development using 4k resolution is not ready for use.)

Warning: UHD resolution is not working properly for all devices, it is in experimental state.

IBiometricSet

This is a common interface that all the candidates and references that perform authentication and identification operations extend.

Parameter
Description
templates List<IMorphoTemplate>The Biometric templates; refer to IMorphoTemplate
biometricModality BiometricModalityThe BiometricModality enum option.

IBiometricCandidate

This is a common interface that all the candidates extend. It extends IBiometricSet.

IBiometricReference

This is a common interface that all the references used to perform an authentication or identification extend. It extends IBiometricSet.

Parameter
Description
userUuid UUIDUser uuid

IBiometricInfo

This is a common interface that all the different Biometrics implement.

Parameter
Description
biometricLocation BiometricLocationThe BiometricLocation enum option.
biometricModality BiometricModalityThe BiometricModality enum option.

BiometricInfo

This is a common object that all the different Biometrics extend. It implements the interface IBiometricInfo.

IImage

This is an image interface that the SDK image objects will extend.

Parameter
Description
buffer byte[]The image
stride intThe stride of the biometric
width longThe width of the image
height longThe height of the image
colorSpace ColorSpaceThe colorspace of the image
resolution floatThe resolution of the image.
imageQuality intImage quality if available, otherwise -1. Currently only available for fingerprint images.
label StringLabel associated to this image, if any. It can be null.
toJPEG byte[]Retrieves the image as a JPEG image with default quality. Default for finger is 90%. Default for finger is 80%. Created JPEG for face will contain capture maker note data inside EXIF metadata containing information such as for example SDK version used for capturing the image.
toJPEG(float quality)Retrieves the image as a JPEG image with quality equal from 0 to 1. Created JPEG for face will contain capture maker note data inside EXIF metadata containing information such as for example SDK version used for capturing the image.

MorphoImage

This is the image object returned by the SDK. It extends BiometricInfo and implements IImage.

Metadata

This is low level data information about capture for verification.

Description
getData() byte[]The information about capture.
encrypt(String random, List<String> certificates) EncryptedDataThe encrypted data.

EncryptedMetadata

This is low level encrypted data information about Capture for verification.

Function name
Description
getEncryptedData() byte[]The information about capture.

FingerTracking

This is a finger tracking object returned by the FingerCaptureTrackingListener.

Parameter
Description
rect RectThe position of the biometric.
previewRect RectThe original preview size to which the coordinates are referred.
orientation IntOrientation of finger in degrees
quality FingerQualityQuality of finger

FingerQuality enum

This enum retrieves information about quality of the face saved in template.

Attribute
Description
UNAVAILABLEThe quality is unavailable because the acquisition process is still ongoing.
LOWA low-quality fingerprint is a fingerprint image that lacks clarity and detail.
MEDIUMA medium-quality fingerprint is a fingerprint image that captures a fair amount of detail.
HIGHA high-quality fingerprint is a fingerprint image that is exceptionally clear and detailed, with distinct ridge patterns and minimal noise or distortion. This level of quality ensures the most reliable and accurate identification.

FaceTracking

This is a face tracking object returned by the FaceCaptureTrackingListener.

Parameter
Description
rect RectThe position of the biometric.
previewRect RectThe original preview size to which the coordinates are referred.

OvalOverlay

Information about oval overlay that might help user to position face correctly in front of camera. Keep in mind these numbers are relative to preview image size. If you want to display some UI elements helping user to place his face, using UIExtensions library is recommended. Otherwise you have to rescale these coordinates by your own to fit your view.

Parameter
Description
width floatThe width length of the oval.
height floatThe height length of the oval.
centerX floatThe position x of oval center.
centerY floatThe position y of oval center.

IMorphoTemplate

This is the biometric template object returned by the SDK. It extends IBiometricInfo.

Parameter
Description
buffer byte[]The template.
uuid UUIDThe template uuid in the database (Can be null).
uuidUser UUIDThe user uuid (Can be null).

IMorphoFaceTemplate

This is the biometric face template object returned by the SDK. It extends IMorphoTemplate.

Parameter
Description
eyesPosition List<IEyePosition>The eyes position; refer to IEyePosition
templateFormat MorphoFaceTemplateFormatThe template format; refer to MorphoFaceTemplateFormat.
qualityRawValue short
quality FaceTemplateQuality

IMorphoFingerTemplate

This is the biometric finger template object returned by the SDK. It extends IMorphoTemplate.

Parameter
Description
fingerPosition IFingerPositionThe finger position.
templateFormat MorphoFingerTemplateFormatThe template format–check MorphoFingerTemplateFormat

AmputeeFingers

This is information for capture which fingers the user is missing.

Description
addMissingFinger() FingerAdd amputated finger to list of amputated fingers
clearMissingFingers()Clear list of amputated fingers
getMissingFingers() List<Finger>Get list of amputated fingers

onTracking

This is invoked multiple times by BioCapture to send feedback about the biometric positions to the app.

Function

An example snippet is shown:

Java
1public void onTracking(List<MorphoBioTraking> trackingInfo);

Arguments

Parameter
Description
trackingInfo List<MorphoBioTraking>The list of tracking info.

CaptureListener

This is a generic capture listener.

onCaptureFinish

This is invoked by BioCapture when the capture finishes.

Function

An example snippet is shown:

Java
1void onCaptureFinish()

VideoRecordingOptions

This object is used to configure the behavior of the VideoRecording. You cannot generate two or more videos at the same time.

Parameter
Description
recordingEnable booleanEnable video recording

VideoRecording

This object is used to generate video in MP4 format. On success it returns a path to the video. You can generate only one video.

Java
1videoRecording.generateVideo(new VideoProgressListener() {
2
3 @Overide
4 void onFinish(String path) {
5 //When creating video comlete with success return path to video
6 }
7
8 @Overide
9 void progress(int progress) {
10 //Showing progress of generating video from 0 to 100
11 }
12
13 @Overide
14 void onError(VideoError error) {
15 //It's call when generating video failed or another video is current generating
16 }
17});

If you do not want to generate video from a previous capture, use:

Java
1videoRecording.clean()

BioCaptureCR2DListener

This listener receives information about CR2D challenge objects.

onCurrentUpdated

This is called every time the current point changes. Cr2dCurrentPoint is an object with information about user position during the challenge.

Java
1void onCurrentUpdated(Cr2dCurrentPoint currentPoint);

onTargetUpdated

This is called every time the target changes. Cr2dTargetPoint is the object with information about a specific target in a challenge. Each target has a unique number. This method is called once per specific target update.

Java
1void onTargetUpdated(Cr2dTargetPoint targetPoint);

onTargetsConditionUpdated

This is called every time the condition of targets changes, where targetCount is the amount of all targets in a challenge. targetStability is the stability for the current target in a challenge (possible value is from 0 to 100).

Java
1void onTargetsConditionUpdated(int targetCount, int targetStability);

BioCaptureResultListener

The capture listener is where the app is going to receive the captured images. It extends CaptureListener.

onCaptureSuccess

This is invoked if BioCapture has a successful capture.

Function

Java
1void onCaptureSuccess(List<MorphoImage> imageList);

Arguments

Parameter
Description
imageList List<MorphoImage>The list of biometric images.

onCaptureFailure

This is invoked if BioCapture fails to capture.

Function

An example snippet is shown:

Java
1void onCaptureFailure(CaptureError captureError, IBiometricInfo biometricInfo, Bundle extraInfo);

Arguments

Parameter
Description
captureError CaptureErrorThe capture error to show why it fails.
biometricInfo IBiometricInfoThe Biometric information.
extraInfo BundleAdditional Biometric information.

The possible keys for extraInfo are:

  • delayedUntil (Date formatted as a ISO8601 string). This key will tell you when the capture will not be blocked.

FaceCaptureFeedbackListener

This is the capture feedback listener. It enables the app to receive feedback about the biometric captures, like moving your head to the left.

onCaptureInfo

This is invoked multiple times by BioCapture to send feedback about the capture process to the app.

Function

An example snippet is shown.

Java
1void onCaptureInfo(FaceCaptureInfo captureInfo);

Arguments

Parameter
Description
faceCaptureInfo FaceCaptureInfoThe feedback.

IDetectBiometricOptions

This interface represents the verification options. This interface extends IBiometricInfo.

Parameter
Description
isTemplateCompressionEnabled booleanEnables or disables the template compression. For the moment this feature is only available for face.

IMatchingOptions

This interface represents the basic matching options.

Parameter
Description
biometricModality BiometricModalityThe BiometricModality enum option

IAuthenticationOptions

This is the interface that represents the authentication options. This interface extends IMatchingOptions.

The matching result is a score that reflects the similarity of two biometrics acquisitions. The threshold is the score value that is used to differentiate a HIT from a NOHIT.

Threshold choice is a compromise between FAR (False Acceptance Rate) and FRR (False Reject Rate).

FAR is the proportion of requests that generate an unexpected HIT with two biometrics acquisitions of two different persons.

FRR is the proportion of requests that generate an unexpected NOHIT with two biometrics acquisitions of the same person.

IDEMIA algorithms

The recognition algorithm similarity matching score is linked with the FAR (as previously defined):

FAR
Score
1%2500
0.1%3000
0.01%3500
0.001%4000
0.0001%4500
0.00001%5000
Parameter
Description
threshold longThe authentication threshold to be considered valid.

IAuthenticationResult

This is the interface that represents an authentication result.

Parameter
Description
score longThe authentication score (between 0 - 50000).
authenticationStatus AuthenticationStatusThe authentication status.

IIdentificationOptions

This is the interface that represents the identification options. This interface extends IMatchingOptions.

IIdentificationResult

This is the interface that represents an identification result.

Parameter
Description
candidateList List<IIdentificationCandidate>The authentication result; refer to IIdentificationCandidate.

IIdentificationCandidate

This is the Interface that represents a candidate result.

Parameter
Description
uuid UUIDThe candidate uuid.
score longThe identification score result.

Enums 

FaceLiveness enum

This enum describes liveness verification mode.

Attribute
Description
NO_LIVENESSNo liveness detection is performed during capture.
ACTIVETriggers a more complex challenge to detect liveness.
PASSIVELiveness is detected without a user challenge—the user is unaware that liveness detection is being employed.
PASSIVE_VIDEOFace is detected without any challenge and effort by the user. Liveness detection is done on server site. Works only with RemoteCaptureHandler(DEPRECATED) and RemoteLiveness

FingerLiveness enum

This enum describes the verification strength for finger liveness capture.

Attribute
Description
NO_LIVENESSNo finger liveness detection is performed during capture
VERY_LOWEasiest finger liveness mode to pass
LOWMore restrictive finger liveness verification
MEDIUMRecommended liveness mode for finger liveness capture

Hand enum

This enum describes the captured hand for finger liveness capture.

Attribute
Description
RIGHTHand right
LEFTHand Left

Finger enum

Attribute
Description
INDEXIndex finger
MIDDLEMiddle finger
RINGRing finger
LITTLELittle finger

FaceLivenessSecurityLevel enum

Security level for face liveness capture. Defines how restrictive the liveness verification will be. The higher the level is set, the more restrictive the verification will be.

Attribute
Description
LOW
MEDIUM
HIGH Recommended level

FaceLivenessResult enum

This enum represents the result of a face liveness check.

Attribute
Description
UNKNOWNUnable to define or liveness is turned off
LIVELiveness success - a living person is detected
FAKELiveness check failure - not a living person
NO_DECISIONWebBioServer is needed to make a decision

FingerLivenessResult enum

This enum represents the result of a finger liveness check.

Attribute
Description
LIVELiveness success - real fingers are detected
FAKELiveness check failure - not real fingers
NO_DECISIONWebBioServer is needed to make a decision

ColorSpace enum

Attribute
Description
Y8Grayscale 8bpp image.
Y16LEGrayscale 16bpp image (Little Endian).
BGR24Color 24bpp BGR image (BMP like memory layout).
RGB24Color 24bpp RGB image (reversed memory layout compared to RT_COLORSPACE_BGR24).

FaceCaptureInfo enum

Attribute
Description
INFO_GET_OUT_FIELDUser must move out of the camera field
INFO_COME_BACK_FIELDUser must move back into the camera field
INFO_TURN_LEFTUser must turn head left
INFO_TURN_RIGHTUser must turn head right
INFO_CENTER_TURN_LEFTUser must face center but turn head left
INFO_CENTER_TURN_RIGHTUser must face center but turn head right
INFO_CENTER_ROTATE_DOWNUser must face center but rotate head down
INFO_CENTER_ROTATE_UPUser must face center but rotate head up
INFO_CENTER_TILT_LEFTUser must face center but tilt head left
INFO_CENTER_TILT_RIGHTUser must face center but tilt head right
INFO_CENTER_MOVE_FORWARDSUser must move forwards
INFO_CENTER_MOVE_BACKWARDSUser must move backwards
INFO_CENTER_LOOK_FRONT_OF_CAMERAUser must look in front of the camera
INFO_CENTER_LOOK_CAMERA_WITH_LESS_MOVEMENTUser must look at the camera with less movement
INFO_TURN_LEFTRIGHTUser must turn left, then right or right, then left
INFO_TURN_DOWNUser must turn head down
INFO_TOO_FASTUser is moving his/her head too fast
INFO_NOT_MOVINGFace movement not detected
DEVICE_MOVEMENT_ROTATIONSmartphone movement detected (the user is moving his/her smartphone and not his/her face)

FingerCaptureInfo enum

Attribute
Description
OPTIMALThe user's fingers are in optimal distance from the phone lens
TOO_CLOSEUser should move the fingers further
TOO_FARUser should move the fingers closer

BiometricLocation enum

Attribute
Description
FACE_FRONTALFace
FINGER_RIGHT_INDEXRight index finger
FINGER_RIGHT_MIDDLERight middle finger
FINGER_RIGHT_RINGRight ring finger
FINGER_RIGHT_LITTLERight little finger
FINGER_RIGHT_THUMBRight thumb
FINGER_RIGHT_FOURRight four fingers
FINGER_LEFT_INDEXLeft index finger
FINGER_LEFT_MIDDLELeft middle finger
FINGER_LEFT_RINGLeft ring finger
FINGER_LEFT_LITTLELeft little finger
FINGER_LEFT_THUMBLeft thumb
FINGER_LEFT_FOURLeft four fingers
FINGER_UNKNOWNUnknown finger
HAND_LEFTLeft hand
HAND_RIGHTRight hand
HAND_UNKNOWNUnknown hand
UNKNOWNUnknown

BiometricModality enum

Attribute
Description
UNKNOWNUnknown
FACEFace
FRICTION_RIDGEFriction ridge (fingers)

Cr2dMode enum

Attribute
Description
RANDOMTargets fully random
PATHTargets defined with path
FIXEDFixed position for target

Camera enum

This enum is used to configure the behavior of BioCapture.

Attribute
Description
FRONTFront camera
REARRear camera

CameraFlash enum

This enum is used to configure the behavior of BioCapture.

Attribute
Description
OFFCamera flash off
ONCamera flash on

Overlay enum

This enum is used to configure the behavior of BioCapture.

Attribute
Description
OFFOverlay off
ONOverlay on

BioCaptureMode enum

This enum is used to configure the behavior of FingerCapture.

Attribute
Description
FINGERSFingerprint one to four finger
THUMBFingerprint one finger
AUTHENTICATIONFingerprint authentication embedded

The goal of the face liveness feature is to provide mechanisms that prevent or limit a variety of methods used in fraud attempts, such as the use of still images or photos or videos of a given person.

CaptureError enum

This enum reports the reason that a capture attempt failed.

Attribute
Description
UNKNOWNUnknown error
LOW_RESOLUTIONResolution too low
NOT_ENOUGH_MOVEMENTNot enough movement
TOO_FASTToo fast
HINT_UNKNOWNHint value is unknown
CAPTURE_TIMEOUTCapture timeout
CAPTURE_DELAYEDCapture delayed due to liveness failures
BAD_CAPTURECapture went wrong
BAD_CAPTURE_FINGERSCapture of the fingers went wrong
BAD_CAPTURE_FACECapture of the face went wrong
BAD_CAPTURE_HANDCapture of the hand went wrong
LIVENESS_CHECKLiveness check failed

AuthenticationStatus enum

This enum contains the authentication status.

Attribute
Description
SUCCESSAuthentication success (above the threshold used for the authentication process)
FAILUREAuthentication failure (below the threshold used for the authentication process)

LogLevel enum

This enum controls the logging level.

Attribute
Description
ERRORError log level or above
DEBUGDebug log level or above
WARNINGWarning log level or above
INFOInfo log level or above
DISABLEDisables logging

MorphoFaceTemplateFormat enum

This enum retrieves information about the face template format.

Attribute
Description
MIMAMIMA format
MOCMOC format

MorphoFingerTemplateFormat enum

FaceTemplateQuality enum

This enum retrieves information about quality of the face saved in template.

Attribute
Description
LOWThe quality of face is low (not recommended to perform matching).
MEDIUMThe quality of face is medium - good enough to perform matching.
HIGHThe quality of face is high.

This enum retrieves information about the finger template format.

Attribute
Description
AAMVAAAMVA format
ANSI_378ANSI_378 format
ANSI_378_2009ANSI_378_2009 format
BIOSCRYPTBIOSCRYPT format
CFVCFV format
DIN_V66400_CSDIN_V66400_CS format
GA_774GA_774 format
ILO_FMRILO_FMR format
MINEX_AMINEX_A format
ISO_19794_2ISO_19794_2 format
ISO_19794_2_2011ISO_19794_2_2011 format
ISO_19794_2_NSISO_19794_2_NS format
ISO_19794_2_CSISO_19794_2_CS format
PKMATPKMAT format
PKCOMPV2PKCOMPV2 format
PKLITEPKLITE format
PKCOMPV1PKCOMPV1 format

CaptureHandlerStatus enum

This enum retrieves the status of the capture handler.

Attribute
Description
STOPThe capture handler is stopped
PREVIEWThe capture handler is in preview mode
CAPTUREThe capture handler is in capture mode

Compression recommendations

Selfie images
  • Recommended size is 400 px
  • Recommended compression is JPEG90
  • Size of image will be about 100 KB
Example code
Java
1val IMAGE_SIZE = 400
2val JPEG_COMPRESSION_LEVEL = 90
3
4private fun prepareImage(image: ByteArray): ByteArray {
5 val imageBitmap = BitmapFactory.decodeByteArray(image, 0, image.size)
6 val scaledBitmap = Bitmap.createScaledBitmap(imageBitmap, IMAGE_SIZE, IMAGE_SIZE, true)
7 imageBitmap.recycle()
8 val byteArrayOutStream = ByteArrayOutputStream()
9 val result = scaledBitmap.compress(Bitmap.CompressFormat.JPEG, JPEG_COMPRESSION_LEVEL, byteArrayOutStream)
10 scaledBitmap.recycle()
11 return byteArrayOutStream.toByteArray()
12}

New face capture API 

Introduction 

In order to make integration of the SDK easier and more intuitive - new API for Face Capture has been delivered. It is based on use cases that are self-explaining which provide specific information depending on a given use case. This allows integrator to focus on working with the data provided by the SDK rather than on SDK configuration.

Old API is still available for backward compability for already integrated users. It's description might be found here.

NOTE: For now, the new API supports only remote use case.

Integration 

License activation

First step that is mandatory to use SDK is to activate license and grant camera permission for application. This part is common for old API and the new one. License handling can be found here.

Adding FaceCaptureView

FaceCaptureView is a key component of SDK. It not only provides preview for the capture but also it is an entry point to SDK's API. It means that on this component integrator sets up capture and orchestrate it's flow.

FaceCaptureView should be added to the layout of capture Activity. It is done as any other android's view. It must be visible to the end user.

XML
1<androidx.constraintlayout.widget.ConstraintLayout
2 xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:orientation="horizontal">
7
8 <com.idemia.capture.face.api.FaceCaptureView
9 android:id="@+id/captureView"
10 android:layout_width="0dp"
11 android:layout_height="0dp"
12 app:layout_constraintBottom_toBottomOf="parent"
13 app:layout_constraintEnd_toEndOf="parent"
14 app:layout_constraintStart_toStartOf="parent"
15 app:layout_constraintTop_toTopOf="parent" />
16
17</androidx.constraintlayout.widget.ConstraintLayout>

As FaceCaptureView is also entry point to SDK, it should be also invoked with proper methods in application logic. This can be done by old way - findViewById:

Kotlin
1@Override
2 protected void onCreate(Bundle savedInstanceState) {
3 super.onCreate(savedInstanceState);
4 setContentView(R.layout.your_activity_layout);
5
6 val captureView = findViewById(R.id.captureView);
7}

or with more popular way - through binding:

Kotlin
1lateinit var binding: YourActivityCaptureBinding
2
3override fun onCreate(savedInstanceState: Bundle?) {
4 super.onCreate(savedInstanceState)
5 binding = YourActivityCaptureBinding.inflate(layoutInflater)
6 setContentView(binding.root)
7
8 val captureView = binding.captureView
9}

Creating use case

In order to perform capture, the next step is to create use case we are interested in.As mentioned above - new API focuses on what we want to do and not on how we want to do. In order to achieve that, use cases have been introduced. They define what will be done and require (at least for result) set of listeners to provide information about capture.

Currently the only available use case for now is RemoteUseCase.

Kotlin
1val remoteUseCase =
2 RemoteUseCase(
3 sessionId,
4 RemoteCaptureListeners(
5 faceTrackingInfo = faceTrackingInfoLoggingListener,
6 captureFeedback = feedbackListener,
7 captureLivenessListener = captureLivenessLoggingListener,
8 stepInfoListener = stepInfoListener,
9 passiveVideoListener = passiveVideoLoggingListener,
10 captureResultListener = captureResultListener
11 ),
12 environmentInfo
13 )

More about use cases and their properties can be found in dedicated section.

Setting up capture

When license is activated, camera permission is granted, and use case has been created, it is time to set up capture and perform it. In order to do that use method setUp on FaceCaptureView:

Kotlin
1fun setUp(useCase: UseCase, lifecycle: Lifecycle?, uiSettings: UISettings?)

Please find below explanation to each function argument:

Parameter
Description
useCase UseCaseThis is use case instance providing type of capture and allowing integrator to get data from it
lifecycle LifecycleThis is Android's component allowing SDK be lifecycle aware. Argument is optional. If not provided integrator has to explicitly manage flow. If lifecycle is provided there is no need to start/cancel/destroy flow.
uiSettings UISettingsSettings providing details to UI-Extensions library. If not provided integrator has to handle displaying proper UI to end user on his own. More information about it can be found here.

In case that Lifecycle component is not configured, methods:

  • start() - Start's capture and liveness verification flow. Recommended to invoke in onResume or onStart methods of Android's lifecycle.
  • cancel() - Cancel's flow. Recommended to invoke in onPause or onStop methods of Android's lifecycle - depending on desired effect.
  • destroy() - Cleans up capture view and it's data. Recommended to invoke in onDestroy method of Android's lifecycle. have to be called explicitly by integrator in order to provide smooth and stable user experience.

Provided that above steps has been done, capture needs to be set up, as in the following example:

Kotlin
1[code in Activity]
2
3fun setupView(useCase: UseCase) {
4 binding.captureView.setUp(
5 useCase,
6 lifecycle,
7 UISettings(passiveVideoSettings, passiveSettings, joinThePointsCaptureSettings)
8 )
9}

Here is example of UISettings setup. Keep in mind that this class keep configuration for each FaceLiveness mode except from NO_LIVENESS:

Kotlin
1val joinThePointsCaptureSettings = joinThePointsChallengeSettings {
2 useInterpolation = true
3 scene {
4 overlay {
5 showOverlay = true
6 imageRes = R.drawable.ic_face_overlay
7 marginVertical = R.dimen.default_face_overlay_vertical_padding
8 marginHorizontal = R.dimen.default_face_overlay_vertical_padding
9 text {
10 text = R.string.default_overlay_text
11 textSize = R.dimen.default_overlay_text_size
12 textColor = Color.parseColor(Colors.text_black)
13 }
14 }
15 capturedLineOpacity = 0.5f
16 pointer {
17 type = PointerType.PULSING
18 collisionWithTargetAction = PointerCollisionAction.NONE
19 }
20 target {
21 pulseAnimation {
22 waves = 3
23 }
24 showMarkOnCurrentTarget = true
25 }
26 verticalTilt {
27 enabled = false
28 }
29 tapping {
30 enabled = false
31 }
32 result {
33 failureImageResId = R.drawable.ic_challenge_failed
34 successImageResId = R.drawable.ic_challenge_success
35 }
36 }
37}
38
39val passiveSettings = passiveCaptureSettings {
40 scene {
41 background {
42 colorEnd = Color.parseColor("#189482")
43 colorStart = Color.parseColor("#38ddb8")
44 }
45 previewScale {
46 scaleX = 1.0f
47 scaleY = 1.0f
48 }
49 feedback {
50 colorText = Color.parseColor(Colors.white)
51 }
52 overlay {
53 showOverlay = true
54 }
55 tapping {
56 colorBackground = Color.parseColor("#FAFAFA")
57 colorImage = Color.parseColor(Colors.black)
58 colorText = Color.parseColor(Colors.black)
59 textResId = "Use your head to interact"
60 textH1ResId = "No tapping needed"
61 enabled = true
62 }
63 verticalTilt {
64 colorBackground = Color.parseColor("#FAFAFA")
65 colorImage = Color.parseColor("#000000")
66 colorText = Color.parseColor("#000000")
67 textResId = "Please hold your phone vertically."
68 enabled = true
69 }
70 countdown {
71 countdownSeconds = 3
72 }
73 delay {
74 isEnabled = true
75 message = "Authentication locked.\nPlease wait for:\n%1$s"
76 }
77 }
78}
79
80val passiveVideoSettings = passiveVideoCaptureSettings {
81 scene {
82 preparationScene {
83 backgroundColor = Color.WHITE
84 }
85 faceOverlay {
86 progressBar {
87 progressFill = Color.GREEN
88 }
89 }
90 background {
91 colorEnd = Color.parseColor("#189482")
92 colorStart = Color.parseColor("#38ddb8")
93 }
94 previewScale {
95 scaleX = 1.0f
96 scaleY = 1.0f
97 }
98 feedback {
99 videoBackground { }
100 }
101 tapping {
102 colorBackground = Color.parseColor("#FAFAFA")
103 colorImage = Color.parseColor("#000000")
104 colorText = Color.parseColor("#000000")
105 textResId = "Use your head to interact"
106 textH1ResId = "No tapping needed"
107 enabled = true
108 }
109 verticalTilt {
110 colorBackground = Color.parseColor("#FAFAFA")
111 colorImage = Color.parseColor("#000000")
112 colorText = Color.parseColor("#000000")
113 textResId = "Please hold your phone vertically."
114 enabled = true
115 }
116 delay {
117 isEnabled = true
118 message = "Authentication locked.\nPlease wait for:\n%1$s"
119 }
120 }
121}

Use cases 

As mentioned in sections above new API is meant to be easier to integrate and more intuitive in general. In order to achieve that use cases have been introduced. Every use case is dedicated to do particular job. Please find below list of available use cases.

RemoteUseCase

This use case is used to perform face capture with backend liveness verification. Thanks to this use case integrator does not have to integrate with backend services as it provides end to end integration. However, few things needs to be provided:

  • Session id for given capture
  • RemoteCaptureListeners
  • EnvironmentInfo
Kotlin
1RemoteUseCase(sessionId: String, listeners: RemoteCaptureListeners, environmentInfo: EnvironmentInfo)
Parameter
Description
sessionId StringSession id correlated with face capture. Most popular approach is to create session outside of application (integrator's backend) and pass it to it. Can be created via backend components: GIPS or directly via WebBio. Please find more instructions according to session creation below.
listeners RemoteCaptureListenersGroup of listeners related to remote use case. They help to gather capture data and informs about flow state and result. See listeners section for more details.
environmentInfo EnvironmentInfoInformations about Proofing Platform environment and authentication method.

RemoteCaptureListeners - detailed description of each listeners can be found in listeners section.

Parameter
Description
livenessActiveListener LivenessActiveListenerProvides information about liveness ACTIVE mode. Usefull when UISettings are not provided to FaceCaptureView.
faceTrackingInfo FaceTrackingInfoListenerProvides coordinates with face.
captureFeedback CaptureFeedbackListenerProvides feedback that should be presented to end user to improve capture process. Handled when UISettings are used.
captureLivenessListener CaptureLivenessListenerProvides information about liveness mode for current capture.
stepInfoListener StepInfoListenerProvides information about state of capture.
passiveVideoListener PassiveVideoListenerProvides information about liveness PASSIVE_VIDEO mode. Usefull when UISettings are not provided to FaceCaptureView.
captureResultListener RemoteCaptureResultListenerProvides information about result of whole flow.
livenessProcessingListener LivenessProcessingListenerProvides progress of sending user image metadata to the server. It takes values from 0.0 to 1.0

EnvironmentInfo

FaceCapture is compatible with two types of the authorization: API Key and OAuth.

  • In token type authorization, an access token is generated by the authorization server using the provided secrets. This token can be utilized by creating an AccessToken class and using the appropriate initializer in the EnvironmentInfo class: init(accessToken: AccessToken, baseUrl: URL).
  • The AccessToken class holds information about the secret and token type from the OAuth authorization server.

Secrets can be found on the webpage: https://experience.idemia.com/dashboard/my-identity-proofing/access/environments/.

Access Token solution constructor:

Parameter
Description
baseUrl StringURL to Proofing services. For example production URL is: https://proofing.app.eu.identity-prod.idemia.io:443/
accessToken AccessTokenDedicated information about access token used to authenticate on Proofing services. Do not share this and try to avoid storing it on application's repository

ApiKey solution constructor:

Parameter
Description
baseUrl StringURL to Proofing services. For example production URL is: https://proofing.app.eu.identity-prod.idemia.io:443/
apiKey StringDedicated key used to authenticate on Proofing services. Do not share this and try to avoid storing it on application's repository

AccessToken

Parameter
Description
secret StringDedicated token used to authenticate on Proofing services. Do not share this and try to avoid storing it on application's repository
tokenType StringToken type to indicate how it should be used in authorization request.
Creating capture session

RemoteUseCase handles liveness verification on backend side. It requires to create session per capture. Common approach is to create session on integrator's backend side and provide it to application. Then capture flow might be triggered. Good to start with pages:

  • General description of liveness remote capture - here
  • GIPS API description - here
  • WebBio API description - here

For example, creating session via GIPS requires:

  1. Create identity by calling: POST: /v1/identities As a result an identity is being returned

  2. Submit confirmation that the user has consented to perform specific evidence verifications: POST: /v1/identities/{id}/consents

  3. Start liveness session by calling: POST: /v1/identities/{id}/attributes/portrait/live-capture-session?mode=nativeSDK Response to this call contains session id used by SDK.

Proceeding with WebBio requires:

  1. Create session by calling: POST: /bioserver-app/v2/bio-sessions Call must contain session data in body.

  2. Retrieve session path from the response:

Kotlin
1val bioSessionPath = response.headers()["Location"]
  1. Get BioSession: GET: /bioserver-app{bioSessionPath} Response to this call contains session id used by SDK.

  2. Initialize the session with id from previous step and liveness parameters passed in body: POST: /bioserver-app/v2/bio-sessions/{bioSessionId}/init-liveness-parameters

Snippet below shows use case creation:

Kotlin
1val environmentInfo = EnvironmentInfo(
2 "https://proofing.app.eu.identity-prod.idemia.io:443/",
3 "YourApiKey"
4)
5val sessionInfo = sessionHandler.createSession(
6 readFaceLivenessModeFromSettings(),
7 readFaceSecurityLevelFromSettings()
8)
9val remoteUseCase = RemoteUseCase(
10 sessionInfo.sessionId,
11 RemoteCaptureListeners(
12 faceTrackingInfo = faceTrackingInfoLoggingListener,
13 captureFeedback = feedbackListener,
14 captureLivenessListener = captureLivenessLoggingListener,
15 stepInfoListener = stepInfoListener,
16 passiveVideoListener = passiveVideoLoggingListener,
17 captureResultListener = captureResultListener
18 ),
19 environmentInfo
20)

If this guide is not enough, there is still FaceSampleAppLite source code on our Artifactory repository. Feel free to download latest package with GIPS implementation from here or WBS implementation from here and see integration with session creation included.

Keep in mind that result of flow on SDK side is sending required data to backend service. Captured image might be required for application needs. To aquire it, additional request to WebBioServer has to be done. API description related to this can be found here.

Listeners 

New API introduces multiple listeners to acquire capture related data by integrator. All listeners are being called on UI thread and it is safe to manipulate UI components directly from them.

CaptureLivenessListener

Returns information about current liveness capture mode. Usefull for RemoteUseCase where mode comes from backend side.

Kotlin
1fun captureLiveness(liveness: Liveness)

Liveness

Value
Description
ACTIVEMeans that current liveness mode is active one. User need to connect points using face.
PASSIVEMeans that current liveness mode is passive one. No challenges for user.
PASSIVE_VIDEOMore advanced variant of passive mode. It requires backend integration (can be used with RemoteUseCase) as it uses more restrictive liveness algorithms.

StepInfoListener

This listener provides information about capture flow state within StepInfo object.

Kotlin
1fun stepInfo(stepInfo: StepInfo)

StepInfo

Value
Description
PREPARING_LIVENESSLiveness challenge is being prepared.
CAPTURE_STARTEDCapture has been started. Preview should actively show frames from camera.

LivenessActiveListener

This listener provides information about active face capture. This mode requires user to connect dots in correct order by moving his face. Callbacks tells integrator what is current status of challenge and what to display. Keep in mind that by providing UISettings to FaceCaptureView, there is no need to handle that because SDK will draw this challenge with style provided.

Kotlin
1fun onPointerUpdate(pointInfo: PointerInfo)

PointerInfo contains information about user's "viewfinder" position. This is the point that user needs to put on a target in order to mark it as "captured".

Kotlin
1fun onTargetUpdate(targetInfo: TargetInfo)

TargetInfo contains information about targets to capture.

Parameter
Description
x IntX coordinate of target.
y IntY coordinate of target.
show BooleanIndicates if target should be visible to user.
radius IntRadius of target relative to capture frame size.
number IntNumber of target.
completness FloatValue ranged from 0.0 to 1.0, where 1.0 tells that target is fully captured.
current BooleanInforms if given target is currently active one (to be captured).
Kotlin
1fun onNumberTargets(numberOfTargets: Int)

This callback provides information about how many points needs to be captured to pass challenge.

PassiveVideoListener

This listeners helps to pass passive video liveness capture mode. Before capture starts there is a preparation phase and capture itself has it's progress. Informations provided within this listener should be presented to end user. Keep in mind that by providing UISettings to FaceCaptureView, there is no need to handle this listener because SDK will draw this challenge with style provided.

Kotlin
1fun onPreparationStarted()

Tells integrator that preparation of capture has been started.

Kotlin
1fun onPreparationFinished()

Tells integrator that preparation phase has finished. Now capture will be performed.

Kotlin
1fun overlayUpdated(overlay: OvalOverlay)

To make capture easier there is a special configuration for UI oval to be displayed to end user. OvalOverlay has coordinates and size of that oval.

Kotlin
1fun progressUpdated(progress: Float)

Progress of capture.

RemoteCaptureResultListener

Used only for RemoteUseCase. Provides information about flow result.

Kotlin
1fun onFinish(result: CaptureResult)

CaptureResult instance might be type of Success that is information about successful flow or Failure that contains Error instance inside. For more details see errors section.

CaptureFeedbackListener

This is listener with crucial information for user about the capture. Helps to find optimal position in front of camera.

Kotlin
1fun onFeedback(captureFeedback: CaptureFeedback)

Where CaptureFeedback is enum with self-explanatory instruction. It is covered by UISettings* by mapping these to text instructions to the user.

FaceTrackingInfoListener

This listener provides rectangle coordinates and size with face position (relative to preview frame size) in real time during capture. Helpful when there is a need to draw overlay on preview showing detected face.

Kotlin
1fun faceTrackingInfo(trackingInfo: FaceTrackingInfo)

FaceTrackingInfo provides "face rectangle" informations.

LivenessProcessingListener

This listener provides information about current progress of uploading metadata to the server.

Kotlin
1fun onLivenessMetadataUploadProgressUpdated(@FloatRange(from = 0.0, to = 1.0) progress: Float)

Errors 

For every flow there is possibility to receive Error type of result. It means that something went wrong during the capture or backend communication. Fortunately, Error object contains a lot of useful informations that help to handle failed flow.

Error

Parameter
Description
type ErrorTypeType of an error. High level information what goes wrong. Find types description below.
code IntSpecial code dedicated for particular case. Very helpful in L2, L3 troubleshooting.
message StringMessage with error description.
unlockDateTime Long?Time in "UTC" time zone when capture will be unblocked. This field have value when ErrorType is DEVICE_BLOCKED

ErrorType

Type
Description
CONNECTION_ISSUEGeneral issue with connection. See message and error code for more informations.
AUTHENTICATIONBackend authentication failed. Probably wrong credentials has been used for the given environment.
INVALID_SESSIONSession ID is not correct. Most probably session expired or has been finished.
TIMEOUTTimeout occured during the flow.
BAD_CAPTURECapture failed. Face was not detected or liveness check did not pass.
UNKNOWNUnknow type of exception. Also used as default type for few cases.
CANCELEDFlow has been canceled. Can be triggered by integrator or automatically when Lifecycle has been passed to setUp method.
VERIFICATIONDevice signature verification failed.
INVALID_LICENSELicense validation failed. Make sure that it has been activated with [LicenseManager](https://experience.idemia.com/identity-proofing/develop/capture-sdk/android/4_x/integration-guide #license-manager)
DEVICE_BLOCKEDCapture on this device got blocked for period of time, because of many failures.

New finger capture API 

Introduction 

In order to make integration of the SDK easier and more intuitive - new API for finger capture has been delivered. It is based on self-explaining use cases which provide specific information depending on a given use case. This allows integrator to focus on working with the data provided by the SDK rather than on SDK configuration.

Old API is also available for integrators as it provides other use cases. It's description might be found here.

NOTE: For now, the new API supports only latent use case.

Integration 

Integration of SDK consists of four steps:

  1. Activating license.
  2. Adding FingerCaptureView to activity.
  3. Creating use case.
  4. Setting up capture.

License activation

This part is common for old API and the new one. License handling can be found here.

Adding FingerCaptureView

FingerCaptureView has to be added to the layout of capture Activity, as for any other Android's view. It is a key component of the SDK. It not only provides preview for the capture but also is an entry point to SDK's API. It means that on this component integrator sets up capture and orchestrate it's flow. This view must be visible to the end user.

XML
1<androidx.constraintlayout.widget.ConstraintLayout
2 xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 android:orientation="horizontal">
7
8 <com.idemia.capture.face.api.FingerCaptureView
9 android:id="@+id/captureView"
10 android:layout_width="match_parent"
11 android:layout_height="match_parent"/>
12
13</androidx.constraintlayout.widget.ConstraintLayout>

As FingerCaptureView is entry point to SDK, it should also be used with proper methods in application logic. This can be done by old way - with findViewById:

Kotlin
1private val captureView: FingerCaptureView? = null
2
3@Override
4 protected void onCreate(Bundle savedInstanceState) {
5 super.onCreate(savedInstanceState);
6 setContentView(R.layout.your_activity_layout);
7
8 captureView = findViewById(R.id.captureView);
9}

or with more up to date way - through binding:

Kotlin
1lateinit var binding: YourActivityCaptureBinding
2private val captureView: FingerCaptureView? = null
3
4override fun onCreate(savedInstanceState: Bundle?) {
5 super.onCreate(savedInstanceState)
6 binding = YourActivityCaptureBinding.inflate(layoutInflater)
7 setContentView(binding.root)
8
9 captureView = binding.captureView
10}

Creating use case

In order to perform capture, the next step is to create use case we are interested in. As mentioned above - new API focuses on what we want to do and not on how we want to do. In order to achieve that, use cases have been introduced. They define what will be done and require (at least for result) set of listeners to provide information about capture.

Currently the only available use case is LatentUseCase.

Kotlin
1val latentUseCase =
2 LatentUseCase(
3 LatentCaptureSettings(TIMEOUT),
4 LatentCaptureListeners(
5 currentDistanceListener = fingerCaptureDistanceListener,
6 feedbackListener = fingerCaptureFeedbackListener,
7 trackingListener = fingerCaptureTrackingListener,
8 result = latentResultListener,
9 torchListener = torchListener
10 )
11 )

More about use cases and their properties can be found in dedicated section.

Setting up capture

When previous steps are completed, it is time to set up capture and perform it. In order to do that use method setUp on FingerCaptureView:

Kotlin
1fun setUp(useCase: UseCase, lifecycle: Lifecycle?, uiSettings: UISettings?)

Please find below explanation to each function argument:

Parameter
Description
useCase UseCaseThis is use case instance providing type of capture and allowing integrator to get data from it
lifecycle LifecycleThis is Android's component allowing SDK to be lifecycle aware. Argument is optional. If not provided integrator has to explicitly manage flow. If lifecycle is provided there is no need to start/cancel/destroy flow.
uiSettings UISettingsSettings providing details to UI-Extensions library. If not provided integrator has to handle displaying proper UI to end user on his own. More information about it can be found here.

In case that Lifecycle parameter is not provided, below methods have to be called explicitly by integrator in order to provide smooth and stable user experience:

  • start() - Start's capture and liveness verification flow. Recommended to invoke it in onResume or onStart methods of Android's lifecycle.
  • cancel() - Cancel's flow. Recommended to invoke it in onPause method of Android's lifecycle.
  • destroy() - Clean's up capture view and it's data. Recommended to invoke it in onDestroy method of Android's lifecycle.

Assuming that above steps has been done, capture needs to be set up, as in the following example:

Kotlin
1[code in Activity]
2
3fun setupView(useCase: UseCase) {
4 binding.captureView.setUp(
5 useCase,
6 lifecycle,
7 UISettings(fingerCaptureSettings)
8 )
9}

Here is an example of UISettings setup.

Kotlin
1val fingerCaptureSettings = fingerCaptureSettings {
2 scene {
3 background {
4 colorEnd = Color.parseColor("#189482")
5 colorStart = Color.parseColor("#38ddb8")
6 }
7 rectangle {
8 color = Color.BLACK
9 strokeWidth = 20f
10 cornerRadius {
11 rx = 20f
12 ry = 20f
13 }
14 }
15 previewScale {
16 scaleX = 1.0f
17 scaleY = 1.0f
18 }
19 tapping {
20 colorBackground = Color.parseColor("#FAFAFA")
21 colorImage = Color.parseColor("#000000")
22 colorText = Color.parseColor("#000000")
23 textResId = R.string.use_your_head
24 textH1ResId = R.string.no_tapping_feedback
25 enabled = true
26 }
27 feedback {
28 feedbackStringMapping = mapping
29 show = true
30 }
31 distance {
32 showOptimalDistanceIndicator = true
33 }
34 progressBar {
35 labelRes = R.string.scanning
36 show = true
37 }
38 }
39}

Contrary to using fingerCaptureSettings in legacy API, there is no need to set range parameter of distance field - it is handled internally within the SDK.

Use cases 

As mentioned in sections above, new API is meant to be easier to integrate and more intuitive in general. To achieve this, use cases has been introduced. Every use case is dedicated to do particular job. Below you can find list of available use cases.

LatentUseCase

This use case can be used to capture a fingerprint of secretion of the skin. The fingerprint will be returned in PNG format. To create LatentUseCase, following properties must be provided:

  • LatentCaptureSettings
  • LatentCaptureListeners
Kotlin
1LatentUseCase(val settings: LatentCaptureSettings, val listeners: LatentCaptureListeners)
Parameter
Description
settings LatentCaptureSettingsLatent capture settings. Currently it contains only one field - timeout, which indicates time of capture.
listeners LatentCaptureListenersGroup of listeners related to latent use case. They help to gather capture data and informs about flow state and result. See listeners section for more details.

LatentCaptureListeners - detailed description of each listener can be found in listeners section.

Parameter
Description
currentDistanceListener FingerCaptureDistanceListenerProvides information about optimal distance range between phone lens and fingers . This listener is optional and is useful when UISettings are not provided.
feedbackListener FingerCaptureFeedbackListenerProvides information whether the distance between fingers and the phone is correct. Works only with calibrated devices. This listener is optional and is useful when UISettings are not provided.
trackingListener FingerCaptureTrackingListenerProvides localisation of fingers. This listener is optional and is useful when UISettings are not provided.
result LatentResultListenerProvides information about capture status.
torchListener TorchListenerProvides device torch controller when available.

Listeners 

New API introduces multiple listeners to acquire capture related data by integrator. All listeners are being called on UI thread and it is safe to manipulate UI components directly from them.

FingerCaptureDistanceListener

Returns information associated with indication of optimal distance range between the phone lens and the fingerprint.

Kotlin
1fun onCaptureDistanceRangeInformation(captureDistanceRangeResult: CaptureDistanceRangeResult)

CaptureDistanceRangeResult

CaptureDistanceRangeResult is a sealead class. It may be CaptureDistanceRangeSuccess or CaptureDistanceRangeUnavailable

Value
Description
CaptureDistanceRangeSuccessMeans that the device is calibrated for distance indication feature. Contains CaptureDistanceRange
CaptureDistanceRangeUnavailableMeans that the device isn't calibrated for distance indication feature or retrieving optimal distance is not possible.

CaptureDistanceRange

Parameter
Description
rangeMin FloatMinimum value that may be returned in boundary range.
optimalMin FloatLower boundary of optimal distance between the phone lens and the fingerprint.
optimalMax FloatUpper boundary of optimal distance between the phone lens and the fingerprint.
rangeMax FloatMaximum value that may be returned in boundary range.

CaptureDistanceRangeUnavailable

Parameter
Description
reason StringA reason why CaptureDistanceRange is unavailable.
Kotlin
1fun onCurrentCaptureDistance(currentCaptureDistance: CurrentCaptureDistance)

CurrentCaptureDistance

Parameter
Description
value FloatCurrent distance between the fingerprint and the phone lens.

FingerCaptureFeedbackListener

Provides information if the distance between fingers (fingerprints) and the phone is acceptable.

Kotlin
1fun onCaptureInfo(captureInfo: FingerCaptureInfo)

FingerCaptureInfo

Value
Description
OPTIMALIndicates that the distance between the fingers (fingerprints) and the phone lens is optimal.
TOO_CLOSEIndicates that the phone lens is too close from the fingers (fingerprints) and should be moved further.
TOO_FARIndicates that the phone lens is too far from the fingers (fingerprints) and should be moved closer.

FingerCaptureTrackingListener

By default returns list with localisations of the fingers. For LatentUseCase this list will contain only one element which should be used to draw overlay that will show the area of a capture.

Kotlin
1fun onTracking(finger: List<FingerBox>)

FingerBox

Parameter
Description
x IntCoordinate of the left side of the rectangle top.
y IntCoordinate of the top of the rectangle right.
width IntRectangle width.
height IntRectangle height.
previewWidth IntWidth of the preview.
previewHeight IntHeight of the preview.
orientation IntRectangle rotation value, in degrees.

TorchListener

Returns TorchController that can be used to control the device torch.

Kotlin
1fun onTorchControllerProvided(torchController: TorchController)

TorchController

Kotlin
1interface TorchController {
2 fun setTorch(torch: Torch)
3 fun getTorch(): Torch
4}

Torch

Type
Description
ONTorch is on or will be turned on
OFFTorch is off or will be turned off.

LatentResultListener

Returns information if capture succeeded or failed. In case of success, LatentSuccess will be returned in onSuccess callback, Error will be returned in onError otherwise.

Kotlin
1interface TorchController {
2 fun onSuccess(result: LatentSuccess)
3 fun onError(error: Error)
4}

LatentSuccess

Parameter
Description
image LatentImageContains image in PNG format with width and height.

LatentImage

Parameter
Description
width IntImage width.
height IntImage height.
data ByteArrayPNG image.

Errors 

For every flow there is possibility to receive Error type of result. It means that something went wrong during the capture or backend communication. Fortunately, Error object contains a lot of useful information that help to handle failed flow.

Error

Parameter
Description
type ErrorTypeType of an error. High level information what goes wrong. Find types description below.
code IntSpecial code dedicated for particular case. Very helpful in L2, L3 troubleshooting.
message StringMessage with error description.

ErrorType

Type
Description
TIMEOUTTimeout occured during the flow.
BAD_CAPTURECapture failed. Fingerprint was not detected or some kind of internal issue appeared.
UNKNOWNUnknow type of exception. Also used as default type for few cases.
INVALID_LICENSELicense validation failed. Make sure that it has been activated with [LicenseManager](https://experience.idemia.com/identity-proofing/develop/capture-sdk/android/4_x/integration-guide #license-manager)

BioStore 

The use of this component is optional. Its purpose is to allow the integrator to easily persist templates.

Query templates by userUUID 

This lists the templates stored in the repository filtering by user.

list_template_by_user_id
s
Java
1BioStoreDB.listTemplates(context, userId, new DataBaseAsyncCallbacks<List<IMorphoTemplate>>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(List<IMorphoTemplate> result) {
9 //The list of templates that match the criteria.
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred.
15 }
16 });

Function

Java
1public static void listTemplates(final Context context, final UUID userId, DataBaseAsyncCallbacks<List<IMorphoTemplate>> callbacks);
Parameter
Description
context ContextThe Android context.
userId UUIDThe user identifier.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Query templates by userUUID and modality 

This lists the templates stored in the repository filtering by User and BiometricModality.

list_template_by_user_id_and_modality
Java
1BioStoreDB.listTemplates(context, userId, biometricModality, new DataBaseAsyncCallbacks<List<IMorphoTemplate>>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(List<IMorphoTemplate> result) {
9 //The list of templates that match the criteria.
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred.
15 }
16 });

Function

Java
1void listTemplates(final Context context, final UUID userId, final BiometricModality biometricModality, DataBaseAsyncCallbacks<List<IMorphoTemplate>> callbacks);
Parameter
Description
context ContextThe Android context.
userId UUIDThe user id.
biometricModality BiometricModalityThe BiometricModality enum option.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Add template 

This stores a template in the repository. If there is a previous template with the same user UUID, Biometric location, and Biometric modality, it will be updated and the UUID returned.

Note: You cannot have two templates with the same configuration.

add_template
Java
1BioStoreDB.addTemplate(context, morphoTemplate, new DataBaseAsyncCallbacks<UUID>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(UUID result) {
9 //The template has been added and the template's uuid is returned as a parameter.
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred.
15 }
16 });

Function

Java
1public static void addTemplate(final Context context, final IMorphoTemplate template, DataBaseAsyncCallbacks<UUID> callbacks);
Parameter
Description
context ContextThe Android context.
template IMorphoTemplateThe template to be stored.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Update template 

This updates a template in the repository.

Update_template
Java
1BioStoreDB.updateTemplate(context, morphoTemplate, new DataBaseAsyncCallbacks<Void>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(Void result) {
9 //updated.
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred.
15 }
16});

Function

Java
1void updateTemplate(final Context context, final IMorphoTemplate template, DataBaseAsyncCallbacks<Void> callbacks);
Parameter
Description
context ContextThe Android context.
template IMorphoTemplateThe template to be updated.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Remove template 

This removes a template from the repository.

remove_template_by_template_id
Java
1BioStoreDB.removeTemplate(context, templateId, new DataBaseAsyncCallbacks<Void>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(Void result) {
9 //The template was removed.
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred.
15 }
16 });

Function

Java
1void removeTemplate(final Context context, final UUID templateId, DataBaseAsyncCallbacks<Void> callbacks);
Parameter
Description
context ContextThe Android context.
templateId UUIDThe template id to be removed.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Remove templates associated to one userUUID 

This removes the templates associated to the user identifier from the repository.

remove_template_by_user_id
Java
1BioStoreDB.removeTemplateByUserId(context, userId, new DataBaseAsyncCallbacks<Integer>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(Integer result) {
9 //The number of templates removed.
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred.
15 }
16 });

Function

Java
1void removeTemplateByUserId(final Context context, final UUID userId, DataBaseAsyncCallbacks<Integer> callbacks);
Parameter
Description
context ContextThe Android context.
userId UUIDThe user id.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Retrieve template 

This retrieves a template from the database.

retrieve_template
Java
1BioStoreDB.getTemplate(context, templateId, new DataBaseAsyncCallbacks<IMorphoTemplate>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(IMorphoTemplate result) {
9 //The template if exists.
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred.
15 }
16 });

Function

Java
1void getTemplate(final Context context, final UUID templateId, DataBaseAsyncCallbacks<MorphoTemplate> callbacks);
Parameter
Description
context ContextThe Android context.
templateId UUIDThe template id.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Clear database 

This clears all the data stored in the database.

Java
1BioStoreDB.clear(context, new DataBaseAsyncCallbacks<Void>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(Void result) {
9 //Data has been cleared
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred
15 }
16 });

Function

Java
1void clear(final Context context, DataBaseAsyncCallbacks<Void> callbacks);
Parameter
Description
context ContextThe Android context.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Add user 

This adds a new user to the database.

Java
1IUser user = new User();
2 user.setName("Jose");
3 BioStoreDB.addUser(context, user, new DataBaseAsyncCallbacks<UUID>() {
4 @Override
5 public void onPreExecute() {
6 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
7 }
8
9 @Override
10 public void onSuccess(UUID result) {
11 //User saved
12 }
13
14 @Override
15 public void onError(Exception e) {
16 // An error has occurred
17 }
18 });

Function

Java
1void addUser(final Context context, final IUser user, DataBaseAsyncCallbacks<UUID> callbacks);
Parameter
Description
context ContextThe Android context.
user IUserThe user.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Update user 

This updates a user in the database.

Java
1IUser user = ...//retrieve old user
2 BioStoreDB.updateUser(context, user, new DataBaseAsyncCallbacks<Void>() {
3 @Override
4 public void onPreExecute() {
5 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
6 }
7
8 @Override
9 public void onSuccess(Void result) {
10 //User updated.
11 }
12
13 @Override
14 public void onError(Exception e) {
15 // An error has occurred.
16 }
17 });

Function

Java
1void updateUser(final Context context, final IUser user, DataBaseAsyncCallbacks<Void> callbacks);
Parameter
Description
context ContextThe Android context.
user IUserThe user.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Remove user 

This removes a user from the database.

Java
1BioStoreDB.removeUser(context, uuid, new DataBaseAsyncCallbacks<Void>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(Void result) {
9 //User removed
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred
15 }
16 });

Function

Java
1void removeUser(final Context context, final UUID uuid, DataBaseAsyncCallbacks<Void> callbacks);
Parameter
Description
context ContextThe Android context.
uuid UUIDThe user uuid.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

Get user 

This retrieves a user from the database.

Java
1BioStoreDB.getUser(context, uuid, new DataBaseAsyncCallbacks<IUser>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(IUser result) {
9 //User
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred
15 }
16 });

Function

Java
1void getUser(final Context context, final UUID uuid, DataBaseAsyncCallbacks<IUser> callbacks);
Parameter
Description
context ContextThe Android context.
uuid UUIDThe user uuid.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.

List users 

List the users stored in the repository.

Java
1BioStoreDB.listUsers(context, new DataBaseAsyncCallbacks<List<IUser>>() {
2 @Override
3 public void onPreExecute() {
4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`
5 }
6
7 @Override
8 public void onSuccess(List<IUser> result) {
9 //Users
10 }
11
12 @Override
13 public void onError(Exception e) {
14 // An error has occurred
15 }
16 });

Function

Java
1void listUsers(final Context context, DataBaseAsyncCallbacks<List<IUser>> callbacks);
Parameter
Description
context ContextThe Android context.
callbacks DataBaseAsyncCallbacksCallbacks to be executed depending on the result.

Errors

You will receive an exception reporting the error.