NEWSMRZ Scanner is now part of barKoder.What it means for you →

DOCUMENTATION

Step-by-step instructions for how to add NFC to your app.

MRZ Scanner 1.x (archive)

Documentation / MRZ Scanner 1.x (archive)

In this article, you will find step-by-step instructions for how to add NFC to your app

 

 

 

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

 

Updated Oct 24, 2026 · Questions? Ask us