반응형

NFC Tag에서 얻을 수 있는 정보를 json 문자열 포맷으로 반환하는 함수를 만들어보았다.

테그 정보 :

  1. UID (고유 ID): tag.id에서 추출한 고유 식별자.
  2. Tech List: 태그가 지원하는 모든 기술 목록 (tag.techList).
  3. NfcA (ISO 14443-3A): ATQA, SAK, 최대 전송 길이, 타임아웃 정보.
  4. IsoDep (ISO 14443-4): 역사적 바이트(historicalBytes), 고층 응답(hiLayerResponse), 최대 전송 길이, 타임아웃 정보.
  5. NfcB (ISO 14443-3B): 응용 데이터, 프로토콜 정보, 최대 전송 길이.
  6. NfcF (Felica): 제조사 정보, 시스템 코드, 최대 전송 길이, 타임아웃.
  7. NfcV (ISO 15693): 응답 플래그, DSFID, 최대 전송 길이.
  8. MifareClassic: 타입, 크기, 섹터 블록 .
  9. MifareUltralight: 타입 정보 (Ultralight, Ultralight C).

 

구현 함수는 다음과 같다.

fun readTagDetailsAsJson(tag: Tag): String {
    val tagInfo = mutableMapOf<String, Any>()

    // UID 정보 (태그 고유 ID)
    tagInfo["uid"] = tag.id.joinToString("") { String.format("%02X", it) }

    // 기술 스택 나열 (태그가 지원하는 모든 기술들)
    tagInfo["techList"] = tag.techList.joinToString()

    // NfcA (ISO 14443-3A) 정보
    val nfcA = NfcA.get(tag)
    if (nfcA != null) {
        tagInfo["NfcA"] = mapOf(
            // ATQA: Answer to Request Type A. 태그가 리더기에 응답할 때 사용하는 정보
            "atqa" to nfcA.atqa.joinToString("") { String.format("%02X", it) },
            // SAK: Select Acknowledge. 태그가 리더기에 제공하는 지원 기능 정보
            "sak" to String.format("%02X", nfcA.sak),
            // 한 번에 보낼 수 있는 최대 전송 길이 (바이트 단위)
            "maxTransceiveLength" to nfcA.maxTransceiveLength,
            // 통신 타임아웃 시간 (밀리초 단위)
            "timeout" to nfcA.timeout
        )
    }

    // IsoDep (ISO 14443-4) 정보
    val isoDep = IsoDep.get(tag)
    if (isoDep != null) {
        tagInfo["IsoDep"] = mapOf(
            // Historical Bytes: 태그가 초기 통신 설정 시 리더기에 제공하는 추가 정보
            "historicalBytes" to (isoDep.historicalBytes?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // Higher Layer Response: 고급 프로토콜에 대한 응답 정보
            "hiLayerResponse" to (isoDep.hiLayerResponse?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // 한 번에 전송할 수 있는 최대 데이터 길이 (바이트 단위)
            "maxTransceiveLength" to (isoDep.maxTransceiveLength.toString() ?: "N/A"),
            // 통신 타임아웃 시간 (밀리초 단위)
            "timeout" to isoDep.timeout
        )
    }

    // NfcB (ISO 14443-3B) 정보
    val nfcB = NfcB.get(tag)
    if (nfcB != null) {
        tagInfo["NfcB"] = mapOf(
            // Application Data: 태그의 애플리케이션과 관련된 데이터
            "applicationData" to (nfcB.applicationData?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // Protocol Info: 태그가 제공하는 프로토콜 정보
            "protocolInfo" to (nfcB.protocolInfo?.joinToString("") { String.format("%02X", it) } ?: "N/A")
        )
    }

    // NfcF (Felica, JIS 6319-4) 정보
    val nfcF = NfcF.get(tag)
    if (nfcF != null) {
        tagInfo["NfcF"] = mapOf(
            // 제조사 코드
            "manufacturer" to (nfcF.manufacturer?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // 시스템 코드
            "systemCode" to (nfcF.systemCode?.joinToString("") { String.format("%02X", it) } ?: "N/A"),
            // 한 번에 전송할 수 있는 최대 데이터 길이 (바이트 단위)
            "maxTransceiveLength" to nfcF.maxTransceiveLength.toString(),
            // 통신 타임아웃 시간 (밀리초 단위)
            "timeout" to nfcF.timeout.toString()
        )
    }

    // NfcV (ISO 15693) 정보
    val nfcV = NfcV.get(tag)
    if (nfcV != null) {
        tagInfo["NfcV"] = mapOf(
            // 응답 플래그
            "responseFlags" to String.format("%02X", nfcV.responseFlags),
            // DSFID (Data Storage Format Identifier)
            "dsfId" to String.format("%02X", nfcV.dsfId),
            // 한 번에 전송할 수 있는 최대 데이터 길이 (바이트 단위)
            "maxTransceiveLength" to nfcV.maxTransceiveLength
        )
    }

    // NfcBarcode (Type V or JIS 6319-4) 정보 - maxTransceiveLength 지원 없음
    val nfcBarcode = NfcBarcode.get(tag)
    if (nfcBarcode != null) {
        tagInfo["NfcBarcode"] = mapOf(
            // 바코드 타입 정보 (Type V or JIS 6319-4)
            "type" to nfcBarcode.type
        )
    }

    // MifareClassic 정보
    val mifareClassic = MifareClassic.get(tag)
    if (mifareClassic != null) {
        tagInfo["MifareClassic"] = mapOf(
            // MifareClassic 타입 (Classic, Plus, Pro)
            "type" to when (mifareClassic.type) {
                MifareClassic.TYPE_CLASSIC -> "Classic"
                MifareClassic.TYPE_PLUS -> "Plus"
                MifareClassic.TYPE_PRO -> "Pro"
                else -> "Unknown"
            },
            // MifareClassic 메모리 크기
            "size" to mifareClassic.size,
            // 섹터 개수
            "sectorCount" to mifareClassic.sectorCount,
            // 블록 개수
            "blockCount" to mifareClassic.blockCount
        )
    }

    // MifareUltralight 정보
    val mifareUltralight = MifareUltralight.get(tag)
    if (mifareUltralight != null) {
        tagInfo["MifareUltralight"] = mapOf(
            // MifareUltralight 타입 (Ultralight, Ultralight C)
            "type" to when (mifareUltralight.type) {
                MifareUltralight.TYPE_ULTRALIGHT -> "Ultralight"
                MifareUltralight.TYPE_ULTRALIGHT_C -> "Ultralight C"
                else -> "Unknown"
            }
        )
    }

    // JSON 형태로 변환하여 반환
    return JSONObject(tagInfo as Map<*, *>).toString()
}

 

결과값 로그 출력 값은 아래와 같다.

로그 출력 값 예 :
{
  "uid": "641B27A2B67881",  // 시리얼 번호
  "techList": "android.nfc.tech.IsoDep, android.nfc.tech.NfcA", // 태그에서 지원하는 NFC 기술 목록
  "NfcA": {		// NfcA (ISO/IEC 14443-3A) 기술에 대한 정보
    "atqa": "4800",		// Answer to Request, Type A (ATQA) 값
    "sak": "20",		// Select Acknowledge (SAK) 값
    "maxTransceiveLength": 253,	// NFC 통신에서 한 번에 전송할 수 있는 최대 데이터 길이(바이트)
    "timeout": 618		// 통신 타임아웃 시간(밀리초)
  },
  "IsoDep": {	// IsoDep (ISO/IEC 14443-4) 기술에 대한 정보
    "historicalBytes": "",	// NFC 태그가 최초로 통신을 시작할 때 제공하는 부가적인 정보를 포함
    "hiLayerResponse": "N\/A",	// 태그가 고급 프로토콜을 지원하는 경우 제공
    "maxTransceiveLength": "65279",// IsoDep에서 한 번에 전송할 수 있는 최대 데이터 길이
    "timeout": 618		// 통신 타임아웃 시간(밀리초)
  }
}

 

 

반응형

'개발 > Android' 카테고리의 다른 글

NFC 권한설정  (1) 2024.10.21
NdefFormatable 태그  (0) 2024.10.21
안드로이드 각 버전별 추가된 주요 기능  (0) 2024.10.15
JIT, AOT 컴파일 비교  (1) 2024.10.15
FCM 푸시설정  (0) 2024.10.14
블로그 이미지

SKY STORY

,