역시 출처는 하드로이드 블로그 ㅜㅜ

http://hardroid.net/profiles/blogs/advanced-nfc


이 문서는 다양한 태그 기술들과 동작하기, NFC 태그들에 쓰기, 포그라운드 디스패칭(foreground dispatching:같은 유형에 대해 다른 앱이 필터가 되어도 포그라운드에 있는 앱이 인텐트들을 핸들링하도록 처리하는 것) 등 추가적인 NFC 토픽을 설명하고 있다.

 

지원되는 태그 기술들과 동작

 

NFC 태그들과 안드로이드 장비간에 동작할 때 읽고 쓰는데 사용하는 주요 포맷은 NDEF 이다. NDEF 데이터가 태그로 부터 스캔될 때 안드로이드는 메시지를 파싱하여 가능한 NdefMessage로 제공한다. 그러나 NDEF 데이터가 포함되어져 있지 않은 태그를 스캔했거나 NDEF 데이터가 MIME 타입 혹은 URI로 매핑되지 않았을 때 태그로 부터 직접 통신하도록 오픈하여 당신의 프로토콜(raw bytes)로 읽고 써야 한다.

 

안드로이드는 이러한 경우를 위해 android.nfc.tech 패키지를 제공하며 패키지 안의 클래스는 Table 1에 설명하고 있다. 태그에 의해 지원되는 기술들은 getTechList()를 사용하여 확인할 수 있으며 이 메서드는 TagTechnology객체와 연관된 전체 이름들이 반환된다.

 

Table 1. 지원되는 태그 기술들
Class설명

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 data에 접근할 수 있도록 지원하고 NDEF 형식의 NFC tags와 연동할 수 있는 기능을 제공.

NdefFormatable

NDEF 형식으로 접근 가능한 태그들을 위한 정형화된 기능을 제공.

 

다음의 기술은 안드로이드에서 지원은 하지만 안드로이드 장비에서 반드시 지원할 필요는 없는 기술들이다.

 

Table 2. 옵션으로 지원되는 기술들
Class설명

MifareClassic

만약 안드로이드 장비가 MIFARE를 지원한다면 MIFARE Classic 프로퍼티들과 I/O 에 접근할 수 있는 기능을 제공.

MifareUltralight

만약 안드로이드 장비가 MIFARE를 지원한다면 MIFARE Ultralight 프로퍼티들과 I/O 에 접근할 수 있는 기능을 제공.

 

태그 기술들과 ACTION_TECH_DISCOVERED 인텐트를 사용하여 동작하기

 

장비가 NDEF 메시지를 스캔했지만 MIME 혹은 URI와 매핑되지 않거나 NDEF 메시지가 아닐 때 태그 디스패치 시스템ACTION_TECH_DISCOVERED인텐트와 함께 액티비티가 실행되도록 시도한다. 이렇게 파싱되지 않을 경우 직접 읽고 쓸 수 있도록  지원되는데 다음과 같은 단계로 태그 기술과 동작하면 된다.

 

  1. 먼저 동작을 하려면 ACTION_TECH_DISCOVERED 인텐트가 선언되어져 있어야 한다. 태그 디스패치 시스템은 이 인텐트 선언의 메타 데이터를 근거로 동작시킨다. 인텐트 선언에 대해서는 NFC Basic 의 "NFC 인텐트에 대한 필터링"을 참조하기 바란다.
  2. 앱이 인텐트로 부터 Tag 객체를 획득한다.

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
  3. android.nfc.tech 패키지의 클래스들에는 get 메서들이 있는데 이 메서드를 통해 TagTechnology 인스턴스를 획득한다. 어떤 TagTechnology의 클래스를 사용할 것인지를 확인하려면 get을 호출하기에 앞서 getTechList() 메서드를 통해 태그가 지원하는 기술들을 열람하여 확인할 수 있다. 다음은 Tag 객체로 부터 MifareUltralight (필립스 사의 마이페어 기술) 인스턴스를 획득하는 예제이다.

    MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));

 

태그에 읽고 쓰기

 

