Use the following code snippet to receive SDK callbacks
VIDVOCRListenervidvOcrListener=newVIDVOCRListener(){@OverridepublicvoidonOCRResult(VIDVOCRResponseresponse){if(response instanceof Success){ //an example code to use the response in your app : StringfirstName=((Success) response).getData().getOcrResult().getFirstName(); //firstName variable will hold the first name of the scanned National ID // Add your own code}elseif(response instanceof CapturedImages){ // Add your own code }elseif(response instanceof UserExit){ // Add your own code}elseif(response instanceof ServiceFailure){ // Add your own code}elseif(response instanceof BuilderError){ // Add your own code}}};
Document verification plus - Case Handling
When using VIDVOCRResult.getData(), the returned ocrResult may include a documentVerificationPlusobject.
This object contains validation flags and quality signals that help you determine whether the document should be accepted, reviewed, recaptured, or rejected.
Fields Returned Under documentVerificationPlus
Field
Type
Meaning
frontDataValidity
boolean
Overall validity of the front side based on greyscale flags + invalid fields list
backDataValidity
boolean
Overall validity of the back side based on greyscale flags + invalid fields list
isFrontGreyscale
boolean
Indicates whether the front side is greyscale
isBackGreyscale
boolean
Indicates whether the back side is greyscale
expired
boolean
Whether the document is recognized as expired
reviewRequired
List<String>
Fields that require attention (e.g. Nid, gender, expirydate…)
How to Read These Values
frontDataValidity and backDataValidity act as parent flags
→ You can take action directly based on them if you want a simple validation flow.
For more control, you can check detailed signals:
use greyscale flags if you want to reject black-and-white copies
use reviewRequiredto apply different logic per field
e.g. reject if nid is invalid but allow if gender is inconsistent
This allows fully customizable decision logic depending on your business rules.
Example Handling Logic
Advance confidence - Case Handling
When using VIDVOCRResult.getData(), the returned ocrResult may include a advancedConfidence object.
This object contains manipulation flags that help you determine whether the document should be accepted, reviewed, recaptured, or rejected.
Fields Returned Under advanceConfidence
Field
Type
Meaning
fraudDetectionZone
int
Parent zone flag → Result of face + image manipulation combined
faceFraudZone
int
Fraud confidence specifically related to face physical tampering
frontImageManipulationZone
int
Indicates signs of front image physical manpulation
Zone Meaning
Value
Color
Meaning
0
Green
No manipulation detected
1
Yellow
Requires human review (suspicious)
2
Red
Strong indicators of fraud / manipulation
Example Handling Logic
Response Instances
Success : Process finished successfully
CapturedImages: Images captured are returned in real-time
Note: ForCapturedImagesinstance, images are not processed yet
BuilderError : Process terminated due to an error in the builder
Note: Check your configurations
ServiceFailure : Process finished with the user's failure to pass the service requirements
UserExit : Process terminated by the user with no errors
Primary Response Object
VIDVOCRResult
Note: This is the first-level object that contains all the second-level objects.
It is present in these type of response and holds data related to the responses, includingSuccess,ServiceFailure, and UserExit.
Here is the attributes of VIDVOCRResultclass that represents the data that could be retrived from the response object VIDVOCRResponse using getData() method that returnsVIDVOCRResultobject like in the example code above showing a use of Success response.
//Note that all decisions taken in this code are just an example of how you can handle
//the logic and that you can take the preferred action according to your business needs
val flags = result.data?.ocrResult?.documentVerificationPlus
when {
// --------------------- GENERIC VALIDATION RESULTS --------------------- //
// Quick validation using global parent flags
flags?.frontDataValidity == false || flags?.backDataValidity == false -> {
AlertDialog(
onDismissDialog = {showRetryOCRSDKDialog.value = false}, onClick = {
// start ocr sdk
}
}, title = "The document failed validation checks." ,"Retry")
}
// Greyscale document detection
flags?.isFrontGreyscale == true || flags?.isBackGreyscale == true -> {
requestRecapture("Document appears to be black & white.") // Developer replaces with custom retry logic
}
// Document is expired
flags?.isExpired == true -> {
AlertDialog(
onDismissDialog = {showRetryOCRSDKDialog.value = false}, onClick = {
// start ocr sdk
}
}, title = "OCR", "Expired ID, Please try again with your recent National ID." ,"Retry")
}
// One or more fields require review
flags?.reviewRequired.isNotEmpty() == true -> {
showError("Some fields require manual review.") // Replace with custom handling
}
// --------------------- FIELD-LEVEL CASES (HANDLE INDIVIDUALLY) --------------------- //
"serial_number" in flags?.reviewRequired.orEmpty() -> {
AlertDialog(
onDismissDialog = {showRetryOCRSDKDialog.value = false}, onClick = {
// start ocr sdk
}
}, title = "OCR", "Serial number is incorrect. Please try again" ,"Retry")}
}
"back_nid" in flags?.reviewRequired.orEmpty() ||
"front_nid" in flags?.reviewRequired.orEmpty() -> {
requestRecapture("NID Mismatch") // Developer replaces with custom retry logic
}
"date_of_birth" in flags?.reviewRequired.orEmpty() -> showError("Date of birth could not be verified.") // Replace with custom handling
"street" in flags?.reviewRequired.orEmpty() -> showError("Street address is empty.") // Replace with custom handling
"police_station" in flags?.reviewRequired.orEmpty() -> showError("Police station field needs review.") // Replace with custom handling
"governorate" in flags?.reviewRequired.orEmpty() -> showError("Governorate value could not be verified.") // Replace with custom handling
"birth_governorate" in flags?.reviewRequired.orEmpty() -> showError("Birth governorate requires review.") // Replace with custom handling
"expiry_date" in flags?.reviewRequired.orEmpty() -> showError("Expiry date is missing or invalid.") // Replace with custom handling
"release_date" in flags?.reviewRequired.orEmpty() -> showError("Release date did not pass validation.") // Replace with custom handling
else -> {
}
}
//Note that all decisions taken in this code are just an example of how you can handle
//the logic and that you can take the preferred action according to your business needs
val fraud = result.data?.ocrResult?.advancedConfidence
// Generic Handling
when (fraud?.fraudDetectionZone) {
1 -> showWarning("Document may be manipulated — review recommended") // Replace with custom handling
2 -> requestRecapture("Possible fraud detected — please retry with clear document")
}
// Detailed Handling
when {
fraud?.faceFraudZone == 1 || fraud?.faceFraudZone == 2 ->
showError("Face area appears manipulated")
fraud?.frontImageManipulationZone == 1 || fraud?.frontImageManipulationZone == 2 ->
showError("Front side image shows manipulation traces")
else -> { /* Accept normally */ }
}