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:
XML1buildscript {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:
XML1artifactoryUserMI=artifactory_user2artifactoryPasswordMI=artifactory_credentials3repositoryUrlMI=https://mi-artifactory.otlabs.fr/artifactory/smartsdk-android-local
More about gradle properties can be found here.
For biometric features the dependency is:
Groovy1implementation ("morpho.mph_bio_sdk.android:SmartBio:version")
For document features the dependency is:
Groovy1implementation ("morpho.mph_bio_sdk.android:SmartDoc:version")
For all features the dependency is:
Groovy1implementation ("morpho.mph_bio_sdk.android:SmartSDK:version")
Version: artifact version
Components
The SDK comprises six distinct components:
- BioCaptureHandler: Handles the capture of the biometrics through the camera of the device.
- BioMatcherHandler: Handles the biometric coding and matching.
- DocumentCaptureHandler: Handles the document reading features (like reading MRZ documents).
- BioStoreDB: Repository to store biometric templates. (This component is optional, in case you don't want to implement your own database.)
- ImageUtils: Handles the image format conversion, in case the integrator must change the image format or import an image.
- 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:
XML1android.useDeprecatedNdk=true
And in your build.gradle add filters for the desired ABI. For now, the SDK supports armeabi-v7a and arm64-v8a:
XML1defaultConfig {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.
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:
XML1android {2 ...3 bundle {4 density {5 enableSplit true6 }7 abi {8 enableSplit true9 }10 language {11 enableSplit false12 }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.
Kotlin1LicenseManager 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:
Kotlin1val activationResult = manager.activate(2 object: LicenseActivationListener {3 override fun onLicenseActivated() {4 //License fetched and activated with success.5 }67 override fun onLicenseActivationFailed(licenseActivationError: LicenseActivationError) {8 //Failed to fetch or activate the license.9 }10 },11 applicationContext12 )
Coroutines solution: It returns LicenseActivationResult
Kotlin1val 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:
- LicenseActivationSuccess
- LicenseActivationError
LicenseActivationError
This is the information about why license can not be activated.
Attribute | Description |
---|---|
type ActivationErrorType | The type of error why license activation failed |
message String | The activation failure reason. |
ActivationErrorType
Attribute | Description |
---|---|
PROFILE_EXPIRED | Profile expired, all licenses won’t work anymore. (Contact with support) |
ACTIVATION_COUNT_EXCEEDED | No more licenses can be consumed. (Contact with support) |
AUTHENTICATION_ISSUE | Credentials and/or profile information are wrong. |
CONNECTION_ISSUE | Connection issue. Make sure that your internet connection is stable. |
UNKNOWN | Unknown 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
- Add the SDK library to your app's
build.gradle
:
Groovy1implementation ("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.
- 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:
Groovy1implementation '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.
- Add the
CaptureView
to the layout where you handle the biometric capture:
XML1<com.idemia.smartsdk.preview.CaptureView2 android:id="@+id/captureView"3 android:layout_width="match_parent"4 android:layout_height="match_parent" />
- On your activity or fragment get a reference to this view:
Java1CaptureView cameraPreview = (CaptureView) findViewById(R.id.captureView);
- 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.
Java1LicenseManager 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).
- Prepare capture settings. For face capture, you should use
FaceCaptureOptions
.
Java1FaceCaptureOptions captureOptions = new FaceCaptureOptions(FaceLiveness.PASSIVE);2 captureOptions.setCamera(Camera.FRONT);3 captureOptions.setCaptureTimeout(120);4 captureOptions.setOverlay(Overlay.OFF);5 captureOptions.setTorch(Torch.OFF);
- In the
onResume()
method of your activity or fragment, obtain a valid reference to theIBioCaptureHandler
using the previously created capture options.
Java1protected void onResume() {2 //Create handler3 BioSdk.createFaceCaptureHandler(this, captureOptions, new MscAsyncCallbacks<IFaceCaptureHandler>() {4 @Override5 public void onPreExecute() {6 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`7 }8 @Override9 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 @Override14 public void onError(BioCaptureHandlerError e) {15 // An error has occurred during the initialization16 }17 });18 super.onResume();19 }
- Add the listeners for the events to the handler:
Java1faceCaptureHandler.setFaceCaptureResultListener(new FaceCaptureResultListener() {2 @Override3 public void onCaptureSuccess(@NotNull FaceImage image) {4 //Successfully captured image5 }67 @Override8 public void onCaptureFailure(@NotNull CaptureError captureError,9 @NotNull IBiometricInfo biometricInfo,10 @NotNull Bundle extraInfo) {11 //Capture failure12 );13 }14 });15 faceCaptureHandler.setFaceCaptureFeedbackListener(new FaceCaptureFeedbackListener() {16 @Override17 public void onCaptureInfo(FaceCaptureInfo captureInfo) {18 //Face capture feedback info, like move your face to the right19 }20 });21 faceCaptureHandler.setFaceTrackingListener(new FaceCaptureTrackingListener() {22 @Override23 public void onTracking(List<FaceTracking> trackingInfo) {24 //Tracking info to know where the face is.25 }26 });
- 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 @Override3 public void onStarted() {4 try {5 captureHandler.startCapture();6 } catch (MSCException e) {7 // handle exception8 }9 }1011 @Override12 public void onError(PreviewError error) {13 // Preview initialization failed and can not be started14 }15 });
- Destroy the handler when
onPause()
is invoked:
Java1@Override2 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
- In your manifest, you must add:
XML1<!--Declare new permissions-->2 <permission3 android:name="your.new.permission.NEW_READ_LKMS_LICENSE_PROVIDER"4 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->5 <permission6 android:name="your.new.permission.NEW_WRITE_LKMS_LICENSE_PROVIDER"7 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->8 <permission9 android:name="your.new.permission.NEW_READ_MPH_BIO_SDK_PROVIDER"10 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->11 <permission12 android:name="your.new.permission.NEW_WRITE_MPH_BIO_SDK_PROVIDER"13 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
XML1<!--The provider must be defined by the implementing app so as to allow multiple apps-->2 <!--Bio store provider provider-->3 <provider4 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>
XML1<!--The provider must be defined by the implementing app so as to allow multiple apps-->2 <!--License provider-->3 <provider4 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:
Gradle1//Feature plugins2implementation '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'910//Algorithm plugins11implementation '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 |
---|---|
CaptureFace | 24.16 MB |
CaptureDocument | 16.82 MB |
CaptureFinger | 17.19 MB |
CaptureBiometry | 28.65 MB |
CaptureBiometry_document | 43.26 MB |
CaptureFace_document | 38.76 MB |
Plugins size
Plugin | Size |
---|---|
plugin-face | 7.59 KB |
plugin-face-normal | 6.75 MB |
plugin-face-lite | 4.79 MB |
plugin-face-cr2dmatching | 6.75 MB |
plugin-finger | 794.64 KB |
plugin-algorithm-f5-4-low75 | 12.30 MB |
plugin-algorithm-f5-0-vid81 | 4.08 MB |
plugin-algorithm-f6-5-low70 | 7.45 MB |
plugin-algorithm-fingerv9 | 1.51 KB |
plugin-improved-pdf417-detection | 8.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 timeout
Below is the generic execution flow to be followed when a capture timeout occurs.
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 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 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.
Creating BioMatcherHandler
Below is the generic execution flow to retrieve and release a BioMatcherhandler
.
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(...)
.
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.
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.
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.
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:
XML1implementatation "morpho.mph_bio_sdk.android:SmartFinger:$smartSdkVersion"
Custom:
XML1implementation "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.
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
-
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 chooseTHUMB
you can only scan a thumb. -
When the FingerCaptureOptions configuration completes, create FingerCaptureHandler.
-
Register the listener with result callbacks.
-
To perform a capture, start the camera preview and then start the capture.
-
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
- Create
LicenseMangager
. - Retrieve the license.
- Activate the license.
- Get a list of templates from
MorphoTemplate
. - Create a
BiometricReference
. - Create the
FingerCaptionOptions
with addedBiometricReference
and threshold. - Create the
FingerCaptureHandler
. - Set the listener,
setAuthenticationListener
. - Start the capture.
- On
callback
, process the result. - Stop the capture.
Below is the sequence diagram of that flow.
Creating fast authentication use case
- 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
.
Kotlin1BioStoreDB.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() {}1415 override fun onSuccess(references: List<IMorphoTemplate>) {16 ...17 //reference candidates18 val reference = BiometricReference(user.uuid, BiometricModality.FRICTION_RIDGE)19 reference.addTemplates(references)20 ...21 }2223 override fun onError(e: Exception) {}24 })25 }26 }2728 override fun onError(e: Exception) {}29})
- Add to
FingerCaptureOptions
theIBiometricReference
with a threshold and create theFingerCaptureHandler
.
Create FingerCaptureOptions
with the added threshold
and biometricRefernece
. Then create FingerCaptureHandler
.
Kotlin1val fingerCaptureOptions = FingerCaptureOptions(BioCaptureMode.FINGERS, Hand.RIGHT)2captureOptions.liveness = FingerLiveness.LOW3captureOptions.bioCaptureMode = BioCaptureMode.FINGERS4captureOptions.camera = Camera.REAR5captureOptions.overlay = Overlay.ON6captureOptions.captureTimeout = 107fingerCaptureOptions.biometricReference = reference8fingerCaptureOptions.threshold = 30009fingerCaptureOptions.uhdResolutionEnabled = true10createFingerCaptureHandler(fingerCaptureOptions)1112BioSdk.createFingerCaptureHandler(this, captureOptions, object : MscAsyncCallbacks<IFingerCaptureHandler> {13 override fun onPreExecute() {}14 override fun onSuccess(result: IFingerCaptureHandler) {15 onFingerCaptureInitialized(result)16 }1718 override fun onError(e: BioCaptureHandlerError) {}19})
- Add the listener to the
FingerCaptureHandler
responsible for thefast 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.
Kotlin1fingerCaptureHandler.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 long | The authentication score (between 0 and 50000). |
authenticationStatus AuthenticationStatus | The 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 |
---|---|
SUCCESS | Authentication was successful. |
FAILURE | Authentication was not successful. |
Capture errors
Errors returned when finger capture fails.
Name | When | Why |
---|---|---|
CAPTURE_TIMEOUT | Used time for capture | Fingers were not captured properly in time |
CAPTURE_DELAYED | Failing captures repeatedly | Prevent spoofing |
BAD_CAPTURE_FINGERS | Capture of fingers failed | Couldn't find fingerprints on captured image |
BAD_CAPTURE_HAND | Capture of hand failed | Wrong hand scanned |
LIVENESS_CHECK | Liveness check failed | Fingerprints 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 @Override5 public void onPreExecute() {6 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`7 }89 @Override10 public void onSuccess(UUID result) {11 //User saved12 }1314 @Override15 public void onError(Exception e) {16 // An error has occurred17 }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 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(List<IMorphoTemplate> result) {9 //The list of templates that match the criteria10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred15 }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 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(UUID result) {9 //The template has been added, and template's uuid is returned as a parameter10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred15 }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 format4 bioMatcherSettings.setFingerprintTemplate(MorphoFingerTemplateFormat.PKCOMPV2);5 BioSdk.createBioMatcherHandler(this, bioMatcherSettings, new BioMatcherAsyncCallbacks<IBioMatcherHandler>() {6 @Override7 public void onPreExecute() {8 // Optional hook on the builtin Android AsyncTask call-back `onPreExecute`9 }1011 @Override12 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 }1617 @Override18 public void onError(Exception e) {19 // An error has occurred20 }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 andscore
which might be in the range 0 – 50000.
1//Authentication options2IAuthenticationOptions authenticationOptions = new AuthenticationOptions();3authenticationOptions.setThreshold(3500);45//Biometric candidate6IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FRICTION_RIDGE);7//We add all the templates for this candidate8biometricCandidate.addTemplates(candidates);910//Biometric references11IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FRICTION_RIDGE);12//We add all the templates for this user13biometricReference.addTemplates(references);1415matcherHandler.authenticate(authenticationOptions, biometricCandidate, biometricReference, new BioMatcherAsyncCallbacks<IAuthenticationResult>() {16 @Override17 public void onPreExecute() {18 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`19 }2021 @Override22 public void onSuccess(IAuthenticationResult result) {23 //The result of the authentication24 long resultScore = result.getScore();25 //authentication status (FAILURE, SUCCESS...)26 AuthenticationStatus authenticationStatus = authenticationResult.getStatus();27 }2829 @Override30 public void onError(Exception e) {31 // An error has occurred32 }33});
Parameters
Parameter | Description |
---|---|
authenticationOptions IAuthenticationOptions | The options used to perform the authentication. This object holds the threshold that the score must exceed to accept the candidate. |
biometricCandidate IBiometricCandidate | Contains the list of templates to match against. |
biometricReference IBiometricReference | Contains 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 |
---|---|---|
BioCaptureMode | Capture modes that are described earlier | BioCaptureMode.FINGERPRINT_RIGHT_CAPTURE |
Overlay | Intuitive rectangles that help the user properly place their fingers during a capture | Overlay.ON |
Camera | Smartphone's camera that will be used during the capture | Camera.REAR |
Liveness | Level of challenge that the fingers image must pass to be considered alive | FingerLiveness.MEDIUM |
Timeout | Duration of capture in seconds | ~10 |
amputeeFingers | Information about which fingers are missing with BioCaptureMode.FINGERS | |
hand | Information about which hand will be scanned |
Capture flow
Sequence diagram
-
After the activation of license, create the handler with the necessary defined capture options.
-
Register the listener to get the result callbacks.
-
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
Capture options configuration
Kotlin1val options = FingerCaptureOptions()2 options.bioCaptureMode = BioCaptureMode.FINGERS3 options.overlay = Overlay.ON4 options.camera = Camera.REAR5 options.captureTimeout = 106 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.
Kotlin1val handler = BioSdk.createFingerCaptureHandler(context, options)2 handler.setFingerCaptureResultListener(object : FingerCaptureResultListener {3 override fun onCaptureFailure(4 captureError: CaptureError,5 biometricInfo: IBiometricInfo,6 extraInfo: Bundle7 ) {8 // handle capture failure9 }1011 override fun onCaptureSuccess(12 images: MutableList<MorphoImage>,13 captureResult: FingerCaptureResult14 ) {15 // handle capture success16 }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 thanFingerLiveness.NONE
. It consists of ascore
value that represents the confidence of liveness recognition and theFingerLivenessResult
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:
- Add the SDK library to your app's
build.gradle
:
Java1implementation ("morpho.mph_bio_sdk.android:SmartDoc:version")
- Add the
CaptureView
to the layout where you handle the biometric capture.
XML1<com.idemia.smartsdk.preview.CaptureView2 android:id="@+id/captureView"3 android:layout_width="match_parent"4 android:layout_height="match_parent" />
- On your activity or fragment, get a reference to this view:
Java1CaptureView cameraPreview = (CaptureView) findViewById(R.id.captureView);
- Activate your license. You can do that in the
onCreate(Bundle savedInstanceState)
, or in a previous stage of your app.
Kotlin1LicenseManager 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 }
- In the
onResume()
method of your activity or fragment, you must obtain a valid reference of theIDocumentCaptureHandler
.
Java1protected void onResume() {2 //Sample configuration3 //The activate process was OK.4 // Populate a CaptureOptions object5 IDocumentCaptureOptions captureOptions = new DocumentCaptureOptions(6 new DocumentCaptureModeConfiguration {7 public DocumentMode provideCaptureMode() {8 return DocumentMode.READ_MRZ9 }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 @Override18 public void onPreExecute() {19 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`20 }21 @Override22 public void onSuccess(IDocumentCaptureHandler result) {23 // Indicates that initialization succeeded, the returned handler can be used to start the capture.24 }25 @Override26 public void onError(BioCaptureHandlerError e) {27 // An error has occurred during the initialization28 }29 });30 super.onResume();31 }
- Add the listeners for the events to the handler.
Java1//MRZ callbacks2captureHandler.setDocumentCaptureListener(new DocumentCaptureListener() {3 @Override4 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 captured7 try {8 byte[] jpegImage = image.getJPEGImage(); Bitmap documentImage = BitmapFactory.decodeByteArray(jpegImage, 0, jpegImage.length);9 //show the document image10 }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 image15 List<DocumentImage> croppedImages = ImageUtils.extractImages(image);16 }17 @Override18 public void onCaptureFieldImageDocument(DocumentImage image, String labelName) {19 //A field has been coded20 }21 @Override22 public void onMRZDocumentRead(List<IMRZLine> mrzLines, IMrzRecord mrzRecord) {23 //MRZ captured24 }25 @Override26 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {27 //Capture failed28 }29 @Override30 public void onCaptureFinish() {31 //Capture finished32 }33});34//Barcode callbacks35captureHandler.setBarcodeListener(new BarcodeListener() {36 @Override37 public void onBarcodeRead(List<String> capture) {38 //Barcode captured39 }40 @Override41 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {42 //Capture failed43 }44 @Override45 public void onCaptureFinish() {46 //Capture finished47 }48});49//Capture feedback listener50captureHandler.setDocCaptureFeedbackListener(new DocumentCaptureFeedbackListener() {51 @Override52 public void onCaptureInfo(DocCaptureInfo docCaptureInfo) {53 //Document captures info54 }55});56//Tracking listener57captureHandler.setDocumentTrackingListener(new DocumentCaptureTrackingListener() {58 @Override59 public void onTracking(List<MorphoDocumentRegion> trackingInfo) {60 //Tracking info61 }62});
- Initialize the preview and capture to start the receive events.
1 captureHandler.startPreview(new PreviewStatusListener() {2 @Override3 public void onStarted() {4 try {5 captureHandler.startCapture();6 } catch (MSCException e) {7 // handle exception8 }9 }1011 @Override12 public void onError(PreviewError error) {13 // Preview initialization failed and can not be started14 }15 });
- Destroy the handler when
onPause()
is invoked.
Java1@Override2 protected void onPause() {3 if(captureHandler!=null) {4 captureHandler.destroy();5 }6 super.onPause();7 }
- If you must force a document capture:
Java1if(captureHandler!=null){2 //Force a document capture3 captureHandler.forceCapture();4}
- In your manifest you must add:
XML1<!--Declare new permissions-->2 <permission3 android:name="your.new.permission.NEW_READ_LKMS_LICENSE_PROVIDER"4 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->5 <permission6 android:name="your.new.permission.NEW_WRITE_LKMS_LICENSE_PROVIDER"7 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->8 <permission9 android:name="your.new.permission.NEW_READ_MPH_BIO_SDK_PROVIDER"10 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->11 <permission12 android:name="your.new.permission.NEW_WRITE_MPH_BIO_SDK_PROVIDER"13 android:protectionLevel="signature" /> <!--unless otherwise required, set the maximum security permission -->
XML1<!--Remove old permissions-->2 <permission3 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider.READ_MPH_BIO_SDK_PROVIDER"4 tools:node="remove" />5 <permission6 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider.WRITE_MPH_BIO_SDK_PROVIDER"7 tools:node="remove" />8 <permission9 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider.WRITE_LKMS_LICENSE_PROVIDER"10 tools:node="remove"11 />12 <permission13 android:name="com.idemia.license.android.sdk.content_provider.LicenseStoreProvider.READ_LKMS_LICENSE_PROVIDER"14 tools:node="remove"15 />
XML1<!--The provider must be defined by the implementing app so as to allow multiple apps-->2<!--Bio store provider provider-->3<provider4 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>
XML1<!--The provider must be defined by the implementing app so as to allow multiple apps-->2<!--License provider-->3<provider4 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>
- You must also set to landscape the orientation of the activity that will read MRZ:
XML1<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.
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 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.
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
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.
-
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.
-
Add
DocumentCaptureView
to the layout. This will be not only capture preview but also entry point to the SDK.
XML1<com.idemia.capture.document.api.DocumentCaptureView2 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.
- 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 String | Live capture session id created with: v1/identities/{identityId}/id-documents/live-capture-session |
apiKey String | ApiKey for authorization on DocServer. |
baseUrl String | Url of document server - for example: https://idproofing-api.environment.idemia.io/doc-server/ |
Kotlin1captureView.setUp(2 RemoteUseCase(3 feedbackListener,4 adjudicationListener,5 sessionInfo,6 timeoutListener7 ),8 lifecycle9)
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.
-
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. -
onResult(result: Result)
- returns result of remote flow. No other callback will occur after this method. Result might be type of Success or Failure.
Kotlin1private val remoteListener = object : RemoteListener {2 override fun onDocumentCaptured(3 images: List<DocumentImage>,4 captureFinalizer: CaptureFinalizer5 ) {6 //Handle captured document7 }89 override fun onResult(result: Result) {10 when (result) {11 is Failure -> //Handle failure result12 is Success -> //Handle success result13 }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.
Kotlin1private val feedbackListener = object : FeedbackListener {2 override fun onFeedback(feedback: CaptureFeedback) {3 //Present feedback to the user4 }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!
Kotlin1private val timeoutListener = CaptureTimeoutListener { documentImages ->2 // Show images to the user3 }
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 FailureType | Type of an error. High level information what goes wrong. Find types description below. |
code Int | Special code dedicated for particular case. Very helpful in L2, L3 troubleshooting. |
message String | Message with error description. |
qualityIndicators DocumentImageQualityIndicators? | Contains information what went wrong if document was not captured before timeout. |
FailureType
Type | Description |
---|---|
CONNECTION_ISSUE | General issue with connection. See message and error code for more informations. |
AUTHENTICATION | Backend authentication failed. Probably wrong credentials has been used for the given environment. |
INVALID_SESSION | Session ID is not correct. Most probably session expired or has been finished. |
TIMEOUT | Timeout occured during the flow. |
BAD_CAPTURE | Capture failed. Face was not detected or liveness check did not pass. |
UNKNOWN | Unknow type of exception. Also used as default type for few cases. |
CANCELED | Flow has been canceled. Can be triggered by integrator or automatically when Lifecycle has been passed to setUp method. |
INVALID_LICENSE | License 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 Boolean | Indicates if there was a problem with detecting entire document |
blur Boolean | Indicates if document was blurred |
glare Boolean | Indicates if reflections were detected |
tooClose Boolean | Indicates if document was too close from the camera |
tooFar Boolean | Indicates if document was too far from the camera |
notStraight Boolean | Indicates if document was straight |
lowLight Boolean | Indicates if lightning conditions were good enough |
badConsistency Boolean | Indicates 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:
Java1IBioSdkInfo 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:
Java1[...]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 Network | Preferred network type that will be used to send the report. |
analyticsConfigurationData AnalyticsConfigurationData | Class 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.
Java1// Get activity from application2 Activity activity = ...3 // Populate a CaptureOptions object4 IDocumentCaptureOptions captureOptions = new DocumentCaptureOptions(5 new DocumentCaptureModeConfiguration {6 public DocumentMode provideCaptureMode() {7 return DocumentMode.READ_MRZ8 }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 @Override18 public void onPreExecute() {19 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`20 }21 @Override22 public void onSuccess(IDocumentCaptureHandler result) {23 // Indicates that initialization succeeded, the returned handler can be used to start the capture.24 }25 @Override26 public void onError(DocumentCaptureHandlerError e) {27 // An error has occurred during the initialization28 }29 });
Parameter | Description |
---|---|
activity Activity | The Android activity. |
options IDocumentCaptureOptions | The capture options to configure the document capture handler. |
callbacks MscAsyncCallbacks | Callbacks to be executed depending on the result. |
Errors
Error code | Description |
---|---|
MSC_ERR_APPLINOTAVAILABLE | The application parameter is not available. |
MSC_ERR_GRAPH_INITIALISATION_FAILED | The graph initialization failed. |
MSC_ERR_INIT | Initialization failed. |
MSC_ERR_PARAMETERS | The parameters are invalid. |
MSC_ERR_PARAMETER_NOT_FOUND | The parameter is missing. |
MSC_ERR_PARAMETER_SIZE | The parameter size is incorrect. |
MSC_ERR_PARAMETER_UNKNOWN | One of the parameters is unknown. |
MSC_ERR_INVALID_HANDLE | The handle is invalid. |
LIBS_NOT_FOUND | The java libraries are not found. |
NO_CONTEXT_SET | The java context is not set. |
NOT_EXECUTED | The java is unable to execute. |
MSC_ERR_LICENSE | The license is invalid. |
MSC_ERR_MEMALLOC | The memory allocation issue. |
MSC_ERR_PROFILENOTAVAILABLE | DocumentCapture profile is not available. |
MSC_ERR_SUBPROFILENOTAVAILABLE | DocumentCapture sub-profile is not available. |
MSC_ERR_TYPE_MISMATCH | DocumentCapture type mismatch . |
UNKNOWN | Unknown 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:
Java1captureHandler.setDocumentCaptureListener(new DocumentCaptureListener() {2 @Override3 public void onCaptureImageDocument(DocumentImage image) {4 //Document image captured5 try {6 byte[] jpegImage = image.getJPEGImage();7 Bitmap documentImage = BitmapFactory.decodeByteArray(jpegImage, 0, jpegImage.length);8 //show the document image9 }catch (Exception e){10 Log.e(TAG, "", e);11 }12 }13 @Override14 public void onCaptureFieldImageDocument(DocumentImage image, String labelName) {15 //A field has been coded16 }17 @Override18 public void onMRZDocumentRead(List<IMRZLine> mrzLines) {19 //MRZ captured20 }21 @Override22 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {23 //Capture failed24 }25 @Override26 public void onCaptureFinish() {27 //Capture finished28 }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
.
Java1//Barcode callbacks for text data2 captureHandler.setBarcodeListener(new BarcodeListener(){3 @Override4 public void onBarcodeRead(List<String> capture){5 //Barcode captured6 }7 @Override8 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {9 //Capture failed10 }11 @Override12 public void onCaptureFinish() {13 //Capture finished14 }15 });
Java1//Barcode callbacks for raw data2 captureHandler.setBarcodeListener(new BarcodeListener(){3 @Override4 public void onBarcodeRead(RTBuffer capture){5 //Barcode captured6 }7 @Override8 public void onDocumentCaptureFailure(DocumentCaptureError captureError, DocumentImageQualityIndicators indicators) {9 //Capture failed10 }11 @Override12 public void onCaptureFinish() {13 //Capture finished14 }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.
Java1captureHandler.setDocCaptureFeedbackListener(new DocumentCaptureFeedbackListener() {2 @Override3 public void onCaptureInfo(DocCaptureInfo docCaptureInfo) {4 //Document captures info5 }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:
Java1captureHandler.setVideoRecordingReadyForGenerationListener(new VideoRecordingReadyForGenerationListener() {23 @Override4 public void videoRecordingReadyForGeneration(VideoRecording videoRecording) {5 //Video recording object to generate video6 }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 @Override3 public void onStarted() {4 try {5 captureHandler.startCapture();6 } catch (MSCException e) {7 // handle exception8 }9 }1011 @Override12 public void onError(PreviewError error) {13 // Preview initialization failed and can not be started14 }15 });
Stop preview
This stops the camera preview as shown in the snippet:
Java1handler.stopPreview()
Start capture
This starts the biometric capture as shown in the snippet.
Java1handler.startCapture();
Stop capture
This stops the biometric capture as shown in the snippet:
Java1handler.stopCapture();
Switch camera
This switches between different cameras as shown in the snippet:
Java1handler.switchCamera(Camera.FRONT); // Use front camera2handler.switchCamera(Camera.REAR); // Use rear camera
Destroy
This releases all the handler resources as shown in the snippet:
Java1handler.destroy();
Overlay
This sets the overlay option as shown in the snippet:
Java1handler.setOverlay(Overlay.OFF); // Disable preview's overlay2handler.setOverlay(Overlay.ON); // Enable preview's overlay
Torch
This sets the torch option as shown in the snippet:
Java1handler.setTorch(Torch.OFF); // Disable the torch2handler.setTorch(Torch.ON); // Enable the torch
CaptureOptions
This retrieves the capture options used in this handler, as shown in the snippet:
Java1IDocumentCaptureOptions options = handler.getCaptureOptions();
Force capture
This forces a capture as shown in the snippet:
Java1handler.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:
Java1handler.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:
Java1CaptureHandlerStatus 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 String | The version of the SDK. |
DocumentCaptureOptions
This object is used to configure the behavior of the DocumentCapture
.
Attribute | Description |
---|---|
captureMode DocumentCaptureMode | The app enum option to configure the capture. |
camera Camera | The app camera option to configure the capture. |
torch Torch | Sets the torch value. |
overlay Overlay | Sets the overlay value. |
captureTimeout Long | Captures the timeout in seconds (default value 120). |
captureImageTimeout Long | Sets 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 LogLevel | Sets the log level. |
DebugDataSettings Debug Data | Sets 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 Rectification | Sets image rectification. Enabled by default. |
acquisitionMode AcquisitionMode | Sets the speed/quality balance during a document capture. |
minDPI int | Minimum resolution in dpi of the datapage captured. Possible value from 1 to 400. |
stillShootEnable Boolean | When enabled, the document image is taken with a single shot with higher resolution. If not, best image from video stream is taken. |
videoRecordingOptions VideoRecordingOptions | When enabled, CaptureSDK returns VideoRecording to generate video from the taken capture. (By default video recording is disabled.) |
uhdResolutionEnabled Boolean | When 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 int | The stride of the biometric. |
width long | The width of the image. |
height long | The height of the image. |
colorSpace ColorSpace | The ColorSpace of the image. |
resolution float | The resolution of the image. |
imageQuality int | Image quality if available, otherwise -1 . Currently only available for fingerprint images. |
label | Label 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 List | A 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 DocumentLocation | Zone in the document to locate specific data, such as a photo or MRZ. |
codedMode CodedMode | Indicates how this image was triggered. |
docLevel DocLevel | Gives information concerning the confidence of the information returned. |
DocumentImageQualityIndicators
This object contains failure reasons of the capture.
Parameter | Description |
---|---|
blur Boolean | Indicates if document was blurred |
glare Boolean | Indicates if reflections were detected |
tooClose Boolean | Indicates if document was too close from the camera |
tooFar Boolean | Indicates if document was too far from the camera |
notStraight Boolean | Indicates if document was straight |
lowLight Boolean | Indicates if lightning conditions were good enough |
badConsistency Boolean | Indicates if enough consecutive good frames were detected for document |
pdf417BadDecoding DocumentImageQualityIndicator | Indicates if pdf417 was detected |
mrzBadDecoding DocumentImageQualityIndicator | Indicates if mrz was detected |
MorphoDocumentRegion
This object contains the coordinates of the document.
Parameter | Description |
---|---|
point1 PointF | Point 1 (Top left) |
point2 PointF | Point 2 (Top right) |
point3 PointF | Point 3 (Bottom right) |
point4 PointF | Point 4 (Bottom left) |
documentLocation DocumentLocation | Zone in the document to locate specific data, such as a photo or MRZ. |
previewRect Rect | The 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 MorphoMrzDocumentCode | The document code. |
morphoMrzDocumentFormat MorphoMrzDocumentFormat | The document format. |
morphoMrzSex MorphoMrzSex | Gender |
code1 char | MRZ code 1 |
code2 char | MRZ code 2 |
issuingCountry String | Issuing country |
documentNumber String | Document number |
surname String | Surname |
surname String | Surname |
givenNames String | Given names |
dateOfBirth Calendar | Date of birth |
expirationDate Calendar | Expiration date |
IMrzFrenchIdCardRecord
The MRZ record interface for French identity cards. It extends IMrzRecord
.
Parameter | Description |
---|---|
optional String | Optional data |
IMrzMRPRecord
The MRZ record interface for MRP cards. It extends IMrzRecord
.
Parameter | Description |
---|---|
personalNumber String | Personal number |
IMrzMrtdTd1Record
The MRZ record interface for MRTD TD1 cards. It extends IMrzRecord
.
Parameter | Description |
---|---|
optional String | Optional data |
optional2 String | Optional data |
IMrzMrtdTd2Record
The MRZ record interface for MRTD TD2 cards. It extends IMrzRecord
.
Parameter | Description |
---|---|
optional String | Optional data |
IMrzMrvARecord
The MRZ record interface for MRV A cards. It extends IMrzRecord
.
Parameter | Description |
---|---|
optional String | Optional data |
IMrzMrvBRecord
The MRZ record interface for MRV B cards. It extends IMrzRecord
.
Parameter | Description |
---|---|
optional String | Optional data |
IMrzSlovackId2_34Record
The MRZ record interface for Slovakian identity cards. It extends IMrzRecord
.
Parameter | Description |
---|---|
optional String | Optional data |
GenericDocumentCaptureListener
This is a generic capture listener.
onDocumentCaptureFailure
This is invoked if DocumentCaptureHandler
fails to do a capture. Check DocumentCaptureError.
Function
Java1void onDocumentCaptureFailure(@NonNull DocumentCaptureError captureError, @Nullable DocumentImageQualityIndicators indicators)
Arguments
Parameter | Description |
---|---|
captureError DocumentCaptureError | An error |
indicators DocumentImageQualityIndicators | Contains information about document integrity, sharpness, lightning and reflections. May be null . |
onCaptureFinish
This is invoked by DocumentCaptureHandler
when it finishes the capture process.
Function
Java1void 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
Java1void onCaptureImageDocument(DocumentImage image);
Arguments
Parameter | Description |
---|---|
image DocumentImage | The document image. |
onCaptureFieldImageDocument
This is invoked if a document field has been captured. Check DocumentImage.
Function
Java1void onCaptureFieldImageDocument(DocumentImage image, String labelName);
Arguments
Parameter | Description |
---|---|
image DocumentImage | The document image. |
labelName String | The 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
Java1void onMRZDocumentRead(List<IMRZLine> mrzLines, IMrzRecord mrzRecord)
Arguments
Parameter | Description |
---|---|
mrzLines List | A list of MRZ lines read. |
mrzRecord IMrzRecord | The 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
Java1void onBarcodeRead(List<String> capture)
Arguments
Parameter | Description |
---|---|
capture List | A list of lines read. |
Function
Java1void onBarcodeRead(RTBuffer capture)
Arguments
Parameter | Description |
---|---|
capture RTBuffer | Raw 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:
Java1void onCaptureInfo(DocCaptureInfo docCaptureInfo);
Arguments
Parameter | Description |
---|---|
docCaptureInfo DocCaptureInfo | The feedback. |
DocumentCaptureTrackingListener
Tracking listener
This sets the listener to receive tracking information, such as where the biometric is located.
Java1captureHandler.setDocumentTrackingListener(new DocumentCaptureTrackingListener() {2 @Override3 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 int | The line number of the MRZ read. |
consorank int | The rank number of the MRZ read. |
Text String | The MRZ text line. |
docLevel DocLevel | Gives 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.
Java1videoRecording.generateVideo(new VideoProgressListener() {234 @Overide5 void onFinish(String path) {6 //When creating video comlete with success return path to video7 }89 @Overide10 void progress(int progress) {11 //Showing progress of generating video from 0 to 10012 }1314 @Overide15 void onError(VideoError error) {16 //It's call when generating video failed or another video is current generating17 }18});
If you do not want to generate video from the previous capture, use:
Java1videoRecording.clean()
Enums
ColorSpace
This is the colorspace enum.
Attribute | Description |
---|---|
Y8 | Grayscale 8bpp image. |
Y16LE | Grayscale 16bpp image (Little Endian). |
BGR24 | Colour 24bpp BGR image (BMP like memory layout). |
RGB24 | Colour 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 |
---|---|
FRONT | Front camera |
REAR | Rear camera |
Torch
This is the enum used to configure the torch for DocumentCapture
.
Attribute | Description |
---|---|
OFF | Torch off |
ON | Torch on |
Overlay
This is the enum used to configure the overlay for DocumentCapture
.
Attribute | Description |
---|---|
OFF | Overlay off |
ON | Overlay on |
OCR (OBSOLETE)
This is the enum used to configure the optical character recognition for DocumentCapture
(obsolete).
Attribute | Description |
---|---|
DISABLE | OCR off |
ENABLE | OCR on |
Rectification
This is the enum used to configure the rectification for DocumentCapture
.
Attribute | Description |
---|---|
DISABLE | Rectification off |
ENABLE | Rectification on |
DocumentCaptureMode
This is the enum used to configure the mode for DocumentCapture
.
Attribute | Description |
---|---|
READ_MRZ | Reads MRZ lines. |
READ_MRZ_DOCUMENT_IMAGE_MEDIUM | Allows the capture of an image at the device's best video resolution after MRZ reading. |
QR_CODE | Reads a QR Code. |
QR_CODE_PDF_417 | Reads PDF417. |
CAPTURE_DOCUMENT_IMAGE_VERY_LOW_ID | Captures an image at the device's best video resolution of ID1, ID2, and ID3 documents. |
CAPTURE_DOCUMENT_IMAGE_VERY_LOW_A4 | Captures an image at the device's best video resolution of an A4 document. |
CAPTURE_DOCUMENT_IMAGE_BARCODE_VERY_LOW_ID1 | Captures an image and read a barcode at the device's best video resolution of ID1 documents. |
CAPTURE_DOCUMENT_IMAGE_VERY_LOW_ID1 | Captures 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 |
---|---|
LOW | Low quality high speed |
MEDIUM | Medium quality medium speed |
HIGH | High quality low speed |
DocumentCaptureError
This enum reports why the document capture fails.
Attribute | Description |
---|---|
UNKNOWN | Unknown error |
INVALID_MRZ | Invalid MRZ line read |
CAPTURE_TIMEOUT | Capture timeout |
BAD_CAPTURE_BARCODE | Barcode capture failed |
BAD_CAPTURE_DOCUMENT | Document capture failed |
BAD_CAPTURE_DOCUMENT_IMAGE | Document image capture failed |
LogLevel
This enum controls the log level.
Attribute | Description |
---|---|
ERROR | Error log level or above |
DEBUG | Debug log level or above |
WARNING | Warning log level or above |
INFO | Info log level or above |
DISABLE | Disables logs |
DocCaptureInfo
This enum reports the document capture information.
Attribute | Description |
---|---|
BADFRAMING | Bad framing detected. |
BLUR | Blur detected. |
ENDSTILL | Point and shoot capture done. |
STARTSTILL | Start point and shoot capture. |
SHAKING | Shaking detected. |
HOLD_STRAIGHT | Hold document straight. |
REFLECTION | Reflection detected. |
TOO_FAR | The document is too far. |
TOO_CLOSE | The document is too close. |
OK | Everything is OK. |
DOCUMENT_NOT_DETECTED | Document not detected within an internal timeout. |
DocumentLocation
This enum shows biometric locations.
Attribute | Description |
---|---|
DOC_MRZ | MRZ zone |
DOC_DATAPAGE | Data page zone |
DOC_PHOTO | Photo zone |
DOC_REFLECT | Reflect zone |
UNKNOWN | Unknown |
CaptureHandlerStatus
This enum retrieves the status of the capture handler.
Attribute | Description |
---|---|
STOP | The handler is stopped. |
PREVIEW | The handler is in preview mode. |
CAPTURE | The handler is in capture mode. |
MorphoMrzDocumentCode
This enum retrieves the MRZ document code.
Attribute | Description |
---|---|
CREW_MEMBER | Crew member code |
MIGRANT | Migrant code |
PASSPORT | Passport code |
TYPE_A | TYPE_A code |
TYPE_C | TYPE_C code |
TYPE_I | TYPE_I code |
TYPE_V | TYPE_V code |
MorphoMrzDocumentFormat
This enum retrieves the MRZ document format.
Attribute | Description |
---|---|
FRENCH_ID | French identity card |
MRTD_TD1 | MRTD TD1 |
MRTD_TD2 | MRTD TD2 |
MRV_VISA_A | MRV Visa A |
MRV_VISA_B | MRV Visa B |
PASSPORT | Passport |
SLOVAK_ID_234 | Slovak identity card |
MorphoMrzSex
This enum retrieves the MRZ document gender.
Attribute | Description |
---|---|
MALE | Male gender |
FEMALE | Female gender |
UNSPECIFIED | Unspecified gender |
Century
This enum helps parse the year of the MRZ documents; only the last two digits of the year are provided.
Attribute | Description |
---|---|
NONE | No century used for extracting the year |
NINETEEN | Nineteenth century used for extracting the year |
TWENTY | Twentieth century used for extracting the year |
TWENTY_ONE | Twenty-first century used for extracting the year |
TWENTY_TWO | Twenty-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 |
---|---|
NOMINAL | All video quality criteria have been fulfilled and the best image is returned. |
FORCE | Force capture trigger has been used |
TIMEOUT | Best image returned on timeout |
DocLevel
This enum gives information concerning the confidence of the information returned.
Attribute | Description |
---|---|
VERY_LOW | Can be obtained with all profiles |
LOW | Can be obtained with high, medium, or low profiles |
MEDIUM | Can be obtained with high or medium profiles |
HIGH | Can be obtained with high profiles |
Integrity
This enum gives information if the image integrity is acceptable.
Attribute | Description |
---|---|
OK | Document integrity is ok |
NOT_OK | Document integrity is invalid |
Sharpness
This enum gives information if the sharpness integrity is acceptable.
Attribute | Description |
---|---|
OK | Document image is sharp |
NOT_OK | Document image is not sharp |
Reflections
This enum gives information if reflections on the document were detected.
Attribute | Description |
---|---|
NOT_DETECTED | No reflections on document image |
DETECTED | Reflections on document image |
Lighting
This enum gives information about lightning condition.
Attribute | Description |
---|---|
OK | Image captured in good lightning conditions |
BAD | Lightning conditions were not good enough for the capture |
DocumentImageQualityIndicator
This enums gives information about quality indicator
Attribute | Description |
---|---|
TRUE | Given indicator is not acceptable |
FALSE | Given indicator is acceptable |
NOT_APPLICABLE | Indicator 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:
Java1val JPEG_COMPRESSION_LEVEL = 922private 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()78 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.
Java1IBioSdkInfo 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 Network | Preferred network type that will be used to send report. |
analyticsConfigurationData AnalyticsConfigurationData | Class 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.
- 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.FRONT3 captureTimeout = 1204 overlay = Overlay.OFF5 torch = Torch.OFF6 }7 val captureHandler = FaceCaptureHandler(context, captureOptions)
Parameter | Description |
---|---|
activity Activity | The Android activity. |
options IFaceCaptureOptions | The capture options to configure the bio capture handler. |
callbacks BioCaptureAsyncCallbacks | Callbacks to be executed depending on the result. |
Errors
Error code | Description |
---|---|
MSC_ERR_APPLINOTAVAILABLE | The application parameter is not available. |
MSC_ERR_GRAPH_INITIALISATION_FAILED | The graph initialization failed. |
MSC_ERR_INIT | Initialization failed. |
MSC_ERR_PARAMETERS | Parameters are invalid. |
MSC_ERR_PARAMETER_NOT_FOUND | Parameter is missing. |
MSC_ERR_PARAMETER_SIZE | Parameter size is incorrect. |
MSC_ERR_PARAMETER_UNKNOWN | One of the parameters is unknown. |
MSC_ERR_INVALID_HANDLE | Handle is invalid. |
LIBS_NOT_FOUND | Java libraries are not found. |
NO_CONTEXT_SET | Java context is not set. |
NOT_EXECUTED | Java is unable to execute. |
MSC_ERR_LICENSE | License is invalid. |
MSC_ERR_MEMALLOC | Memory allocation issue. |
MSC_ERR_PROFILENOTAVAILABLE | BioCapture profile is not available. |
MSC_ERR_SUBPROFILENOTAVAILABLE | BioCapture sub-profile is not available. |
MSC_ERR_TYPE_MISMATCH | BioCapture type mismatch. |
UNKNOWN | Unknown error |
Creating a BioMatcher Handler
This allows you to retrieve a handler to perform all the matching, identifying, and template coding operations.
-
Review the use cases named Create BioMatcherHandler.
-
Review the features provided by this handler here.
Java1IBioMatcherSettings bioMatcherSettings = new BioMatcherSettings();2 bioMatcherSettings.setLogLevel(LogLevel.DISABLE);3 bioMatcherSettings.setDumpFileEnable(false);4 bioMatcherSettings.setDumpFileFolder(null);5 //To configure finger print template format6 bioMatcherSettings.setFingerprintTemplate(MorphoFingerTemplateFormat.PKCOMPV2);7 BioSdk.createBioMatcherHandler(this, bioMatcherSettings, new BioMatcherAsyncCallbacks<IBioMatcherHandler>() {8 @Override9 public void onPreExecute() {10 // Optional hook on the builtin Android AsyncTask call-back `onPreExecute`11 }1213 @Override14 public void onSuccess(IBioMatcherHandler result) {15 // Indicates that initialization succeeded. The returned handler can be used to perform the matching and identify operations.16 }1718 @Override19 public void onError(Exception e) {20 // An error has occurred.21 }22 });
Parameter | Description |
---|---|
context Context | The Android context. |
settings IBioMatcherSettings | The settings to configure the matcher. |
callbacks BioMatcherAsyncCallbacks | Callbacks 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:
Java1captureHandler.setFaceTrackingListener(new FaceCaptureTrackingListener() {2 @Override3 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:
Java1captureHandler.setFingerTrackingListener(new FingerCaptureTrackingListener() {2 @Override3 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:
Java1handler.startPreview(new PreviewStatusListener() {2 @Override3 public void onStarted() {4 try {5 captureHandler.startCapture();6 } catch (MSCException e) {7 // handle exception8 }9 }1011 @Override12 public void onError(PreviewError error) {13 // Preview initialization failed and can not be started14 }15 });
Kotlin1coroutineScope.launch {2 documentHandler.startPreview()3 documentHandler.startCapture()4}
Stop preview
This stops the camera preview as shown in the snippet:
Java1handler.stopPreview()
Start capture
This starts the biometric capture as shown in the snippet.
Java1handler.startCapture();
Stop capture
This stops the biometric capture as shown in the snippet:
Java1handler.stopCapture();
Switch camera
This switches between different cameras as shown in the snippet:
Java1handler.switchCamera(Camera.FRONT); // Use front camera2handler.switchCamera(Camera.REAR); // Use rear camera
Destroy
This releases all the handler resources as shown in the snippet:
Java1handler.destroy();
Overlay
This sets the overlay option.
Java1handler.setOverlay(Overlay.OFF); // Disable preview's overlay2handler.setOverlay(Overlay.ON); // Enable preview's overlay
Torch
This sets the torch option as shown in the snippet:
Java1handler.setTorch(Torch.OFF); // Disable the torch2handler.setTorch(Torch.ON); // Enable the torch
CaptureOptions
This retrieves the capture options used in this handler as shown in the snippet:
Java1ICaptureOptions options = handler.getCaptureOptions();
Force capture
This forces a capture as shown in the snippet:
Java1handler.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:
Java1handler.requestPartialDumpVideo();
Capture handler status
Note: Check CaptureHandlerStatus.
This retrieves the status of the capture handler as shown in the snippet:
Java1CaptureHandlerStatus 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:
Java1// Get activity from application2Activity activity = ...3// Populate a CaptureOptions object4IFaceCaptureOptions 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 @Override12 public void onPreExecute() {13 // Optional hook on the builtin Android AsyncTask call-back `onPreExecute`14 }1516 @Override17 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 }2223 @Override24 public void onError(BioCaptureHandlerError e) {25 // An error has occurred during the initialization26 }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:
Java1faceCaptureHandler.setFaceCaptureResultListener(new FaceCaptureResultListener() {2 @Override3 public void onCaptureSuccess(@NotNull FaceImage image) {4 }56 @Override7 public void onCaptureFailure(@NotNull CaptureError captureError,8 @NotNull IBiometricInfo biometricInfo,9 @NotNull Bundle extraInfo) {10 }11 });
onCaptureSuccess | Called when captured is finished successfully |
---|---|
image FaceImage | Capture face image |
FaceImage | |
---|---|
getLivenessResult FaceLivenessResult | Resolution of capture liveness: LIVE ,FAKE , or NO_DECISION |
getMetadata Metadata | Low 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 CaptureError | Reason of capture failure |
biometricInfo IBiometricInfo | Biometric information about location and classification |
extraInfo Bundle | Holds 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
Java1captureHandler.setVideoRecordingReadyForGenerationListener(new VideoRecordingReadyForGenerationListener() {2 @Override3 public void videoRecordingReadyForGeneration(VideoRecording videoRecording) {4 //Video recording object to generate video5 }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:
Java1FaceCaptureOptions 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"
Java1FaceCaptureOptions 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:
Java1((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:
Java1handler.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:
Java1[...]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:
Java1((FaceCaptureHandler)handler).setMaxCapturesBeforeDelay(5);
There is also a getter for this value as shown in the snippet:
Java1((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:
Java1List<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:
Java1((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:
Java1handler.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
Java1captureHandler.setVideoRecordingReadyForGenerationListener(new VideoRecordingReadyForGenerationListener() {2 @Override3 public void videoRecordingReadyForGeneration(VideoRecording videoRecording) {4 //Video recording object to generate video5 }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:
Java1FaceCaptureOptions 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"
Java1FaceCaptureOptions 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:
Java1[...]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:
Java1// Get activity from application2 Activity activity = ...3 // Populate a CaptureOptions object4 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 reference12 IBiometricReference biometricReference = ...13 captureOptions.setBiometricReference(biometricReference);14 //////////////////////////////////15 BioSdk.createFingerCaptureHandler(activity, captureOptions, new MscAsyncCallbacks<IFingerCaptureHandler>() {16 @Override17 public void onPreExecute() {18 // Optional hook on the builtin Android AsyncTask call-back `onPreExecute`19 }2021 @Override22 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 initialization28 }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.
Java1fingerCaptureHandler.setFingerCaptureResultListener(new FingerCaptureResultListener() {2 @Override3 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 FingerCaptureResult | Holds information about the capture, like liveness |
FingerCaptureResult | |
---|---|
getLivenessResult FingerLivenessResult | Resolution of capture liveness: LIVE ,FAKE ,NO_DECISION |
getScore double | Deprecated Finger capture liveness score |
onCaptureFailure | Called when capture fails |
---|---|
captureError CaptureError | Reason of capture failure |
biometricInfo IBiometricInfo | Biometric information about location and classification |
extraInfo Bundle | Holds 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.
Java1fingerCaptureHandler.setAuthenthicationListener(new BioCaptureAuthenticationListener() {2 @Override3 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 CaptureDistanceRange | Contains 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 String | The reason of the distance range unavailibility, e.g. "The device is not calibrated for this feature" |
CaptureDistanceRange | |
---|---|
rangeMin float | Minimum value that may be returned in _FingerCaptureCurrentDistanceListener. Should be equal to 0.0 |
optimalMin float | Lower boundary of optimal distance between the phone and the fingers |
optimalMax float | Upper boundary of optimal distance between the phone and the fingers |
rangeMax float | Maximum 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 @Override3 public void onCurrentCaptureDistance(@NonNull CurrentCaptureDistance currentCaptureDistance) {4 //handle currentCaptureDistance5 }6 });
onCurrentCaptureDistance | Called when the distance between the fingers and the phone lens changes |
---|---|
currentCaptureDistance CurrentCaptureDistance | Contains the distance between the phone lens and the fingers |
CurrentCaptureDistance | |
---|---|
value float | Value 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 @Override3 public void onCurrentCaptureDistance(@NonNull captureInfo: FingerCaptureInfo) {4 //handle captureInfo5 }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:
Java1//Authentication options2IAuthenticationOptions authenticationOptions = new AuthenticationOptions();3authenticationOptions.setThreshold(3500);45//Biometric candidate6IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FACE);7//We add all the templates for this candidate8biometricCandidate.addTemplates(candidates);910//Biometric references11IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FACE);12//We add all the templates for this user13biometricReference.addTemplates(references);1415matcherHandler.authenticate(authenticationOptions, biometricCandidate, biometricReference, new BioMatcherAsyncCallbacks<IAuthenticationResult>() {16 @Override17 public void onPreExecute() {18 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`19 }2021 @Override22 public void onSuccess(IAuthenticationResult result) {23 //The result of the authentication24 long resultScore = result.getScore();25 //authentication status (FAILURE, SUCCESS...)26 AuthenticationStatus authenticationStatus = authenticationResult.getStatus();27 }2829 @Override30 public void onError(Exception e) {31 // An error has occurred32 }33});
Function
Java1void authenticate(IAuthenticationOptions authenticationOptions, IBiometricCandidate biometricCandidate, IBiometricReference biometricReference, BioMatcherAsyncCallbacks<IAuthenticationResult> callbacks);
Parameter | Description |
---|---|
authenticationOptions IAuthenticationOptions | The options used to perform the authentication. |
biometricCandidate IBiometricCandidate | It contains the list of templates that you want to match. |
biometricReference IBiometricReference | It contains the list of templates that you want to use as reference, each of one has the userUUID to which they belong. |
callbacks BioMatcherAsyncCallbacks | Callbacks 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:
Java1//Authentication options2IAuthenticationOptions authenticationOptions = new AuthenticationOptions();3authenticationOptions.setThreshold(3500);45//Biometric candidate6IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FACE);7//We add all the templates for this candidate8biometricCandidate.addTemplates(candidates);910//Biometric references11IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FACE);12//We add all the templates for this user13biometricReference.addTemplates(references);1415IAuthenticationResult result = matcherHandler.authenticate(authenticationOptions, biometricCandidate, biometricReference);16/The result of the authentication17long resultScore = result.getScore();18//authentication status (FAILURE, SUCCESS...)19AuthenticationStatus authenticationStatus = authenticationResult.getStatus();
Function
An example snippet is shown.
Java1IAuthenticationResult authenticate(IAuthenticationOptions authenticationOptions, IBiometricCandidate biometricCandidate, IBiometricReference biometricReference);
Parameter | Description |
---|---|
authenticationOptions IAuthenticationOptions | The options used to perform the authentication. |
biometricCandidate IBiometricCandidate | Contains the list of templates that you want to match. |
biometricReference IBiometricReference | Contains 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:
Java1//Identification options2IIdentificationOptions identificationOptions = new IdentificationOptions();34//Biometric candidate5IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FACE);6//We add all the templates for this candidate7biometricCandidate.addTemplates(candidates);89//We create the list of references10ArrayList<IBiometricReference> biometricReferences = new ArrayList<IBiometricReference>();11//Biometric reference for one user12IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FACE);13//We add all the templates for this user14biometricReference.addTemplates(references);1516//We add the user to the list17biometricReferences.add(biometricReference);1819matcherHandler.identify(identificationOptions, biometricCandidate, biometricReferences, new BioMatcherAsyncCallbacks<IIdentificationResult>() {20 @Override21 public void onPreExecute() {22 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`23 }2425 @Override26 public void onSuccess(IIdentificationResult result) {27 //The identification result28 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 }3435 }3637 @Override38 public void onError(Exception e) {39 // An error has occurred40 }41});
Function
An example snippet is shown.
Java1void identify(IIdentificationOptions identificationOptions, IBiometricCandidate biometricCandidate, List<IBiometricReference> biometricReferences, BioMatcherAsyncCallbacks<IIdentificationResult> callbacks);
Parameter | Description |
---|---|
identificationOptions IIdentificationOptions | The options used to perform the identification |
biometricCandidate IBiometricCandidate | Contains 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 BioMatcherAsyncCallbacks | Callbacks 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.
Java1//Identification options2IIdentificationOptions identificationOptions = new IdentificationOptions();34//Biometric candidate5IBiometricCandidate biometricCandidate = new BiometricCandidate(BiometricModality.FACE);6//We add all the templates for this candidate7biometricCandidate.addTemplates(candidates);89//We create the list of references10ArrayList<IBiometricReference> biometricReferences = new ArrayList<IBiometricReference>();11//Biometric reference for one user12IBiometricReference biometricReference = new BiometricReference(user.getUuid(), BiometricModality.FACE);13//We add all the templates for this user14biometricReference.addTemplates(references);1516//We add the user to the list17biometricReferences.add(biometricReference);1819IIdentificationResult result = matcherHandler.identify(identificationOptions, biometricCandidate, biometricReferences)20//The identification result21List<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.
Java1IIdentificationResult identify(IIdentificationOptions identificationOptions, IBiometricCandidate biometricCandidate, List<IBiometricReference> biometricReferences);
Parameter | Description |
---|---|
identificationOptions IIdentificationOptions | The options used to perform the identification. |
biometricCandidate IBiometricCandidate | Contains 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.
Java1//Create a populate options2 IDetectBiometricOptions detectBiometricsOptions = new DetectBiometricsOptions();3 detectBiometricsOptions.setBiometricLocation(BiometricLocation.FACE_FRONTAL);4 detectBiometricsOptions.setBiometricModality(BiometricModality.FACE);56 bioMatcherHandler.detectBiometric(detectBiometricsOptions, image, new BioMatcherAsyncCallbacks<List<IMorphoTemplate>>() {7 @Override8 public void onPreExecute() {9 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`10 }1112 @Override13 public void onSuccess(List<IMorphoTemplate> result) {14 //A List of templates extracted from the image15 }1617 @Override18 public void onError(Exception e) {19 // An error has occurred20 }21 });
Function
An example snippet is shown.
Java1public void detectBiometric(final IDetectBiometricOptions detectBiometricsOptions, final IImage image, BioMatcherAsyncCallbacks<List<IMorphoTemplate>> callbacks)
Parameter | Description |
---|---|
detectBiometricsOptions IDetectBiometricOptions | The options used during the detection process. |
image IImage | The image. |
callbacks BioMatcherAsyncCallbacks | Callbacks 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.
Java1/Create a populate options2IDetectBiometricOptions detectBiometricsOptions = new DetectBiometricsOptions();3detectBiometricsOptions.setBiometricLocation(BiometricLocation.FACE_FRONTAL);4detectBiometricsOptions.setBiometricModality(BiometricModality.FACE);56List<IMorphoTemplate> templates = bioMatcherHandler.detectBiometric(detectBiometricsOptions, image)7/A List of templates extracted from the image
Function
An example snippet is shown.
Java1public List<IMorphoTemplate> detectBiometric(final IDetectBiometricOptions detectBiometricsOptions, final IImage image)
Parameter | Description |
---|---|
detectBiometricsOptions IDetectBiometricOptions | The options to use during the detection process. |
image IImage | The image. |
Errors
You will receive an exception reporting the error.
Destroy
This releases all the handler resources as shown in the snippet:
Java1handler.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.
Java1ImageUtils.morphoImageY800ToARGB8888(getApplicationContext(), morphoImage, new ImageUtilsAsyncCallbacks<Bitmap>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(Bitmap bitmap) {9 //The image in ARGB888810 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred15 }16 });
Function
Java1public static void morphoImageY800ToARGB8888(final Context context, final MorphoImage image, ImageUtilsAsyncCallbacks<Bitmap> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
image MorphoImage | The image. |
callbacks ImageUtilsAsyncCallbacks | Callbacks 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
.
Java1ImageUtils.bitmapToMorphoImageY800(getApplicationContext(), bitmap, new ImageUtilsAsyncCallbacks<MorphoImage>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(MorphoImage image) {9 //Remember to configure the Morpho Image10 image.setBiometricModality(BiometricModality.FACE);11 image.setBiometricLocation(BiometricLocation.FACE_FRONTAL);12 }1314 @Override15 public void onError(Exception e) {16 // An error has occurred17 }18 });
Function
Java1public static void bitmapToMorphoImageY800(final Context context, final Bitmap image, ImageUtilsAsyncCallbacks<MorphoImage> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
image Bitmap | The image. |
callbacks ImageUtilsAsyncCallbacks | Callbacks 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.
Java1//Maximum size 500 KB2 Bitmap compressed = ImageUtils.compressBitmap(bitmap, 500);
Function
Java1public static Bitmap compressBitmap(Bitmap srcBitmap, int maxSize) throws IllegalArgumentException;
Parameter | Description |
---|---|
srcBitmap Bitmap | The image. |
maxSize int | The 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.
Java1//Maximum size 500 px2 Bitmap resized = ImageUtils.resizeBitmap(bitmap, 500);
Function
Java1public static Bitmap resizeBitmap(Bitmap srcBitmap, int maxSideLengthInPixels) throws IllegalArgumentException;
Parameter | Description |
---|---|
srcBitmap Bitmap | The image. |
maxSideLengthInPixels int | Maximum 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.
Java1//Maximum pixel length is 3000 pixels2 //Maximum size 500 KB3 byte[] jpegImage = ImageUtils.resizeAndCompressToByteArray(image, 3000, 500); //returned image in jpeg format as byte[]
Function
Java1public static byte[] resizeAndCompressToByteArray(IImage image, int maxSideLengthInPixels, int maxSizeInKB) throws Exception;
Parameter | Description |
---|---|
image IImage | The image. |
maxSideLengthInPixels int | Maximum side length desired in pixels. |
maxSizeInKB int | The 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.
Java1IImage iImage = ImageUtils.doCrop(image, documentRegion.getPoint1().x, documentRegion.getPoint1().y, documentRegion.getPoint3().x, documentRegion.getPoint3().y);
Function
Java1public static IImage doCrop(IImage srcImage, double topLeftX, double topLeftY, double bottomRightX, double bottomRightY) throws Exception;
Parameter | Description |
---|---|
srcImage IImage | The image. |
topLeftX double | The top left position X coordinate. |
topLeftY double | The top left position Y coordinate. |
bottomRightX double | The bottom right position X coordinate. |
bottomRightY double | The 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.
Java1IImage iImage = ImageUtils.doRotation(image, 90);
Function
Java1public static IImage doRotation(IImage srcImage, float degrees) throws Exception;
Parameter | Description |
---|---|
srcImage IImage | The image. |
degrees float | The 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.
Java1IImage iImage = ImageUtils.doFlip(image, FlipType.LI_F_BOTH);
Function
Java1public static IImage doFlip(IImage srcImage, FlipType flipType) throws Exception;
Parameter | Description |
---|---|
srcImage IImage | The image. |
flipType FlipType | The 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.
Java1IImage iImage = ImageUtils.toJPG2000(image, false);
Function
Java1public static IImage toJPG2000(IImage srcImage, boolean isLatent) throws Exception;
Parameter | Description |
---|---|
srcImage IImage | The image in raw format. |
isLatent boolean | False 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.
Java1IImage iImage = ImageUtils.toJPG2000(image, 102400);
Function
Java1public static IImage toJPG2000(IImage srcImage, int outputMaximumSizeInBytes) throws Exception;
Parameter | Description |
---|---|
srcImage IImage | The image in raw format. |
outputMaximumSizeInBytes int | Maximum 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.
Java1IImage iImage = ImageUtils.toWSQ(srcImage, 15, (byte) 0, (byte) 0xff);
Function
Java1public static IImage toWSQ(IImage srcImage, float compressionRatio, byte scannerBlack, byte scannerWhite) throws java.lang.Exception;
Parameter | Description |
---|---|
srcImage IImage | The image in raw format. |
compressionRatio float | Maximum size (in bytes) of the output compressed buffer. |
scannerBlack byte | BLACK calibration value (if unknown, use 0 ) |
scannerWhite byte | WHITE 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.
Java1List<DocumentImage> iImages = ImageUtils.extractImages(srcImage);
Function
Java1public static List<DocumentImage> extractImages(DocumentImage srcImage) throws java.lang.Exception;
Parameter | Description |
---|---|
srcImage IImage | The 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.
Java1Bitmap result = ImageUtils.resizeBitmap(srcImage, UseCase.BIOMETRIC, DocumentType.SELFIE, false);
Function
Java1public static Bitmap resizeBitmap(Bitmap srcBitmap, UseCase useCase, DocumentType documentType, boolean isCropped) throws IllegalArgumentException;
Parameter | Description |
---|---|
srcImage Bitmap | The source image to resize. |
useCase UseCase | The use case. |
documentType DocumentType | The type of document. |
isCropped boolean | True 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 String | The version of the SDK |
IBioMatcherSettings
This object is used to configure the behavior of BioMatcher
.
Attribute | Description |
---|---|
debugDataSettings DebugDataSettings | Sets options used for preparing debug data dump |
fingerTemplateFormat MorphoFingerTemplateFormat | Finger template format, only used for fingerprints—default format is PKLITE |
ICaptureOptions
This object is used to configure the behavior of Capture
.
Attribute | Description |
---|---|
camera Camera | The app camera option to configure BioCapture . |
torch Torch | Sets the torch value. |
overlay Overlay | Sets the overlay value. |
captureTimeout Long | Capture timeout in seconds (default value 120 ). |
logLevel LogLevel | Sets the log level. |
DebugDataSettings Debug Data | Sets 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 int | For CR2D sets dots seed |
liveness FaceLiveness | Set challenge for face |
securityLevel FaceLivenessSecurityLevel | Set liveness security |
videoRecordingOptions VideoRecordingOptions | When 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 IBiometricReference | The biometric reference to use during the finger authentication. Only compatible with capture mode AUTHENTICATION . Check IBiometricReference. |
threshold long | Set threshold for finger capture with success |
crossMatchingVerificationThreshold long | Deprecated Used for verification mechanism to set threshold |
liveness FingerLiveness | Set liveness security |
bioCaptureMode BioCaptureMode | Set capture mode for finger |
numberOfFingers int | Set how many fingers need be to captured. Only compatible with FINGERS . Obsolete |
amputeeFingers AmputeeFingers | Set which fingers Person does not have. Only compatible with FINGERS . |
hand Hand | Set which hand will be scanned |
UHDResolutionEnabled boolean | Enables 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 BiometricModality | The 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 UUID | User uuid |
IBiometricInfo
This is a common interface that all the different Biometrics implement.
Parameter | Description |
---|---|
biometricLocation BiometricLocation | The BiometricLocation enum option. |
biometricModality BiometricModality | The 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 int | The stride of the biometric |
width long | The width of the image |
height long | The height of the image |
colorSpace ColorSpace | The colorspace of the image |
resolution float | The resolution of the image. |
imageQuality int | Image quality if available, otherwise -1 . Currently only available for fingerprint images. |
label String | Label 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) EncryptedData | The 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 Rect | The position of the biometric. |
previewRect Rect | The original preview size to which the coordinates are referred. |
orientation Int | Orientation of finger in degrees |
quality FingerQuality | Quality of finger |
FingerQuality enum
This enum retrieves information about quality of the face saved in template.
Attribute | Description |
---|---|
UNAVAILABLE | The quality is unavailable because the acquisition process is still ongoing. |
LOW | A low-quality fingerprint is a fingerprint image that lacks clarity and detail. |
MEDIUM | A medium-quality fingerprint is a fingerprint image that captures a fair amount of detail. |
HIGH | A 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 Rect | The position of the biometric. |
previewRect Rect | The 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 float | The width length of the oval. |
height float | The height length of the oval. |
centerX float | The position x of oval center. |
centerY float | The 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 UUID | The template uuid in the database (Can be null ). |
uuidUser UUID | The 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 MorphoFaceTemplateFormat | The 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 IFingerPosition | The finger position. |
templateFormat MorphoFingerTemplateFormat | The template format–check MorphoFingerTemplateFormat |
AmputeeFingers
This is information for capture which fingers the user is missing.
Description | |
---|---|
addMissingFinger() Finger | Add 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:
Java1public 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:
Java1void 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 boolean | Enable 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.
Java1videoRecording.generateVideo(new VideoProgressListener() {23 @Overide4 void onFinish(String path) {5 //When creating video comlete with success return path to video6 }78 @Overide9 void progress(int progress) {10 //Showing progress of generating video from 0 to 10011 }1213 @Overide14 void onError(VideoError error) {15 //It's call when generating video failed or another video is current generating16 }17});
If you do not want to generate video from a previous capture, use:
Java1videoRecording.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.
Java1void 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.
Java1void 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
).
Java1void 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
Java1void 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:
Java1void onCaptureFailure(CaptureError captureError, IBiometricInfo biometricInfo, Bundle extraInfo);
Arguments
Parameter | Description |
---|---|
captureError CaptureError | The capture error to show why it fails. |
biometricInfo IBiometricInfo | The Biometric information. |
extraInfo Bundle | Additional 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.
Java1void onCaptureInfo(FaceCaptureInfo captureInfo);
Arguments
Parameter | Description |
---|---|
faceCaptureInfo FaceCaptureInfo | The feedback. |
IDetectBiometricOptions
This interface represents the verification options. This interface extends IBiometricInfo.
Parameter | Description |
---|---|
isTemplateCompressionEnabled boolean | Enables 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 BiometricModality | The 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 long | The authentication threshold to be considered valid. |
IAuthenticationResult
This is the interface that represents an authentication result.
Parameter | Description |
---|---|
score long | The authentication score (between 0 - 50000). |
authenticationStatus AuthenticationStatus | The 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 UUID | The candidate uuid . |
score long | The identification score result. |
Enums
FaceLiveness enum
This enum describes liveness verification mode.
Attribute | Description |
---|---|
NO_LIVENESS | No liveness detection is performed during capture. |
ACTIVE | Triggers a more complex challenge to detect liveness. |
PASSIVE | Liveness is detected without a user challenge—the user is unaware that liveness detection is being employed. |
PASSIVE_VIDEO | Face 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_LIVENESS | No finger liveness detection is performed during capture |
VERY_LOW | Easiest finger liveness mode to pass |
LOW | More restrictive finger liveness verification |
MEDIUM | Recommended liveness mode for finger liveness capture |
Hand enum
This enum describes the captured hand for finger liveness capture.
Attribute | Description |
---|---|
RIGHT | Hand right |
LEFT | Hand Left |
Finger enum
Attribute | Description |
---|---|
INDEX | Index finger |
MIDDLE | Middle finger |
RING | Ring finger |
LITTLE | Little 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 |
---|---|
UNKNOWN | Unable to define or liveness is turned off |
LIVE | Liveness success - a living person is detected |
FAKE | Liveness check failure - not a living person |
NO_DECISION | WebBioServer is needed to make a decision |
FingerLivenessResult enum
This enum represents the result of a finger liveness check.
Attribute | Description |
---|---|
LIVE | Liveness success - real fingers are detected |
FAKE | Liveness check failure - not real fingers |
NO_DECISION | WebBioServer is needed to make a decision |
ColorSpace enum
Attribute | Description |
---|---|
Y8 | Grayscale 8bpp image. |
Y16LE | Grayscale 16bpp image (Little Endian). |
BGR24 | Color 24bpp BGR image (BMP like memory layout). |
RGB24 | Color 24bpp RGB image (reversed memory layout compared to RT_COLORSPACE_BGR24). |
FaceCaptureInfo enum
Attribute | Description |
---|---|
INFO_GET_OUT_FIELD | User must move out of the camera field |
INFO_COME_BACK_FIELD | User must move back into the camera field |
INFO_TURN_LEFT | User must turn head left |
INFO_TURN_RIGHT | User must turn head right |
INFO_CENTER_TURN_LEFT | User must face center but turn head left |
INFO_CENTER_TURN_RIGHT | User must face center but turn head right |
INFO_CENTER_ROTATE_DOWN | User must face center but rotate head down |
INFO_CENTER_ROTATE_UP | User must face center but rotate head up |
INFO_CENTER_TILT_LEFT | User must face center but tilt head left |
INFO_CENTER_TILT_RIGHT | User must face center but tilt head right |
INFO_CENTER_MOVE_FORWARDS | User must move forwards |
INFO_CENTER_MOVE_BACKWARDS | User must move backwards |
INFO_CENTER_LOOK_FRONT_OF_CAMERA | User must look in front of the camera |
INFO_CENTER_LOOK_CAMERA_WITH_LESS_MOVEMENT | User must look at the camera with less movement |
INFO_TURN_LEFTRIGHT | User must turn left, then right or right, then left |
INFO_TURN_DOWN | User must turn head down |
INFO_TOO_FAST | User is moving his/her head too fast |
INFO_NOT_MOVING | Face movement not detected |
DEVICE_MOVEMENT_ROTATION | Smartphone movement detected (the user is moving his/her smartphone and not his/her face) |
FingerCaptureInfo enum
Attribute | Description |
---|---|
OPTIMAL | The user's fingers are in optimal distance from the phone lens |
TOO_CLOSE | User should move the fingers further |
TOO_FAR | User should move the fingers closer |
BiometricLocation enum
Attribute | Description |
---|---|
FACE_FRONTAL | Face |
FINGER_RIGHT_INDEX | Right index finger |
FINGER_RIGHT_MIDDLE | Right middle finger |
FINGER_RIGHT_RING | Right ring finger |
FINGER_RIGHT_LITTLE | Right little finger |
FINGER_RIGHT_THUMB | Right thumb |
FINGER_RIGHT_FOUR | Right four fingers |
FINGER_LEFT_INDEX | Left index finger |
FINGER_LEFT_MIDDLE | Left middle finger |
FINGER_LEFT_RING | Left ring finger |
FINGER_LEFT_LITTLE | Left little finger |
FINGER_LEFT_THUMB | Left thumb |
FINGER_LEFT_FOUR | Left four fingers |
FINGER_UNKNOWN | Unknown finger |
HAND_LEFT | Left hand |
HAND_RIGHT | Right hand |
HAND_UNKNOWN | Unknown hand |
UNKNOWN | Unknown |
BiometricModality enum
Attribute | Description |
---|---|
UNKNOWN | Unknown |
FACE | Face |
FRICTION_RIDGE | Friction ridge (fingers) |
Cr2dMode enum
Attribute | Description |
---|---|
RANDOM | Targets fully random |
PATH | Targets defined with path |
FIXED | Fixed position for target |
Camera enum
This enum is used to configure the behavior of BioCapture
.
Attribute | Description |
---|---|
FRONT | Front camera |
REAR | Rear camera |
CameraFlash enum
This enum is used to configure the behavior of BioCapture
.
Attribute | Description |
---|---|
OFF | Camera flash off |
ON | Camera flash on |
Overlay enum
This enum is used to configure the behavior of BioCapture
.
Attribute | Description |
---|---|
OFF | Overlay off |
ON | Overlay on |
BioCaptureMode enum
This enum is used to configure the behavior of FingerCapture
.
Attribute | Description |
---|---|
FINGERS | Fingerprint one to four finger |
THUMB | Fingerprint one finger |
AUTHENTICATION | Fingerprint 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 |
---|---|
UNKNOWN | Unknown error |
LOW_RESOLUTION | Resolution too low |
NOT_ENOUGH_MOVEMENT | Not enough movement |
TOO_FAST | Too fast |
HINT_UNKNOWN | Hint value is unknown |
CAPTURE_TIMEOUT | Capture timeout |
CAPTURE_DELAYED | Capture delayed due to liveness failures |
BAD_CAPTURE | Capture went wrong |
BAD_CAPTURE_FINGERS | Capture of the fingers went wrong |
BAD_CAPTURE_FACE | Capture of the face went wrong |
BAD_CAPTURE_HAND | Capture of the hand went wrong |
LIVENESS_CHECK | Liveness check failed |
AuthenticationStatus enum
This enum contains the authentication status.
Attribute | Description |
---|---|
SUCCESS | Authentication success (above the threshold used for the authentication process) |
FAILURE | Authentication failure (below the threshold used for the authentication process) |
LogLevel enum
This enum controls the logging level.
Attribute | Description |
---|---|
ERROR | Error log level or above |
DEBUG | Debug log level or above |
WARNING | Warning log level or above |
INFO | Info log level or above |
DISABLE | Disables logging |
MorphoFaceTemplateFormat enum
This enum retrieves information about the face template format.
Attribute | Description |
---|---|
MIMA | MIMA format |
MOC | MOC format |
MorphoFingerTemplateFormat enum
FaceTemplateQuality enum
This enum retrieves information about quality of the face saved in template.
Attribute | Description |
---|---|
LOW | The quality of face is low (not recommended to perform matching). |
MEDIUM | The quality of face is medium - good enough to perform matching. |
HIGH | The quality of face is high. |
This enum retrieves information about the finger template format.
Attribute | Description |
---|---|
AAMVA | AAMVA format |
ANSI_378 | ANSI_378 format |
ANSI_378_2009 | ANSI_378_2009 format |
BIOSCRYPT | BIOSCRYPT format |
CFV | CFV format |
DIN_V66400_CS | DIN_V66400_CS format |
GA_774 | GA_774 format |
ILO_FMR | ILO_FMR format |
MINEX_A | MINEX_A format |
ISO_19794_2 | ISO_19794_2 format |
ISO_19794_2_2011 | ISO_19794_2_2011 format |
ISO_19794_2_NS | ISO_19794_2_NS format |
ISO_19794_2_CS | ISO_19794_2_CS format |
PKMAT | PKMAT format |
PKCOMPV2 | PKCOMPV2 format |
PKLITE | PKLITE format |
PKCOMPV1 | PKCOMPV1 format |
CaptureHandlerStatus enum
This enum retrieves the status of the capture handler.
Attribute | Description |
---|---|
STOP | The capture handler is stopped |
PREVIEW | The capture handler is in preview mode |
CAPTURE | The 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
Java1val IMAGE_SIZE = 4002val JPEG_COMPRESSION_LEVEL = 9034private 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.
XML1<androidx.constraintlayout.widget.ConstraintLayout2 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">78 <com.idemia.capture.face.api.FaceCaptureView9 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" />1617</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:
Kotlin1@Override2 protected void onCreate(Bundle savedInstanceState) {3 super.onCreate(savedInstanceState);4 setContentView(R.layout.your_activity_layout);56 val captureView = findViewById(R.id.captureView);7}
or with more popular way - through binding:
Kotlin1lateinit var binding: YourActivityCaptureBinding23override fun onCreate(savedInstanceState: Bundle?) {4 super.onCreate(savedInstanceState)5 binding = YourActivityCaptureBinding.inflate(layoutInflater)6 setContentView(binding.root)78 val captureView = binding.captureView9}
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.
Kotlin1val remoteUseCase =2 RemoteUseCase(3 sessionId,4 RemoteCaptureListeners(5 faceTrackingInfo = faceTrackingInfoLoggingListener,6 captureFeedback = feedbackListener,7 captureLivenessListener = captureLivenessLoggingListener,8 stepInfoListener = stepInfoListener,9 passiveVideoListener = passiveVideoLoggingListener,10 captureResultListener = captureResultListener11 ),12 environmentInfo13 )
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:
Kotlin1fun setUp(useCase: UseCase, lifecycle: Lifecycle?, uiSettings: UISettings?)
Please find below explanation to each function argument:
Parameter | Description |
---|---|
useCase UseCase | This is use case instance providing type of capture and allowing integrator to get data from it |
lifecycle Lifecycle | This 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 UISettings | Settings 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:
Kotlin1[code in Activity]23fun 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:
Kotlin1val joinThePointsCaptureSettings = joinThePointsChallengeSettings {2 useInterpolation = true3 scene {4 overlay {5 showOverlay = true6 imageRes = R.drawable.ic_face_overlay7 marginVertical = R.dimen.default_face_overlay_vertical_padding8 marginHorizontal = R.dimen.default_face_overlay_vertical_padding9 text {10 text = R.string.default_overlay_text11 textSize = R.dimen.default_overlay_text_size12 textColor = Color.parseColor(Colors.text_black)13 }14 }15 capturedLineOpacity = 0.5f16 pointer {17 type = PointerType.PULSING18 collisionWithTargetAction = PointerCollisionAction.NONE19 }20 target {21 pulseAnimation {22 waves = 323 }24 showMarkOnCurrentTarget = true25 }26 verticalTilt {27 enabled = false28 }29 tapping {30 enabled = false31 }32 result {33 failureImageResId = R.drawable.ic_challenge_failed34 successImageResId = R.drawable.ic_challenge_success35 }36 }37}3839val passiveSettings = passiveCaptureSettings {40 scene {41 background {42 colorEnd = Color.parseColor("#189482")43 colorStart = Color.parseColor("#38ddb8")44 }45 previewScale {46 scaleX = 1.0f47 scaleY = 1.0f48 }49 feedback {50 colorText = Color.parseColor(Colors.white)51 }52 overlay {53 showOverlay = true54 }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 = true62 }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 = true69 }70 countdown {71 countdownSeconds = 372 }73 delay {74 isEnabled = true75 message = "Authentication locked.\nPlease wait for:\n%1$s"76 }77 }78}7980val passiveVideoSettings = passiveVideoCaptureSettings {81 scene {82 preparationScene {83 backgroundColor = Color.WHITE84 }85 faceOverlay {86 progressBar {87 progressFill = Color.GREEN88 }89 }90 background {91 colorEnd = Color.parseColor("#189482")92 colorStart = Color.parseColor("#38ddb8")93 }94 previewScale {95 scaleX = 1.0f96 scaleY = 1.0f97 }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 = true108 }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 = true115 }116 delay {117 isEnabled = true118 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
Kotlin1RemoteUseCase(sessionId: String, listeners: RemoteCaptureListeners, environmentInfo: EnvironmentInfo)
Parameter | Description |
---|---|
sessionId String | Session 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 RemoteCaptureListeners | Group 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 EnvironmentInfo | Informations about Proofing Platform environment and authentication method. |
RemoteCaptureListeners - detailed description of each listeners can be found in listeners section.
Parameter | Description |
---|---|
livenessActiveListener LivenessActiveListener | Provides information about liveness ACTIVE mode. Usefull when UISettings are not provided to FaceCaptureView. |
faceTrackingInfo FaceTrackingInfoListener | Provides coordinates with face. |
captureFeedback CaptureFeedbackListener | Provides feedback that should be presented to end user to improve capture process. Handled when UISettings are used. |
captureLivenessListener CaptureLivenessListener | Provides information about liveness mode for current capture. |
stepInfoListener StepInfoListener | Provides information about state of capture. |
passiveVideoListener PassiveVideoListener | Provides information about liveness PASSIVE_VIDEO mode. Usefull when UISettings are not provided to FaceCaptureView. |
captureResultListener RemoteCaptureResultListener | Provides information about result of whole flow. |
livenessProcessingListener LivenessProcessingListener | Provides 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 theEnvironmentInfo
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 String | URL to Proofing services. For example production URL is: https://proofing.app.eu.identity-prod.idemia.io:443/ |
accessToken AccessToken | Dedicated 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 String | URL to Proofing services. For example production URL is: https://proofing.app.eu.identity-prod.idemia.io:443/ |
apiKey String | Dedicated 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 String | Dedicated token used to authenticate on Proofing services. Do not share this and try to avoid storing it on application's repository |
tokenType String | Token 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:
-
Create identity by calling:
POST: /v1/identities
As a result an identity is being returned -
Submit confirmation that the user has consented to perform specific evidence verifications:
POST: /v1/identities/{id}/consents
-
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:
-
Create session by calling:
POST: /bioserver-app/v2/bio-sessions
Call must contain session data in body. -
Retrieve session path from the response:
Kotlin1val bioSessionPath = response.headers()["Location"]
-
Get BioSession:
GET: /bioserver-app{bioSessionPath}
Response to this call contains session id used by SDK. -
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:
Kotlin1val 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 = captureResultListener18 ),19 environmentInfo20)
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.
Kotlin1fun captureLiveness(liveness: Liveness)
Liveness
Value | Description |
---|---|
ACTIVE | Means that current liveness mode is active one. User need to connect points using face. |
PASSIVE | Means that current liveness mode is passive one. No challenges for user. |
PASSIVE_VIDEO | More 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.
Kotlin1fun stepInfo(stepInfo: StepInfo)
StepInfo
Value | Description |
---|---|
PREPARING_LIVENESS | Liveness challenge is being prepared. |
CAPTURE_STARTED | Capture 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.
Kotlin1fun 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".
Kotlin1fun onTargetUpdate(targetInfo: TargetInfo)
TargetInfo contains information about targets to capture.
Parameter | Description |
---|---|
x Int | X coordinate of target. |
y Int | Y coordinate of target. |
show Boolean | Indicates if target should be visible to user. |
radius Int | Radius of target relative to capture frame size. |
number Int | Number of target. |
completness Float | Value ranged from 0.0 to 1.0, where 1.0 tells that target is fully captured. |
current Boolean | Informs if given target is currently active one (to be captured). |
Kotlin1fun 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.
Kotlin1fun onPreparationStarted()
Tells integrator that preparation of capture has been started.
Kotlin1fun onPreparationFinished()
Tells integrator that preparation phase has finished. Now capture will be performed.
Kotlin1fun 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.
Kotlin1fun progressUpdated(progress: Float)
Progress of capture.
RemoteCaptureResultListener
Used only for RemoteUseCase. Provides information about flow result.
Kotlin1fun 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.
Kotlin1fun 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.
Kotlin1fun faceTrackingInfo(trackingInfo: FaceTrackingInfo)
FaceTrackingInfo provides "face rectangle" informations.
LivenessProcessingListener
This listener provides information about current progress of uploading metadata to the server.
Kotlin1fun 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 ErrorType | Type of an error. High level information what goes wrong. Find types description below. |
code Int | Special code dedicated for particular case. Very helpful in L2, L3 troubleshooting. |
message String | Message 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_ISSUE | General issue with connection. See message and error code for more informations. |
AUTHENTICATION | Backend authentication failed. Probably wrong credentials has been used for the given environment. |
INVALID_SESSION | Session ID is not correct. Most probably session expired or has been finished. |
TIMEOUT | Timeout occured during the flow. |
BAD_CAPTURE | Capture failed. Face was not detected or liveness check did not pass. |
UNKNOWN | Unknow type of exception. Also used as default type for few cases. |
CANCELED | Flow has been canceled. Can be triggered by integrator or automatically when Lifecycle has been passed to setUp method. |
VERIFICATION | Device signature verification failed. |
INVALID_LICENSE | License 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_BLOCKED | Capture 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:
- Activating license.
- Adding FingerCaptureView to activity.
- Creating use case.
- 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.
XML1<androidx.constraintlayout.widget.ConstraintLayout2 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">78 <com.idemia.capture.face.api.FingerCaptureView9 android:id="@+id/captureView"10 android:layout_width="match_parent"11 android:layout_height="match_parent"/>1213</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:
Kotlin1private val captureView: FingerCaptureView? = null23@Override4 protected void onCreate(Bundle savedInstanceState) {5 super.onCreate(savedInstanceState);6 setContentView(R.layout.your_activity_layout);78 captureView = findViewById(R.id.captureView);9}
or with more up to date way - through binding:
Kotlin1lateinit var binding: YourActivityCaptureBinding2private val captureView: FingerCaptureView? = null34override fun onCreate(savedInstanceState: Bundle?) {5 super.onCreate(savedInstanceState)6 binding = YourActivityCaptureBinding.inflate(layoutInflater)7 setContentView(binding.root)89 captureView = binding.captureView10}
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.
Kotlin1val latentUseCase =2 LatentUseCase(3 LatentCaptureSettings(TIMEOUT),4 LatentCaptureListeners(5 currentDistanceListener = fingerCaptureDistanceListener,6 feedbackListener = fingerCaptureFeedbackListener,7 trackingListener = fingerCaptureTrackingListener,8 result = latentResultListener,9 torchListener = torchListener10 )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:
Kotlin1fun setUp(useCase: UseCase, lifecycle: Lifecycle?, uiSettings: UISettings?)
Please find below explanation to each function argument:
Parameter | Description |
---|---|
useCase UseCase | This is use case instance providing type of capture and allowing integrator to get data from it |
lifecycle Lifecycle | This 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 UISettings | Settings 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:
Kotlin1[code in Activity]23fun setupView(useCase: UseCase) {4 binding.captureView.setUp(5 useCase,6 lifecycle,7 UISettings(fingerCaptureSettings)8 )9}
Here is an example of UISettings setup.
Kotlin1val fingerCaptureSettings = fingerCaptureSettings {2 scene {3 background {4 colorEnd = Color.parseColor("#189482")5 colorStart = Color.parseColor("#38ddb8")6 }7 rectangle {8 color = Color.BLACK9 strokeWidth = 20f10 cornerRadius {11 rx = 20f12 ry = 20f13 }14 }15 previewScale {16 scaleX = 1.0f17 scaleY = 1.0f18 }19 tapping {20 colorBackground = Color.parseColor("#FAFAFA")21 colorImage = Color.parseColor("#000000")22 colorText = Color.parseColor("#000000")23 textResId = R.string.use_your_head24 textH1ResId = R.string.no_tapping_feedback25 enabled = true26 }27 feedback {28 feedbackStringMapping = mapping29 show = true30 }31 distance {32 showOptimalDistanceIndicator = true33 }34 progressBar {35 labelRes = R.string.scanning36 show = true37 }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
Kotlin1LatentUseCase(val settings: LatentCaptureSettings, val listeners: LatentCaptureListeners)
Parameter | Description |
---|---|
settings LatentCaptureSettings | Latent capture settings. Currently it contains only one field - timeout, which indicates time of capture. |
listeners LatentCaptureListeners | Group 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 FingerCaptureDistanceListener | Provides information about optimal distance range between phone lens and fingers . This listener is optional and is useful when UISettings are not provided. |
feedbackListener FingerCaptureFeedbackListener | Provides 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 FingerCaptureTrackingListener | Provides localisation of fingers. This listener is optional and is useful when UISettings are not provided. |
result LatentResultListener | Provides information about capture status. |
torchListener TorchListener | Provides 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.
Kotlin1fun onCaptureDistanceRangeInformation(captureDistanceRangeResult: CaptureDistanceRangeResult)
CaptureDistanceRangeResult
CaptureDistanceRangeResult is a sealead class. It may be CaptureDistanceRangeSuccess or CaptureDistanceRangeUnavailable
Value | Description |
---|---|
CaptureDistanceRangeSuccess | Means that the device is calibrated for distance indication feature. Contains CaptureDistanceRange |
CaptureDistanceRangeUnavailable | Means that the device isn't calibrated for distance indication feature or retrieving optimal distance is not possible. |
CaptureDistanceRange
Parameter | Description |
---|---|
rangeMin Float | Minimum value that may be returned in boundary range. |
optimalMin Float | Lower boundary of optimal distance between the phone lens and the fingerprint. |
optimalMax Float | Upper boundary of optimal distance between the phone lens and the fingerprint. |
rangeMax Float | Maximum value that may be returned in boundary range. |
CaptureDistanceRangeUnavailable
Parameter | Description |
---|---|
reason String | A reason why CaptureDistanceRange is unavailable. |
Kotlin1fun onCurrentCaptureDistance(currentCaptureDistance: CurrentCaptureDistance)
CurrentCaptureDistance
Parameter | Description |
---|---|
value Float | Current distance between the fingerprint and the phone lens. |
FingerCaptureFeedbackListener
Provides information if the distance between fingers (fingerprints) and the phone is acceptable.
Kotlin1fun onCaptureInfo(captureInfo: FingerCaptureInfo)
FingerCaptureInfo
Value | Description |
---|---|
OPTIMAL | Indicates that the distance between the fingers (fingerprints) and the phone lens is optimal. |
TOO_CLOSE | Indicates that the phone lens is too close from the fingers (fingerprints) and should be moved further. |
TOO_FAR | Indicates 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.
Kotlin1fun onTracking(finger: List<FingerBox>)
FingerBox
Parameter | Description |
---|---|
x Int | Coordinate of the left side of the rectangle top. |
y Int | Coordinate of the top of the rectangle right. |
width Int | Rectangle width. |
height Int | Rectangle height. |
previewWidth Int | Width of the preview. |
previewHeight Int | Height of the preview. |
orientation Int | Rectangle rotation value, in degrees. |
TorchListener
Returns TorchController that can be used to control the device torch.
Kotlin1fun onTorchControllerProvided(torchController: TorchController)
TorchController
Kotlin1interface TorchController {2 fun setTorch(torch: Torch)3 fun getTorch(): Torch4}
Torch
Type | Description |
---|---|
ON | Torch is on or will be turned on |
OFF | Torch 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.
Kotlin1interface TorchController {2 fun onSuccess(result: LatentSuccess)3 fun onError(error: Error)4}
LatentSuccess
Parameter | Description |
---|---|
image LatentImage | Contains image in PNG format with width and height. |
LatentImage
Parameter | Description |
---|---|
width Int | Image width. |
height Int | Image height. |
data ByteArray | PNG 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 ErrorType | Type of an error. High level information what goes wrong. Find types description below. |
code Int | Special code dedicated for particular case. Very helpful in L2, L3 troubleshooting. |
message String | Message with error description. |
ErrorType
Type | Description |
---|---|
TIMEOUT | Timeout occured during the flow. |
BAD_CAPTURE | Capture failed. Fingerprint was not detected or some kind of internal issue appeared. |
UNKNOWN | Unknow type of exception. Also used as default type for few cases. |
INVALID_LICENSE | License 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.
Java1BioStoreDB.listTemplates(context, userId, new DataBaseAsyncCallbacks<List<IMorphoTemplate>>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(List<IMorphoTemplate> result) {9 //The list of templates that match the criteria.10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred.15 }16 });
Function
Java1public static void listTemplates(final Context context, final UUID userId, DataBaseAsyncCallbacks<List<IMorphoTemplate>> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
userId UUID | The user identifier. |
callbacks DataBaseAsyncCallbacks | Callbacks 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
.
Java1BioStoreDB.listTemplates(context, userId, biometricModality, new DataBaseAsyncCallbacks<List<IMorphoTemplate>>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(List<IMorphoTemplate> result) {9 //The list of templates that match the criteria.10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred.15 }16 });
Function
Java1void listTemplates(final Context context, final UUID userId, final BiometricModality biometricModality, DataBaseAsyncCallbacks<List<IMorphoTemplate>> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
userId UUID | The user id . |
biometricModality BiometricModality | The BiometricModality enum option. |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.addTemplate(context, morphoTemplate, new DataBaseAsyncCallbacks<UUID>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(UUID result) {9 //The template has been added and the template's uuid is returned as a parameter.10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred.15 }16 });
Function
Java1public static void addTemplate(final Context context, final IMorphoTemplate template, DataBaseAsyncCallbacks<UUID> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
template IMorphoTemplate | The template to be stored. |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.updateTemplate(context, morphoTemplate, new DataBaseAsyncCallbacks<Void>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(Void result) {9 //updated.10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred.15 }16});
Function
Java1void updateTemplate(final Context context, final IMorphoTemplate template, DataBaseAsyncCallbacks<Void> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
template IMorphoTemplate | The template to be updated. |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.removeTemplate(context, templateId, new DataBaseAsyncCallbacks<Void>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(Void result) {9 //The template was removed.10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred.15 }16 });
Function
Java1void removeTemplate(final Context context, final UUID templateId, DataBaseAsyncCallbacks<Void> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
templateId UUID | The template id to be removed. |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.removeTemplateByUserId(context, userId, new DataBaseAsyncCallbacks<Integer>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(Integer result) {9 //The number of templates removed.10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred.15 }16 });
Function
Java1void removeTemplateByUserId(final Context context, final UUID userId, DataBaseAsyncCallbacks<Integer> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
userId UUID | The user id . |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.getTemplate(context, templateId, new DataBaseAsyncCallbacks<IMorphoTemplate>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(IMorphoTemplate result) {9 //The template if exists.10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred.15 }16 });
Function
Java1void getTemplate(final Context context, final UUID templateId, DataBaseAsyncCallbacks<MorphoTemplate> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
templateId UUID | The template id . |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.clear(context, new DataBaseAsyncCallbacks<Void>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(Void result) {9 //Data has been cleared10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred15 }16 });
Function
Java1void clear(final Context context, DataBaseAsyncCallbacks<Void> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1IUser user = new User();2 user.setName("Jose");3 BioStoreDB.addUser(context, user, new DataBaseAsyncCallbacks<UUID>() {4 @Override5 public void onPreExecute() {6 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`7 }89 @Override10 public void onSuccess(UUID result) {11 //User saved12 }1314 @Override15 public void onError(Exception e) {16 // An error has occurred17 }18 });
Function
Java1void addUser(final Context context, final IUser user, DataBaseAsyncCallbacks<UUID> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
user IUser | The user. |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1IUser user = ...//retrieve old user2 BioStoreDB.updateUser(context, user, new DataBaseAsyncCallbacks<Void>() {3 @Override4 public void onPreExecute() {5 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`6 }78 @Override9 public void onSuccess(Void result) {10 //User updated.11 }1213 @Override14 public void onError(Exception e) {15 // An error has occurred.16 }17 });
Function
Java1void updateUser(final Context context, final IUser user, DataBaseAsyncCallbacks<Void> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
user IUser | The user. |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.removeUser(context, uuid, new DataBaseAsyncCallbacks<Void>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(Void result) {9 //User removed10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred15 }16 });
Function
Java1void removeUser(final Context context, final UUID uuid, DataBaseAsyncCallbacks<Void> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
uuid UUID | The user uuid . |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.getUser(context, uuid, new DataBaseAsyncCallbacks<IUser>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(IUser result) {9 //User10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred15 }16 });
Function
Java1void getUser(final Context context, final UUID uuid, DataBaseAsyncCallbacks<IUser> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
uuid UUID | The user uuid . |
callbacks DataBaseAsyncCallbacks | Callbacks 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.
Java1BioStoreDB.listUsers(context, new DataBaseAsyncCallbacks<List<IUser>>() {2 @Override3 public void onPreExecute() {4 // Optional hook on the builtin Android AsyncTask callback `onPreExecute`5 }67 @Override8 public void onSuccess(List<IUser> result) {9 //Users10 }1112 @Override13 public void onError(Exception e) {14 // An error has occurred15 }16 });
Function
Java1void listUsers(final Context context, DataBaseAsyncCallbacks<List<IUser>> callbacks);
Parameter | Description |
---|---|
context Context | The Android context. |
callbacks DataBaseAsyncCallbacks | Callbacks to be executed depending on the result. |
Errors
You will receive an exception reporting the error.