Android - OCR Module¶
The OCR module reads data from identity cards or passports using images captured by the rear camera. It performs visual object analysis, hologram detection, front/back face reading, and MRZ area reading operations.
⚠️ Prerequisite: Maven access must be provided before using the OCR Module 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 dependency to the build.gradle.kts file:¶
3. Gradle Sync¶
Sync the Gradle files by clicking on the "Sync Now" option.
ℹ️ The version number must be the same for all modules.
Implementation¶
1. Permissions¶
Camera permission is automatically added to the manifest by the SDK and is requested by the SDK at required points. 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 entire screen should be added to the layout of the Activity where the OCR process 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.
Adding to the class:
Overriding 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 interrupted.
}
override fun initializeCompleted(module: EnModules) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
when (module) {
EnModules.OCR -> {
// OCR operations 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}")
}
}
Note
The LuminosityFailed error captured via the IDDocFailed() callback is not a critical error. It only indicates that the brightness is not adequate. When this error occurs, the flow should not be interrupted. If desired, a warning related to brightness can be shown.
4. Initializing EnQualifyOCR¶
Before starting OCR operations, EnQualifyOCR.initialize() must be called. If another operation is attempted before initialization, the SDK will not function.
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
)
Initialization Parameters¶
| Parameter | Type | Description |
|---|---|---|
context | Context | The runtime context of the application |
sessionModel | SessionModel | Session information to be used during OCR operations |
baseModel | BaseModel | Model carrying the basic data during the validation 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 initialize() is called, the SDK automatically executes the following steps sequentially:
- Token Creation If token creation fails,
tokenCreateFailedis triggered:
override fun tokenCreateFailed(errorMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name} $errorMessage")
}
- Session Initialization If session initialization fails,
sessionAddFailedis triggered:
override fun sessionAddFailed(errorMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
- Fetching Settings If settings cannot be fetched,
settingsGetFailedis triggered:
override fun settingsGetFailed(errorMessage: String) {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
- Completion When all steps are completed successfully,
initializeCompletedis triggered, and OCR operations can be started.
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. The parameter specifies which face should be recognized. |
hologramCheckStart() | Starts the hologram detection process |
iDDocFrontStart(withVisualAnalysis: Boolean = false) | Starts scanning the front face of the identity. If set to true, visual element analysis will also take place. |
iDDocBackStart(withVisualAnalysis: Boolean = false) | Starts scanning the back face of the identity. If set to true, visual element analysis will also take place. |
iDDocComplete() | Notifies the SDK that all identity reading steps have been completed |
addIntegration(integrationModel) | Adds integration data |
closeSession(isFinished: Boolean) | Closes the session |
clear() | Cleans the SDK |
getSessionUId() | Returns the UId of the current session. |
concealConfigGet() | Returns a list of touch test items that can be performed. |
frontSignatureConcealCheck() | Starts a touch test for the front signature. |
frontMliConcealCheck() | Starts a touch test for the front MLI. |
frontCrescentConcealCheck() | Starts a touch test for the front crescent. |
backOviConcealCheck() | Starts a 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 specifies 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}")
}
ID Back Side Scanning¶
When the process is completed, IDDocBackCompleted is triggered:
override fun IDDocBackCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Finishing ID Reading Flow¶
When all steps are completed, iDDocComplete() is called. This function stops the camera analysis, terminates the process, and begins sending the read data to the backoffice:
When the data is successfully transmitted to the backoffice, IDDocCompleted is triggered:
override fun IDDocCompleted() {
Log.i(tag, "${object {}.javaClass.enclosingMethod?.name}")
}
Front Side 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 Side 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 Side 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 Side 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}")
}
Finishing Touch Test¶
This function is called after the touch test operations have been performed.
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 for through the following callbacks:
override fun integrationAddCompleted() {
Log.i(TAG, "integrationAddCompleted")
}
override fun integrationAddFailed(errorMessage: String) {
Log.i(TAG, "integrationAddFailed: $errorMessage")
}
Closing and Clearing Session¶
// Close the session
enQualifyOCR.closeSession(isFinished = true)
// Session close 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 SDK (should be called after session is closed)
enQualifyOCR.clear()
ℹ️ After closing the session,
initialize()must be called again to reuse the SDK.
Obtaining 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"), // This is non-fatal — 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 non-fatal. The reading process should not be stopped when this error occurs.
Accessing Result Data¶
After the OCR reading process is completed, the read data can be accessed via the CustomerIDDoc object:
For the description 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 the 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 close error |
integrationAddCompleted() | Integration data added successfully |
integrationAddFailed(errorMessage: String) | Failed 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) | ID type successfully detected |
hologramCheckVerified() | Hologram successfully detected |
IDDocFrontCompleted() | Front side reading completed |
IDDocBackCompleted() | Back side reading completed |
IDDocSaveStarted() | Data transmission to backoffice has started |
IDDocCompleted() | Data successfully transmitted to 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 |