Android - OCR Module¶
The OCR module reads data from identity cards or passports using images taken from the rear camera. It performs visual object analysis, hologram detection, front/back face reading, and MRZ area reading operations.
⚠️ Prerequisite: Before using the OCR Module, Maven access must be provided and the Core Module must be added to the project.
Adding to the Project¶
1. Add to the libs.versions.toml file:¶
[versions]
...
enqualify-plus = "x.x.x.x"
[libraries]
...
enqualify-plus-ocr = {
group = "com.enqualify.plus",
name = "ocr",
version.ref = "enqualify-plus"
}
2. Add the dependency to the build.gradle.kts file:¶
3. Gradle Sync¶
Synchronize the Gradle files by clicking on the "Sync Now" option.
ℹ️ The version number must be the same across all modules.
Implementation¶
1. Permissions¶
Camera permission is automatically added to the manifest by the SDK and requested at necessary points by the SDK. The following line is for informational purposes only:
The OCR module will not work if camera permission is not granted.
2. Activity Layout — FrameLayout¶
A FrameLayout that covers the full screen must be added to the layout of the Activity where the OCR operation will take place. The SDK manages camera screens and page transitions through this component:
<FrameLayout
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
3. Adding the OCRCallbacks Interface¶
The OCRCallbacks interface contains the necessary callback methods to manage OCR operations and must work with an Activity.
Add to the class:
Override the callbacks:
class EnQualifyPlusActivity : AppCompatActivity(), OCRCallbacks {
override fun IDDocTypeCheckVerified(isFront: Boolean) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun IDDocFrontCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun hologramCheckVerified() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun IDDocBackCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun IDDocSaveStarted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun IDDocCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun IDDocFailed(ocrFailureCode: OCRFailureCode, additionalMessage: String?) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
// LuminosityFailed is not a critical error; reading should not be stopped.
}
override fun initializeCompleted(module: EnModules) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
when (module) {
EnModules.OCR -> {
// OCR processes can be initiated
}
}
}
override fun initializeFailed(failureCode: FailureCode, additionalMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun FrontCrescentConcealChecked() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun FrontMliConcealChecked() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun FrontSignatureConcealChecked() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun BackOviConcealChecked() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun IDDocConcealCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
}
The LuminosityFailed error will be captured through the IDDocFailed() callback and is not a critical error. It simply indicates that the brightness is not suitable. When this error occurs, the flow should not be interrupted. If desired, a related warning about brightness can be displayed.
4. Initializing EnQualifyOCR¶
Before starting OCR operations, EnQualifyOCR.initialize() must be called. If another operation is attempted without initialization, the SDK will not work.
val sessionModel = SessionModel(
callType = "NewCustomer",
reference = UUID.randomUUID().toString()
)
val baseModel = BaseModel(
baseURL = "https://deveqmapi.enqura.com",
signallingCertificateList = listOf("enqura"),
mapiCertificateList = listOf("enqura"),
mobileUser = "mobile",
countryCode = "TUR",
locale = "TR",
useEmbeddedLocalSound = false
)
EnQualifyOCR.initialize(
context = this,
fragmentManager = supportFragmentManager,
containerID = R.id.fragmentContainer,
sessionModel = sessionModel,
baseModel = baseModel
)
Initialize Parameters¶
| Parameter | Type | Description |
|---|---|---|
context | Context | The runtime context of the application |
sessionModel | SessionModel | Session information to be used during the OCR process |
baseModel | BaseModel | Model carrying basic data during the verification process |
fragmentManager | FragmentManager | Manages the OCR fragments |
containerID | Int | The ID of the container where the OCR fragment will be added |
Automatic Flow After Initialization¶
After the initialize() is called, the SDK automatically executes the following steps in order:
- Token Creation If the token creation fails,
tokenCreateFailedis triggered:
override fun tokenCreateFailed(errorMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name} $errorMessage")
}
- Session Start If the session start fails,
sessionAddFailedis triggered:
override fun sessionAddFailed(errorMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
- Getting Settings If the settings cannot be retrieved,
settingsGetFailedis triggered:
override fun settingsGetFailed(errorMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
- Completion Once all steps are successfully completed,
initializeCompletedis triggered, and OCR operations can be initiated.
OCR Operations¶
Functions¶
| Function | Description |
|---|---|
addFragment(fragment) | Adds a new fragment on top of the current fragment |
replaceFragment(fragment) | Replaces the current fragment with a new one |
iDDocTypeCheckStart(isFront: Boolean = true) | Starts the identity type recognition process. Indicates which face needs to be recognized with the parameter it receives. |
hologramCheckStart() | Starts the hologram detection process |
iDDocFrontStart(withVisualAnalysis: Boolean = false) | Starts scanning the front face of the identity. If the parameter is set to true, visual elements will also be analyzed. |
iDDocBackStart(withVisualAnalysis: Boolean = false) | Starts scanning the back face of the identity. If the parameter is set to true, visual elements will also be analyzed. |
iDDocComplete() | Notifies the SDK that all identity reading steps are completed |
addIntegration(integrationModel) | Adds integration data |
closeSession(isFinished: Boolean) | Closes the session |
clear() | Clears the SDK |
getSessionUId() | Returns the UId of the current session. |
concealConfigGet() | Returns the touch test elements that can be performed in list form. |
frontSignatureConcealCheck() | Starts the touch test for the front signature. |
frontMliConcealCheck() | Starts the touch test for the front MLI. |
frontCrescentConcealCheck() | Starts the touch test for the front crescent. |
backOviConcealCheck() | Starts the touch test for the back face OVI. |
idDocConcealComplete() | Ends the touch test. |
Identity Type Recognition¶
When the process is completed, IDDocTypeCheckVerified is triggered. The isFront parameter indicates which face of the identity will be identified.
override fun IDDocTypeCheckVerified(isFront: Boolean) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Identity Front Face Scanning¶
When the process is completed, IDDocFrontCompleted is triggered:
override fun IDDocFrontCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Hologram Detection¶
When the process is completed, hologramCheckVerified is triggered:
override fun hologramCheckVerified() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Identity Back Face Scanning¶
When the process is completed, IDDocBackCompleted is triggered:
override fun IDDocBackCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Ending the Identity Reading Flow¶
When all steps are completed, iDDocComplete() is called. This function stops the camera analysis, ends the processing, and starts sending the read data to the backoffice:
When the data is successfully sent to the backoffice, IDDocCompleted is triggered:
override fun IDDocCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Front Crescent Touch Test¶
This step can only be performed after the OCR process is completed.
When the touch test is successful, FrontCrescentConcealChecked is triggered:
override fun FrontCrescentConcealChecked {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Front Signature Touch Test¶
This step can only be performed after the OCR process is completed.
When the touch test is successful, FrontSignatureConcealChecked is triggered:
override fun FrontSignatureConcealChecked {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Front MLI (Ghost Image) Touch Test¶
This step can only be performed after the OCR process is completed.
When the touch test is successful, FrontMliConcealChecked is triggered:
override fun FrontMliConcealChecked {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Back OVI Touch Test¶
This step can only be performed after the OCR process is completed.
When the touch test is successful, BackOviConcealChecked is triggered:
override fun BackOviConcealChecked {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Ending the Touch Test¶
After the touch test operations are performed, this function is called.
When the process is completed, idDocConcealCompleted is triggered:
override fun idDocConcealCompleted {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Adding Integration Data¶
val integrationModel = IntegrationModel(
idRegistration = IDRegistration(),
addressRegistration = AddressRegistration(),
data = ""
)
enQualifyOCR.addIntegration(integrationModel)
Results are listened to through the following callbacks:
override fun integrationAddCompleted() {
Log.i(TAG, "integrationAddCompleted")
}
override fun integrationAddFailed(errorMessage: String) {
Log.i(TAG, "integrationAddFailed: $errorMessage")
}
Closing Session and Clearing¶
// Close the session
enQualifyOCR.closeSession(isFinished = true)
// Session closure callbacks
override fun sessionCloseCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
override fun sessionCloseFailed(errorMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name} $errorMessage")
}
// Clear the SDK (should be called after the session is closed)
enQualifyOCR.clear()
ℹ️ After closing the session,
initialize()must be called again to reuse the SDK.
Getting Session Information¶
Error Management¶
FailureCode (Core / Initialize Errors)¶
enum class FailureCode(val errorMessage: String) {
CameraError("Unable to access the camera. Please check device settings and retry."),
CameraStartError(""),
CameraNotSupported("Failed to initialize the camera. Device may not support required resolution or FPS."),
SdkInitializationError("Required sdk initialization did not completed."),
CameraPermissionDenied("Camera permission denied"),
CertificateFailed("Certificate failed"),
AIModelNotFound("AI model not found"),
NfcCertificateNotFound("Nfc Certificate not found")
}
It is communicated through the initializeFailed callback:
override fun initializeFailed(failureCode: FailureCode, additionalMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
OCRFailureCode (OCR Process Errors)¶
enum class OCRFailureCode(errorMessage: String) {
IDDocSaveFailed("save failed"),
LuminosityFailed("Luminosity failed"), // Is not critical — reading should not be stopped
TypeCheckFailed(""),
HologramCheckError(""),
VisualAnalysingFrontError(""),
VisualAnalysingBackError(""),
ReadIdDocFrontError(""),
ReadIdDocBackError(""),
ReadPassportError(""),
IDDocError(""),
CameraError("Unable to access the camera. Please check device settings and retry."),
CameraStartError(""),
CameraNotSupported("Failed to initialize the camera. Device may not support required resolution or FPS."),
SdkInitializationError("Required sdk initialization did not completed."),
CameraPermissionDenied("Camera permission denied"),
Failed(""),
IDDocTimeout("Timeout")
}
It is communicated through the IDDocFailed callback:
override fun IDDocFailed(ocrFailureCode: OCRFailureCode, additionalMessage: String?) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
⚠️ Important:
LuminosityFailedis a warning and is not critical. When this error occurs, the reading process should not be interrupted.
Accessing Result Data¶
Once the OCR reading process is completed, the read data can be accessed through the CustomerIDDoc object:
For the explanation of the CustomerIDDoc model and all its fields, refer to the Core Module — CustomerIDDoc page.
Callback Reference¶
Token / Session / Settings¶
| Callback | Description |
|---|---|
tokenCreateCompleted(isNewCreatedToken: Boolean) | Triggered when a token is created |
tokenCreateFailed(errorMessage: String) | Token creation error |
sessionAddFailed(errorMessage: String) | Session creation error |
settingsGetFailed(errorMessage: String) | Triggered when settings cannot be retrieved |
sessionCloseCompleted(status: CallSessionTypeStatus) | Triggered when the session is closed |
sessionCloseFailed(errorMessage: String) | Session closing error |
integrationAddCompleted() | Integration data has been successfully added |
integrationAddFailed(errorMessage: String) | Unable to add integration data |
initializeFailed(failureCode: FailureCode, additionalMessage: String) | Core initialize error |
OCR¶
| Callback | Description |
|---|---|
initializeCompleted(module: EnModules) | Initialization completed, OCR ready |
IDDocTypeCheckVerified(isFront: Boolean) | Identity type successfully identified |
hologramCheckVerified() | Hologram successfully detected |
IDDocFrontCompleted() | Front face reading completed |
IDDocBackCompleted() | Back face reading completed |
IDDocSaveStarted() | Data started to be sent to the backoffice |
IDDocCompleted() | Data successfully sent to the backoffice |
IDDocFailed(ocrFailureCode, additionalMessage) | OCR process error |
FrontCrescentConcealChecked() | Front crescent touch detected |
FrontMliConcealChecked() | Front MLI touch detected |
FrontSignatureConcealChecked() | Front signature touch detected |
BackOviConcealChecked() | Back OVI touch detected |
IDDocConcealCompleted() | Touch test completed |