인텐트로부터 Tag객체를 획득한 후 Tag 객체를 통해 연관된 태그 기술의 인스턴스를 획득 한 후 통신을 열면 NFC 태그와 읽고 쓸 수 있다.
 

이를 통해 당신이 원하는 데이터 프로토콜로 읽고 쓸 수 있지만 될 수 있는 한 직접 태그와 통신을 열었을 때도 NDEF 데이터 형식으로 읽고 쓸 수 있다.

 

다음은 MIFARE Ultralight 태그에 당신이 원하는 구조로 데이터를 읽고 쓰는 작업의 예제이다.

 

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{

    privatestaticfinalString 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 closing 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 writing MifareUltralight message...", e);
        }finally{
            if(mifare != null){
               try{
                   mifare.close();
               }
               catch(IOException e){
                   Log.e(TAG,"Error closing tag...", e);
               }
            }
        }
        return null;
    }
}

 

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

 

포그라운드 디스패치 시스템은 같은 인텐트를 선언한 다른 액티비티의 우선순위를 무시하고 포그라운드 상태의 액티비티가 인텐트를 가로챌 수 있게 허락한다. 약간의 데이터 구조들이 안드로이드 시스템이 당신의 앱에게 검색된 인텐트들을 보낼 수 있도록 할 때 이 시스템이 사용된다. 포그라운드 디스패치 시스템을 활성화 하려면 

 

  1. 액티비티의 onCreate() 메서드에 다음의 코드를 추가한다.

    1. 안드로이드 시스템이 스캔된 태그의 세부사항을 채울 수 있도록 PendingIntent 객체를 생성한다.

    PendingIntent pendingIntent = PendingIntent.getActivity(
        this0new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

    2. 가로채어 처리하고 싶은 인텐트 필터를 선언한다.

    포그라운드 디스패치 시스템은 장비가 태그를 스캔할 때 수신하고 싶은 인텐트에 대한 인텐트 필터 선언을 체크한다. 만약 매칭이 되면 앱은 인텐트를 핸들링한다. 만약 매칭되지 않으면 포그라운드 디스패치 시스템은 인텐트 디스패치 시스템에게 제어를 양도한다.

    만약 TAG_DISCOVERED로 양도되는 모든 태그에 대해 필터링하고 싶다면 인텐트 필터와 기술 필터에 null 배열을 명시하면 된다.

    다음은 NDEF_DISCOVERED 에 대한 모든 MIME 타입들을 핸들링하도록 선언하는 예제이다. 당신은 핸들링하고자 한 타입만 선언하기 바란다.


    IntentFilter ndef =new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
    try{
        ndef.addDataType("*/*");    /* 모든 MIME을 전달받는다.
                                       당신은 오직 필요한 것만 설정하기 바란다. */

    }
    catch(MalformedMimeTypeException e){
        throw new RuntimeException("fail", e);
    }
    ntentFiltersArray = new IntentFilter[]{ndef,};

     

    3. 앱이 핸들링하고 싶은 태그 기술들의 배열을 설정한다. 기술에 대한 전체 이름은 Object.class.getName() 메서드를 사용한다.

    techListsArray = new String[][]{new String[]{NfcF.class.getName()}};
  2. 액티비티의 라이프사이클 메서드에 포그라운드 디스패치를 활성화, 비활성화 시키는 로직을 추가한다.

    enableForegroundDispatch() 메서드는 오직 액티비티가 포그라운드에 있을 때 메인 쓰레드에서 호출되어야 한다.(onResume() 메서드에서는 이를 보장한다.) 당신은 또한 스캔된 NFC 태그로 부터 데이터를 처리하기 위해onNewIntent() 콜백 메서드를 구현해야한다.

    public void onPause(){
        super.onPause();
        mAdapter.disableForegroundDispatch(this);
    }

    public void onResume(){
        super.onResume();
        mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
    }

    public void onNewIntent(Intent intent){
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        //do something with tagFromIntent
    }

 

완벽한 코드는 API Demo의 ForegroundDispatch 샘플을 보기 바란다.


Posted by 새우아저씨
,