diff --git a/README.md b/README.md index fa2b7a5..10e3657 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Acuant Android SDK v11.4.12 -**April 2021** +# Acuant Android SDK v11.4.13 +**May 2021** See [https://github.com/Acuant/AndroidSDKV11/releases](https://github.com/Acuant/AndroidSDKV11/releases) for release notes. @@ -193,18 +193,18 @@ The SDK includes the following modules: - Add the following dependencies - implementation 'com.acuant:acuantcommon:11.4.12' - implementation 'com.acuant:acuantcamera:11.4.12' - implementation 'com.acuant:acuantimagepreparation:11.4.12' - implementation 'com.acuant:acuantdocumentprocessing:11.4.12' - implementation 'com.acuant:acuantechipreader:11.4.12' - implementation 'com.acuant:acuantfacematch:11.4.12' - implementation 'com.acuant:acuanthgliveness:11.4.12' - implementation ('com.acuant:acuantipliveness:11.4.12'){ + implementation 'com.acuant:acuantcommon:11.4.13' + implementation 'com.acuant:acuantcamera:11.4.13' + implementation 'com.acuant:acuantimagepreparation:11.4.13' + implementation 'com.acuant:acuantdocumentprocessing:11.4.13' + implementation 'com.acuant:acuantechipreader:11.4.13' + implementation 'com.acuant:acuantfacematch:11.4.13' + implementation 'com.acuant:acuanthgliveness:11.4.13' + implementation ('com.acuant:acuantipliveness:11.4.13'){ transitive = true } - implementation 'com.acuant:acuantfacecapture:11.4.12' - implementation 'com.acuant:acuantpassiveliveness:11.4.12' + implementation 'com.acuant:acuantfacecapture:11.4.13' + implementation 'com.acuant:acuantpassiveliveness:11.4.13' - Acuant also relies on Google Play services dependencies, which are pre-installed on almost all Android devices. diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/AcuantMrzCameraFragment.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/AcuantMrzCameraFragment.kt index bb20e6b..c24663a 100644 --- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/AcuantMrzCameraFragment.kt +++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/AcuantMrzCameraFragment.kt @@ -119,6 +119,7 @@ class AcuantMrzCameraFragment : AcuantBaseCameraFragment(), ActivityCompat.OnReq override fun onOcrDetected(textBlock: String?){ if (textBlock != null && allowCapture) { val result = mrzParser.parseMrz(textBlock) + //Log.d("MRZLOG", " " + result?.checkSumResult1 + ", "+ result?.checkSumResult2 +", "+ result?.checkSumResult3 +", "+ result?.checkSumResult4 +", "+ result?.checkSumResult5) if (result != null) { if (result.checkSumResult1 && result.checkSumResult2 && result.checkSumResult3 && result.checkSumResult4 && result.checkSumResult5) { capturing = true @@ -204,7 +205,7 @@ class AcuantMrzCameraFragment : AcuantBaseCameraFragment(), ActivityCompat.OnReq fun isAcceptableAspectRatio(points: Array) : Boolean { val ratio = distance(points[0], points[3]) / distance(points[0], points[1]) - return ratio > 8f && ratio < 10f + return ratio > 4f && ratio < 10f } fun isAcceptableDistance(points: Array, screenSize: Float): Boolean { diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/MrzParser.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/MrzParser.kt index 181b3eb..819202d 100644 --- a/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/MrzParser.kt +++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/MrzParser.kt @@ -1,7 +1,5 @@ package com.acuant.acuantcamera.helper -import android.util.Log - class MrzParser{ companion object { @@ -19,15 +17,130 @@ class MrzParser{ mrzLines.add(mrzLinesTmp[i]) } } - if(mrzLines.size == 2){ - val result = parseFirstLine(mrzLines[0]) + + if (mrzLines.size == 2) { + //Log.d("MRZLOG", "Follows:\n" + mrzLines[0] + "\n" +mrzLines[1]) + var result = parseFirstLineOfTwoLine(mrzLines[0]) //not checking result of first line as it is not strictly needed for echip reading - return parseSecondLine(mrzLines[1], result) + result = parseSecondLineOfTwoLine(mrzLines[1], result) + + result?.threeLineMrz = false + //Log.d("MRZLOG", " " + result?.checkSumResult1 + ", "+ result?.checkSumResult2 +", "+ result?.checkSumResult3 +", "+ result?.checkSumResult4 +", "+ result?.checkSumResult5) + return result + } else if (mrzLines.size == 3) { + //Log.d("MRZLOG", "Follows:\n" + mrzLines[0] + "\n" +mrzLines[1]) + var result = parseFirstLineOfThreeLine(mrzLines[0]) + if (result != null) { + result = parseSecondLineOfThreeLine(mrzLines[1], result) + + result?.threeLineMrz = true + + return result + //third line does not contain any relevant info + } } return null } - private fun parseFirstLine(firstLine:String): MrzResult?{ + private fun parseFirstLineOfThreeLine (firstLine: String) : MrzResult? { + var startPos = 0 + if(firstLine.length == 30){ + startPos+=2 + + val country = firstLine.substring(startPos, startPos+3) + startPos+=3 + + var passportNumber = firstLine.substring(startPos, startPos+9) + startPos+=9 + + var check1 = firstLine[startPos] + var checkSumResult1 = checkSum(passportNumber, check1) + ++startPos + + if (!checkSumResult1) { + passportNumber = passportNumber.replace('O', '0') + checkSumResult1 = checkSum(passportNumber, check1) + + if (checkSumResult1 && check1 == 'O') { + check1 = '0' + checkSumResult1 = checkSum(passportNumber, check1) + } + } + + val optional1 = firstLine.substring(startPos, startPos + 15) + + return MrzResult(country = country, passportNumber = passportNumber, checkSumResult1 = checkSumResult1, checkChar1 = check1, optionalField1 = optional1) + } + return null + } + + private fun parseSecondLineOfThreeLine (line: String, result: MrzResult) : MrzResult? { + + if(line.length != 30){ + return null + } + + var startPos = 0 + result.dob = line.substring(startPos, startPos+6) + startPos+=6 + + var check2 = line[startPos] + result.checkSumResult2 = checkSum(result.dob, check2) + ++startPos + + if (!result.checkSumResult2) { + result.dob = result.dob.replace('O', '0') + result.checkSumResult2 = checkSum(result.dob, check2) + + if (!result.checkSumResult2 && check2 == 'O') { + check2 = '0' + result.checkSumResult2 = checkSum(result.dob, check2) + } + } + + result.gender = line.substring(startPos, startPos+1) + ++startPos + + result.passportExpiration = line.substring(startPos, startPos+6) + startPos+=6 + + var check3 = line[startPos] + result.checkSumResult3 = checkSum(result.passportExpiration, check3) + ++startPos + + if (!result.checkSumResult3) { + result.passportExpiration = result.passportExpiration.replace('O', '0') + result.checkSumResult3 = checkSum(result.passportExpiration, check3) + + if (!result.checkSumResult3 && check3 == 'O') { + check3 = '0' + result.checkSumResult3 = checkSum(result.passportExpiration, check3) + } + } + + result.nationality = line.substring(startPos, startPos+3) + startPos+=3 + + val optional2 = line.substring(startPos, startPos+11) + startPos += 11 + + val finalCheckString = result.passportNumber + result.checkChar1 + result.optionalField1 + result.dob + check2 + + result.passportExpiration + check3 + optional2 + result.checkSumResult4 = checkSum(finalCheckString, line[startPos]) + + if (!result.checkSumResult4 && line[startPos] == 'O') { + result.checkSumResult4 = checkSum(finalCheckString, '0') + } + + result.checkSumResult5 = true + + result.passportNumber = result.passportNumber.replace("<", "") + + return result + } + + + private fun parseFirstLineOfTwoLine(firstLine:String): MrzResult?{ var startPos = 0 if(firstLine[startPos] == PASSPORT_FIRST_VALUE && firstLine.length == 44){ startPos+=2 @@ -46,9 +159,8 @@ class MrzParser{ return null } - private fun parseSecondLine(line:String, result: MrzResult?): MrzResult?{ + private fun parseSecondLineOfTwoLine (line: String, result: MrzResult?) : MrzResult? { - //Log.d("SecondLine:", line) if(line.length != 44){ return null @@ -61,7 +173,7 @@ class MrzParser{ } var startPos = 0 - resultLocal.passportNumber = line.substring(startPos, startPos+9).replace("<", "") + resultLocal.passportNumber = line.substring(startPos, startPos+9)//.replace("<", "") startPos+=9 var check1 = line[startPos] @@ -140,9 +252,10 @@ class MrzParser{ resultLocal.checkSumResult5 = checkSum(finalCheckString, line[startPos]) if (!resultLocal.checkSumResult5 && line[startPos] == 'O') { - resultLocal.checkSumResult5 = checkSum(resultLocal.personalDocNumber, '0') + resultLocal.checkSumResult5 = checkSum(finalCheckString, '0') } - Log.d("SecondLine:", "" + resultLocal.checkSumResult1 + " " + resultLocal.checkSumResult2 + " " + resultLocal.checkSumResult3 + " " + resultLocal.checkSumResult4 + " " + resultLocal.checkSumResult5) + + resultLocal.passportNumber = resultLocal.passportNumber.replace("<", "") return resultLocal } diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/MrzResult.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/MrzResult.kt index ea3a3cc..55e094f 100644 --- a/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/MrzResult.kt +++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/MrzResult.kt @@ -11,8 +11,11 @@ data class MrzResult(var surName:String = "", var gender: String= "", var passportExpiration: String= "", var personalDocNumber: String= "", + internal var optionalField1: String= "", var checkSumResult1: Boolean = false, var checkSumResult2: Boolean = false, var checkSumResult3: Boolean = false, var checkSumResult4: Boolean = false, - var checkSumResult5: Boolean = false): Serializable + var checkSumResult5: Boolean = false, + var threeLineMrz: Boolean = false, + internal var checkChar1: Char = '<'): Serializable diff --git a/acuantcommon/acuantcommon.aar b/acuantcommon/acuantcommon.aar index 907af83..968a024 100644 Binary files a/acuantcommon/acuantcommon.aar and b/acuantcommon/acuantcommon.aar differ diff --git a/acuantdocumentprocessing/acuantdocumentprocessing.aar b/acuantdocumentprocessing/acuantdocumentprocessing.aar index ef8d5e0..e2dacda 100644 Binary files a/acuantdocumentprocessing/acuantdocumentprocessing.aar and b/acuantdocumentprocessing/acuantdocumentprocessing.aar differ diff --git a/acuantechipreader/acuantechipreader.aar b/acuantechipreader/acuantechipreader.aar index 91aba5a..8811497 100644 Binary files a/acuantechipreader/acuantechipreader.aar and b/acuantechipreader/acuantechipreader.aar differ diff --git a/acuantfacecapture/src/test/java/com/acuant/acuanthgliveness/ExampleUnitTest.java b/acuantfacecapture/src/test/java/com/acuant/acuanthgliveness/ExampleUnitTest.java deleted file mode 100644 index ac3ec3b..0000000 --- a/acuantfacecapture/src/test/java/com/acuant/acuanthgliveness/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.acuant.acuanthgliveness; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/acuantfacematch/acuantfacematch.aar b/acuantfacematch/acuantfacematch.aar index 26d959b..f6b22b8 100644 Binary files a/acuantfacematch/acuantfacematch.aar and b/acuantfacematch/acuantfacematch.aar differ diff --git a/acuanthgliveness/acuanthgliveness.aar b/acuanthgliveness/acuanthgliveness.aar index 629f597..eef02ac 100644 Binary files a/acuanthgliveness/acuanthgliveness.aar and b/acuanthgliveness/acuanthgliveness.aar differ diff --git a/acuantimagepreparation/acuantimagepreparation.aar b/acuantimagepreparation/acuantimagepreparation.aar index 39bb43e..919d7f1 100644 Binary files a/acuantimagepreparation/acuantimagepreparation.aar and b/acuantimagepreparation/acuantimagepreparation.aar differ diff --git a/acuantipliveness/acuantipliveness.aar b/acuantipliveness/acuantipliveness.aar index 4ed46aa..f75dcfb 100644 Binary files a/acuantipliveness/acuantipliveness.aar and b/acuantipliveness/acuantipliveness.aar differ diff --git a/acuantpassiveliveness/acuantpassiveliveness.aar b/acuantpassiveliveness/acuantpassiveliveness.aar index 03846b5..097b763 100644 Binary files a/acuantpassiveliveness/acuantpassiveliveness.aar and b/acuantpassiveliveness/acuantpassiveliveness.aar differ diff --git a/app/src/main/java/com/acuant/sampleapp/MainActivity.kt b/app/src/main/java/com/acuant/sampleapp/MainActivity.kt index 46c6831..f5cbe20 100644 --- a/app/src/main/java/com/acuant/sampleapp/MainActivity.kt +++ b/app/src/main/java/com/acuant/sampleapp/MainActivity.kt @@ -567,6 +567,7 @@ class MainActivity : AppCompatActivity(), AdapterView.OnItemSelectedListener, IP confirmNFCDataActivity.putExtra("DOE", result.passportExpiration) confirmNFCDataActivity.putExtra("DOCNUMBER", result.passportNumber) confirmNFCDataActivity.putExtra("COUNTRY", result.country) + confirmNFCDataActivity.putExtra("THREELINE", result.threeLineMrz) this.startActivity(confirmNFCDataActivity) } diff --git a/app/src/main/java/com/acuant/sampleapp/NfcConfirmationActivity.kt b/app/src/main/java/com/acuant/sampleapp/NfcConfirmationActivity.kt index 0f2df79..0d628d7 100644 --- a/app/src/main/java/com/acuant/sampleapp/NfcConfirmationActivity.kt +++ b/app/src/main/java/com/acuant/sampleapp/NfcConfirmationActivity.kt @@ -49,6 +49,7 @@ class NfcConfirmationActivity : AppCompatActivity(), NfcTagReadingListener { private var documentNumber: String? = null private var dob: String? = null private var doe: String? = null + private var threeLine: Boolean = false private var error: Boolean = true private fun setProgress(visible : Boolean, state : HelpState = HelpState.Locate, text : String = "") { @@ -123,13 +124,14 @@ class NfcConfirmationActivity : AppCompatActivity(), NfcTagReadingListener { documentNumber = intent.getStringExtra("DOCNUMBER") dob = intent.getStringExtra("DOB") doe = intent.getStringExtra("DOE") + threeLine = intent.getBooleanExtra("THREELINE", false) mrzDocNumber = findViewById(R.id.mrzDocumentNumber) mrzDOB = findViewById(R.id.mrzDOB) mrzDOE = findViewById(R.id.mrzDOE) locationText = findViewById(R.id.mrzInstruction2) - if(!position.equals("unknown", true) && position != "") { + if(!position.equals("unknown", true) && position != "" && !threeLine) { locationText.text = "Note: For $country passports, the eChip is typically on the $position" } else { locationText.text = "" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f91d700..298a4c4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -129,7 +129,7 @@ Verify captured data and tap &startEchip; Photo of the person obtained from chip Photo of signature obtained from passport chip - Read Passport MRZ + Read MRZ Ensure sufficient lighting with no reflection or glare on the passport. Tap anywhere to continue