고급 NFC 개요

이 문서에서는 다양한 태그 기술 사용, NFC 태그에 쓰기, 포그라운드 디스패치를 통해 포그라운드에 있는 애플리케이션이 인텐트를 처리할 수 없습니다.

지원되는 태그 기술 사용

NFC 태그 및 Android 지원 기기로 작업할 때 읽는 데 사용하는 기본 형식은 태그에 쓰기 데이터는 NDEF입니다. 기기가 NDEF 데이터로 태그를 스캔할 때 Android에서 지원을 제공합니다. NdefMessage에서 메시지를 파싱하여 전달합니다. 있습니다. 하지만 태그가 포함되지 않은 태그를 검사할 때 NDEF 데이터 또는 NDEF 데이터를 MIME 유형 또는 URI에 매핑할 수 없는 경우. 이 경우 태그와 직접 통신을 시작하고 자체 프로토콜 (원시 바이트) Android는 android.nfc.tech 패키지(표 1에 설명되어 있음) 다음과 같은 작업을 할 수 있습니다. getTechList() 메서드를 사용하여 기술을 결정합니다. 태그에서 지원하고 해당 TagTechnology를 만듭니다. android.nfc.tech에서 제공한 클래스 중 하나가 있는 객체

표 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 다음과 같이 형식이 지정된 NFC 태그 작업 및 NDEF 데이터에 대한 액세스를 제공합니다. NDEF.
NdefFormatable NDEF 형식일 수 있는 태그의 형식 작업을 제공합니다.

다음 태그 기술은 Android 지원 기기에서 반드시 지원되지는 않습니다.

표 2. 지원되는 태그 기술(선택사항)

클래스 설명
MifareClassic MIFARE Classic 속성 및 I/O 작업에 대한 액세스를 제공합니다(이 Android 기기의 경우). MIFARE를 지원합니다.
MifareUltralight MIFARE Ultralight 속성 및 I/O 작업(이 Android의 경우)에 대한 액세스를 제공합니다. 기기는 MIFARE를 지원합니다.

태그 기술 및 ACTION_TECH_DISCOVERED 인텐트 사용

기기가 NDEF 데이터가 있지만 MIME 또는 URI에 매핑할 수 없는 태그를 검사하는 경우 태그 디스패치 시스템은 ACTION_TECH_DISCOVERED로 활동을 시작하려고 합니다. 인텐트를 지정할 수 있습니다. ACTION_TECH_DISCOVERED는 태그가 스캔합니다. 이 대체를 사용하면 태그의 데이터로 작업할 수 있습니다. 태그 디스패치 시스템에서 파싱할 수 없는 경우 직접 수정할 수 있습니다. GCP로 작업할 때의 기본 단계는 태그 기술은 다음과 같습니다.

  1. 다음을 지정하는 ACTION_TECH_DISCOVERED 인텐트 필터링: 태그 기술을 지정합니다. NFC 필터링 인텐트를 참조하세요. 일반적으로 태그 디스패치 시스템은 NDEF 메시지가 표시될 때 ACTION_TECH_DISCOVERED 인텐트를 시작하려고 시도합니다. MIME 유형 또는 URI에 매핑할 수 없거나 스캔된 태그에 NDEF 데이터가 포함되지 않은 경우. 대상 자세한 내용은 태그 디스패치 시스템을 참고하세요.
  2. 애플리케이션이 인텐트를 수신하면 다음에서 Tag 객체를 가져옵니다. 인텐트:

    Kotlin

    var tagFromIntent: Tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
    

    자바

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    
  3. 다음 중 하나를 호출하여 TagTechnology의 인스턴스를 가져옵니다. android.nfc.tech 패키지에 있는 클래스의 get 팩토리 메서드 다음과 같은 작업을 할 수 있습니다. 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;
    }
}

포그라운드 디스패치 시스템 사용

포그라운드 디스패치 시스템을 통해 활동이 인텐트를 가로채고 같은 인텐트를 처리하는 다른 활동보다 우선 순위가 높습니다. 이 시스템을 사용할 때는 다음이 포함됩니다. 몇 가지 데이터 구조를 구성해야 합니다. 인텐트를 애플리케이션에 추가합니다. 포그라운드 디스패치 시스템을 사용하려면 다음 단계를 따르세요.

  1. 활동의 onCreate() 메서드에 다음 코드를 추가합니다. <ph type="x-smartling-placeholder">
      </ph>
    1. Android 시스템에서 채울 수 있도록 변경 가능한 PendingIntent 객체를 만듭니다. 태그의 세부정보가 함께 표시됩니다.

      Kotlin

      val intent = Intent(this, javaClass).apply {
          addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
      }
      var pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent,
              PendingIntent.FLAG_MUTABLE)
      

      자바

      PendingIntent pendingIntent = PendingIntent.getActivity(
          this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
          PendingIntent.FLAG_MUTABLE);
      
    2. 가로챌 인텐트를 처리하기 위해 인텐트 필터를 선언합니다. 포그라운드 디스패치 시스템은 지정된 인텐트 필터를 기기가 태그를 스캔합니다. 일치하는 경우 애플리케이션이 인텐트를 처리합니다. 포함된 경우 일치하지 않으면 포그라운드 디스패치 시스템이 인텐트 디스패치 시스템으로 대체됩니다. 인텐트 필터와 기술 필터의 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, };
      
    3. 애플리케이션에서 처리할 태그 기술의 배열을 설정합니다. 먼저 Object.class.getName() 메서드를 사용하여 개발자가 필요로 하는 기술의 클래스를 가져올 수 있습니다. 도움이 될 수 있습니다

      Kotlin

      techListsArray = arrayOf(arrayOf<String>(NfcF::class.java.name))
      

      자바

      techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
      
  2. 다음 활동 수명 주기 콜백을 재정의하고 활동이 손실될 때 포그라운드 전달 (onPause()) (onResume()) 다시 초점을 맞춥니다. enableForegroundDispatch()는 다음에서 호출해야 합니다. 활동이 포그라운드에 있는 경우에만 기본 스레드에 있을 수 있습니다 (onResume()에서 호출하면 보장됨). 스캔된 NFC의 데이터를 처리하려면 onNewIntent 콜백도 구현해야 합니다. 태그 사이에 있어야 합니다.
  3. 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
    }
    

    Java

    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
    }