Posted on: Thursday, 12 September 2019
1. Please add permissions in AndoidManifest.xml
<uses-permission android:name="android.permission.NFC" />
2. Add the implementation in Build.Gradle(module:app) -
implementation 'org.jmrtd:jmrtd:0.5.5'
implementation 'edu.ucar:jj2000:5.2'
implementation 'com.github.mhshams:jnbis:1.1.0'
implementation 'net.sf.scuba:scuba-sc-android:0.0.9'
implementation 'com.madgag.spongycastle:prov:1.54.0.0'
implementation 'androidx.multidex:multidex:2.0.1'
JMRTD: An Open Source Java Implementation of Machine Readable Travel Documents, JMRTD is an open source Java implementation of the Machine Readable Travel Document(MRTD) standards as specified by the International Civil Aviation Organization (ICAO). The electronic passport (or "ePassport"), which by now has been introduced in many countries, is an implementation of these standards.
3. Use this function in ScannerActivity onResume
private fun enableNfcForegroundDispatch() {
if (scannerType == ScannerType.SCANNER_TYPE_MRZ) {
val adapter = NfcAdapter.getDefaultAdapter(this)
if (adapter != null) {
val intent = Intent(applicationContext, ScannerActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
var pendingIntentFlag = PendingIntent.FLAG_UPDATE_CURRENT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
pendingIntentFlag = pendingIntentFlag or PendingIntent.FLAG_MUTABLE
val pendingIntent = PendingIntent.getActivity(this, 0, intent, pendingIntentFlag)
val filter = arrayOf(arrayOf("android.nfc.tech.IsoDep"))
adapter.enableForegroundDispatch(this, pendingIntent, null, filter)
}
}
}
4. Create class NFCResultModel
class NFCResultModel {
var givenNames: String? = null
var surnames: String? = null
var gender: String? = null
var issuingCountry: String? = null
var nationality: String? = null
var portrait: Bitmap? = null
var fullNameNFC: String? = null
var address: String? = null
var placeOfBirth: String? = null
}
5. In the next step, please create the function performReadNFC into the ScannerActivity.
private fun performReadNFC(isoDep: IsoDep, bacKey: BACKeySpec): NFCResultModel? {
val nfcResultModel = NFCResultModel()
try {
val cardService = CardService.getInstance(isoDep)
cardService.open()
val service = PassportService(cardService)
service.open()
var paceSucceeded = false
try {
val cardAccessFile = CardAccessFile(service.getInputStream(PassportService.EF_CARD_ACCESS))
val paceInfos = cardAccessFile.paceInfos
paceSucceeded = if (paceInfos != null && paceInfos.isNotEmpty()) {
val paceInfo = paceInfos.iterator().next()
service.doPACE(bacKey, paceInfo.objectIdentifier, PACEInfo.toParameterSpec(paceInfo.parameterId))
true
} else {
true
}
} catch (e: Exception) {
}
service.sendSelectApplet(paceSucceeded)
if (!paceSucceeded) {
try {
service.getInputStream(PassportService.EF_COM).read()
} catch (e: Exception) {
service.doBAC(bacKey)
}
}
val lds = LDS()
try {
val dg11In = service.getInputStream(PassportService.EF_DG11)
lds.add(PassportService.EF_DG11, dg11In, dg11In.length)
val dg11File = lds.dG11File
nfcResultModel.fullNameNFC = dg11File.nameOfHolder
nfcResultModel.address = dg11File.permanentAddress?.joinToString { it }
nfcResultModel.placeOfBirth = dg11File.placeOfBirth?.joinToString { it }
} catch (e: CardServiceException) {
}
val dg1In = service.getInputStream(PassportService.EF_DG1)
lds.add(PassportService.EF_DG1, dg1In, dg1In.length)
val dg1File = lds.dG1File
val dg2In = service.getInputStream(PassportService.EF_DG2)
lds.add(PassportService.EF_DG2, dg2In, dg2In.length)
val dg2File = lds.dG2File
val allFaceImageInfos: MutableList<FaceImageInfo> = ArrayList()
val faceInfos = dg2File!!.faceInfos
for (faceInfo in faceInfos) {
allFaceImageInfos.addAll(faceInfo.faceImageInfos)
}
if (allFaceImageInfos.isNotEmpty()) {
val faceImageInfo = allFaceImageInfos.iterator().next()
val imageLength = faceImageInfo.imageLength
val dataInputStream = DataInputStream(faceImageInfo.imageInputStream)
val buffer = ByteArray(imageLength)
dataInputStream.readFully(buffer, 0, imageLength)
val inputStream: InputStream = ByteArrayInputStream(buffer, 0, imageLength)
nfcResultModel.portrait = ImageUtil.decodeImage(context, faceImageInfo.mimeType, inputStream)
}
val mrzInfo = dg1File?.mrzInfo
nfcResultModel.givenNames = mrzInfo?.secondaryIdentifier?.replace("<", "")
nfcResultModel.surnames = mrzInfo?.primaryIdentifier?.replace("<", "")
nfcResultModel.gender = mrzInfo?.gender.toString()
nfcResultModel.issuingCountry = mrzInfo?.issuingState?.replace("<", "")
nfcResultModel.nationality = mrzInfo?.nationality?.replace("<", "")
} catch (e: Exception) {
return null
}
return nfcResultModel
}
6. Make these variables
val tag = intent.extras?.getParcelable<Tag>(NfcAdapter.EXTRA_TAG)
val isoDep = IsoDep.get(tag)
val bacKey: BACKeySpec = BACKey(resultModel!!.documentNumber, resultModel!!.expirationDateRaw,resultModel!!.dobRaw)
val NFCResult = performReadNFC(isoDep, bacKey)
7. var Name = NFCResult?.fullNameNFC