Skip to content

Commit

Permalink
Read mifare card data
Browse files Browse the repository at this point in the history
  • Loading branch information
andras-adam committed Oct 12, 2022
1 parent 900a045 commit c1394b2
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 6 deletions.
52 changes: 52 additions & 0 deletions app/src/main/java/com/virtualtag/app/data/MifareClassicHelper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.virtualtag.app.data

import android.nfc.tech.MifareClassic
import android.util.Log
import java.io.IOException

class MifareClassicHelper(tag: MifareClassic) {
val timeout: Int
val maxTransceiveLength: Int
val size: Int
val type: Int
val sectorCount: Int
val blockCount: Int
val data: String

init {
timeout = tag.timeout
maxTransceiveLength = tag.maxTransceiveLength
size = tag.size
type = tag.type
sectorCount = tag.sectorCount
blockCount = tag.blockCount
data = readData(tag)
}

private fun readData(tag: MifareClassic): String {
try {
var dataAccumulator = ""
// Connect to the tag
tag.connect()
// Loop through sectors on the tag
for (currentSector in 0 until tag.sectorCount) {
// Authenticate sector with the default key
val auth = tag.authenticateSectorWithKeyA(currentSector, MifareClassic.KEY_DEFAULT)
if (!auth) throw IOException("Failed to authenticate sector")
// Get block count in sector
val sectorBlockCount = tag.getBlockCountInSector(currentSector)
// Loop through blocks in the sector
for (currentBlockInSector in 0 until sectorBlockCount) {
// Calculate the block's index
val blockIndex = tag.sectorToBlock(currentSector) + currentBlockInSector
// Read the block's data and store as HEX
dataAccumulator += tag.readBlock(blockIndex).toHex()
}
}
return dataAccumulator
} catch (e: IOException) {
e.localizedMessage?.let { Log.e("MifareClassicHelper", it) }
return ""
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.virtualtag.app.data

import android.nfc.tech.MifareUltralight
import android.util.Log
import java.io.IOException

class MifareUltralightHelper(tag: MifareUltralight) {
val type: Int
val timeout: Int
val maxTransceiveLength: Int
val data: String

init {
type = tag.type
timeout = tag.timeout
maxTransceiveLength = tag.maxTransceiveLength
data = readData(tag)
}

private fun readData(tag: MifareUltralight): String {
try {
var dataAccumulator = ""
// Connect to the tag
tag.connect()
// Get the number of readable pages
val readablePagesCount = when (type) {
// Ultralight has 16 pages, all readable
MifareUltralight.TYPE_ULTRALIGHT -> 16
// Ultralight C has 48 pages, but the last 4 are unreadable
MifareUltralight.TYPE_ULTRALIGHT_C -> 44
else -> 0
}
// Read every fourth page, as 4 pages are read at a time by `readPages()`
for (currentPage in 0..readablePagesCount) {
if (currentPage % 4 == 0) dataAccumulator += tag.readPages(currentPage).toHex()
}
return dataAccumulator
} catch (e: IOException) {
e.localizedMessage?.let { Log.e("MifareUltralightHelper", it) }
return ""
}
}
}
20 changes: 14 additions & 6 deletions app/src/main/java/com/virtualtag/app/data/ScanningViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.MifareClassic
import android.nfc.tech.MifareUltralight
import android.nfc.tech.NdefFormatable
import android.nfc.tech.NfcA
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import java.io.IOException

// Byte array to HEX helper
fun ByteArray.toHex(): String = joinToString(separator = "") { "%02x".format(it) }
Expand All @@ -40,11 +40,8 @@ class ScanningViewModel : ViewModel() {
val intentFilter = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
val intentFiltersArray = arrayOf(intentFilter)
val techListsArray = arrayOf(
arrayOf(
NfcA::class.java.name,
MifareUltralight::class.java.name,
NdefFormatable::class.java.name
)
arrayOf(MifareClassic::class.java.name),
arrayOf(MifareUltralight::class.java.name),
)
// Enable foreground dispatch
adapter.enableForegroundDispatch(
Expand Down Expand Up @@ -75,6 +72,17 @@ class ScanningViewModel : ViewModel() {
val tag: Tag? = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
Log.i("NFC", "scanned ${tag?.id?.toHex()}")
_scannedTag.value = tag
//
if (tag?.techList?.contains(MifareClassic::class.java.name) == true) {
val mfc = MifareClassic.get(scannedTag.value)
val data = MifareClassicHelper(mfc)
Log.d("MFC", data.data)
}
if (tag?.techList?.contains(MifareUltralight::class.java.name) == true) {
val mfu = MifareUltralight.get(scannedTag.value)
val data = MifareUltralightHelper(mfu)
Log.d("MFU", data.data)
}
}
}
}

0 comments on commit c1394b2

Please sign in to comment.