이 문서에서는 다양한 태그 기술을 사용한 작업, NFC 태그에 쓰기 및 포그라운드 디스패치(다른 애플리케이션이 인텐트를 필터링하더라도 포그라운드 애플리케이션이 동일한 인텐트를 처리할 수 있음)와 같은 고급 NFC 주제에 대해 설명합니다.
지원되는 태그 기술 사용
NFC 태그 및 Android 구동 기기로 작업하는 경우 태그에서 데이터를 읽고 쓰는 데 사용하는 기본 형식은 NDEF입니다. 기기가 NDEF 데이터로 태그를 검사하면 Android는 메시지를 파싱하고 가능한 경우 NdefMessage
에 전달하도록 지원합니다. 그러나 NDEF 데이터가 포함되지 않은 태그를 검사하거나 NDEF 데이터를 MIME 유형 또는 URI에 매핑할 수 없는 경우도 있습니다.
이러한 경우에는 태그와 직접 통신하여 자신의 프로토콜(원시 바이트)로 읽고 쓸 수 있어야 합니다. Android는 android.nfc.tech
패키지로 이러한 사용 사례의 일반적인 지원을 제공합니다(표 1에서 설명). getTechList()
메서드를 사용하여 태그에서 지원하는 기술을 확인하고, android.nfc.tech
에서 제공하는 클래스 중 하나를 사용하여 해당하는 TagTechnology
객체를 만들 수 있습니다.
표 1. 지원되는 태그 기술
클래스 | 설명 |
---|---|
TagTechnology |
모든 태그 기술 클래스가 구현해야 하는 인터페이스. |
NfcA |
NFC-A(ISO 14443-3A) 속성 및 I/O 작업에 액세스하도록 지원합니다. |
NfcB |
NFC-B(ISO 14443-3B) 속성 및 I/O 작업에 액세스하도록 지원합니다. |
NfcF |
NFC-F 속성(JIS 6319-4) 및 I/O 작업에 액세스하도록 지원합니다. |
NfcV |
NFC-V(ISO 15693) 속성 및 I/O 작업에 액세스하도록 지원합니다. |
IsoDep |
ISO-DEP(ISO 14443-4) 속성 및 I/O 작업에 액세스하도록 지원합니다. |
Ndef |
NDEF로 형식이 지정된 NFC 태그에서 NDEF 데이터 및 작업에 액세스하도록 지원합니다. |
NdefFormatable |
NDEF 형식일 수 있는 태그의 형식 작업을 제공합니다. |
다음 태그 기술은 Android 구동 기기에서 지원되지 않아도 됩니다.
표 2. 지원되는 태그 기술(선택사항)
클래스 | 설명 |
---|---|
MifareClassic |
이 Android 기기가 MIFARE를 지원하는 경우 MIFARE Classic 속성 및 I/O 작업에 액세스하도록 지원합니다. |
MifareUltralight |
이 Android 기기가 MIFARE를 지원하는 경우 MIFARE Ultralight 속성 및 I/O 작업에 액세스하도록 지원합니다. |
태그 기술 및 ACTION_TECH_DISCOVERED 인텐트 사용
NDEF 데이터가 있지만 MIME 또는 URI에 매핑할 수 없는 태그를 기기에서 검사할 경우 태그 디스패치 시스템은 ACTION_TECH_DISCOVERED
인텐트로 활동을 시작하려고 시도합니다. ACTION_TECH_DISCOVERED
는 비 NDEF 데이터가 있는 태그를 검사할 경우에도 사용됩니다. 이 대체를 사용하면 태그 디스패치 시스템에서 태그를 파싱할 수 없는 경우 태그의 데이터로 직접 작업할 수 있습니다. 태그 기술로 작업할 경우 기본 단계는 다음과 같습니다.
- 처리할 태그 기술을 지정하는
ACTION_TECH_DISCOVERED
인텐트를 필터링합니다. 자세한 내용은 NFC 인텐트 필터링을 참조하세요. NDEF 메시지를 MIME 유형 또는 URI에 매핑할 수 없거나 검사한 태그에 NDEF 데이터가 포함되지 않은 경우 일반적으로 태그 디스패치 시스템은ACTION_TECH_DISCOVERED
인텐트를 시작하려고 시도합니다. 자세한 내용은 태그 디스패치 시스템을 참조하세요. - 애플리케이션이 인텐트를 수신하면 인텐트에서
Tag
객체를 가져옵니다.Kotlin
var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
자바
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
android.nfc.tech
패키지에서 클래스의get
팩토리 메서드 중 하나를 호출하여TagTechnology
의 인스턴스를 가져옵니다.get
팩토리 메서드를 호출하기 전에getTechList()
를 호출하여 지원되는 태그의 기술을 열거할 수 있습니다. 예를 들어Tag
에서MifareUltralight
의 인스턴스를 가져오려면 다음과 같이 하세요.Kotlin
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
자바
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
태그 읽기 및 쓰기
NFC 태그를 읽고 쓰려면 인텐트에서 태그를 가져오고 태그와의 통신을 시작해야 합니다. 태그에서 데이터를 읽고 쓰려면 자체 프로토콜 스택을 정의해야 합니다. 하지만 태그로 직접 작업할 경우 여전히 NDEF 데이터를 읽고 쓸 수 있습니다. 구성 방식은 각자 선택할 수 있습니다. 다음 예는 MIFARE Ultralight 태그의 사용 방법을 보여줍니다.
Kotlin
package com.example.android.nfc import android.nfc.Tag import android.nfc.tech.MifareUltralight import java.io.IOException import java.nio.charset.Charset class MifareUltralightTagTester { fun writeTag(tag: Tag, tagText: String) { MifareUltralight.get(tag)?.use { ultralight -> ultralight.connect() Charset.forName("US-ASCII").also { usAscii -> ultralight.writePage(4, "abcd".toByteArray(usAscii)) ultralight.writePage(5, "efgh".toByteArray(usAscii)) ultralight.writePage(6, "ijkl".toByteArray(usAscii)) ultralight.writePage(7, "mnop".toByteArray(usAscii)) } } fun readTag(tag: Tag): String? { return MifareUltralight.get(tag)?.use { mifare -> mifare.connect() val payload = mifare.readPages(4) String(payload, Charset.forName("US-ASCII")) } } } }
자바
package com.example.android.nfc; import android.nfc.Tag; import android.nfc.tech.MifareUltralight; import android.util.Log; import java.io.IOException; import java.nio.charset.Charset; public class MifareUltralightTagTester { private static final String TAG = MifareUltralightTagTester.class.getSimpleName(); public void writeTag(Tag tag, String tagText) { MifareUltralight ultralight = MifareUltralight.get(tag); try { ultralight.connect(); ultralight.writePage(4, "abcd".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(5, "efgh".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(6, "ijkl".getBytes(Charset.forName("US-ASCII"))); ultralight.writePage(7, "mnop".getBytes(Charset.forName("US-ASCII"))); } catch (IOException e) { Log.e(TAG, "IOException while writing MifareUltralight...", e); } finally { try { ultralight.close(); } catch (IOException e) { Log.e(TAG, "IOException while closing MifareUltralight...", e); } } } public String readTag(Tag tag) { MifareUltralight mifare = MifareUltralight.get(tag); try { mifare.connect(); byte[] payload = mifare.readPages(4); return new String(payload, Charset.forName("US-ASCII")); } catch (IOException e) { Log.e(TAG, "IOException while reading MifareUltralight message...", e); } finally { if (mifare != null) { try { mifare.close(); } catch (IOException e) { Log.e(TAG, "Error closing tag...", e); } } } return null; } }
포그라운드 디스패치 시스템 사용
포그라운드 디스패치 시스템에서는 활동이 인텐트를 가로채고 동일한 인텐트를 처리하는 다른 활동보다 우선순위가 있음을 주장할 수 있습니다. 이 시스템을 사용하려면 애플리케이션에 적절한 인텐트를 보낼 수 있도록 Android 시스템용으로 몇 가지 데이터 구조를 구축해야 합니다. 포그라운드 디스패치 시스템을 사용하려면 다음 단계를 따르세요.
- 활동의
onCreate()
메서드에서 다음 코드를 추가합니다.- 태그 검사 시 Android 시스템이 태그의 세부정보를 채울 수 있도록
PendingIntent
객체를 만듭니다.Kotlin
val intent = Intent(this, javaClass).apply { addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) } var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
자바
PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
- 가로챌 인텐트를 처리하기 위해 인텐트 필터를 선언합니다. 포그라운드 디스패치 시스템은 기기가 태그를 검사할 때 받는 인텐트를 사용하여 지정된 인텐트 필터를 확인합니다. 일치하는 경우 애플리케이션이 인텐트를 처리합니다. 일치하지 않는 경우 포그라운드 디스패치 시스템이 인텐트 디스패치 시스템으로 대체됩니다.
인텐트 필터 및 기술 필터의
null
배열을 지정하면TAG_DISCOVERED
인텐트로 대체되는 모든 태그를 필터링하게 됩니다. 아래의 코드 스니펫은NDEF_DISCOVERED
의 모든 MIME 유형을 처리합니다. 필요한 항목만 처리해야 합니다.Kotlin
val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply { try { addDataType("*/*") /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (e: IntentFilter.MalformedMimeTypeException) { throw RuntimeException("fail", e) } } intentFiltersArray = arrayOf(ndef)
자바
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndef.addDataType("*/*"); /* Handles all MIME based dispatches. You should specify only the ones that you need. */ } catch (MalformedMimeTypeException e) { throw new RuntimeException("fail", e); } intentFiltersArray = new IntentFilter[] {ndef, };
- 애플리케이션에서 처리할 태그 기술의 배열을 설정합니다. 지원할 기술 클래스를 가져오려면
Object.class.getName()
메서드를 호출합니다.Kotlin
techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
자바
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
- 태그 검사 시 Android 시스템이 태그의 세부정보를 채울 수 있도록
- 다음 활동 수명 주기 콜백을 재정의하고, 활동이 포커스를 잃고(
onPause()
) 다시 얻을 때(onResume()
) 포그라운드 디스패치를 사용 설정 및 사용 중지할 로직을 추가합니다.enableForegroundDispatch()
는 기본 스레드에서 호출해야 하며, 활동이 포그라운드에 있을 경우에만(onResume()
에서 호출 시 보장됨) 호출해야 합니다. 검사된 NFC 태그에서 데이터를 처리하려면onNewIntent
콜백도 구현해야 합니다.
Kotlin
public override fun onPause() { super.onPause() adapter.disableForegroundDispatch(this) } public override fun onResume() { super.onResume() adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray) } public override fun onNewIntent(intent: Intent) { val tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG) //do something with tagFromIntent }
자바
public void onPause() { super.onPause(); adapter.disableForegroundDispatch(this); } public void onResume() { super.onResume(); adapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray); } public void onNewIntent(Intent intent) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); //do something with tagFromIntent }
전체 샘플은 API 데모의 ForegroundDispatch 샘플을 참조하세요.