본문 바로가기
Programming/Android Java

안드로이드 NFC 읽고/쓰기 구현

by 개Foot/Dog발?! 2014. 9. 26.

URL : http://hyosang.kr/432


.....


NFC에서 전송되는 데이터는 NDEF (NFC Data Exchange Format) 이라는 형식을 따른다.

한번에 전송되는 NFC 데이터는 NDEFMessage (android.nfc.NdefMessage) 이고, 하나의 NDEFMessage에는 여러개의 NDEFRecord (android.nfc.NdefRecord) 를 포함한다.


NDEFRecord는 3bit의 TNF(Type Name Field)를 가지며, TNF는 기본적으로 안드로이드의 NdefRecord 클래스에 정의되어 있다.

이 TNF에는 몇가지 제약사항이 있다.

- TNF_EMPTY인 경우 type, id, payload를 가질 수 없다

- TNF_UNKNOWN이나 0x07인 경우 type을 가질 수 없다

- TNF_UNCHANGED는 사용될 수 없다.

이 규칙을 위반한 경우 IllegalArgumentException이 발생하게 된다.


TNF_MEDIA인 경우 type은 mime type이 들어가야 한다.

TNF_UNKNOWN인 경우 데이터(payload)는 mime중 application/octet-stream 과 유사하며, type은 지정하지 않는다.

단순히 notification의 목적이면 TNF_EMPTY를 사용할 수 있다. type, payload가 필요하지 않기 때문.

URL/URI 형식의 데이터를 전송하려면 TNF_ABSOLUTE_URI를 사용하면 된다.

* URL/URI 형식은 TNF_WELL_KNOWN 타입에 RTD_URI 형식도 가능하다


NDEFRecord를 생성하기 위해 createUri(), createMime(), createExternal()같은 몇개의 헬퍼 메소드가 제공되고 있으니 참고.


데이터를 파악하기 위해 TNF, type이 사용되고,

데이터 자체를 위해 id와 payload 필드가 제공된다.


id의 최대 크기는 255바이트,

payload의 최대 크기는 2^32-1 의 크기만큼 담을 수 있다.

* payload는 SR값이 0일 경우 2^8-1이고 SR값이 1일 경우 2^8-1의 길이를 가진다. 이론상으로는


1. Permission 추가 & feature추가 

    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    <uses-permission android:name="android.permission.NFC" />


2-1. 쓰기기능 구현

NFC를 통해 데이터를 송신하는 송신측에서는 기본적으로 두개의 인터페이스를 구현해 주어야 한다.


1) android.nfc.NfcAdapter.CreateNdefMessageCallback

이 인터페이스에는 NdefMessage형을 반환하는 createNdefMessage(NfcEvent event) 메소드가 선언되어 있다.

메소드명에서 유추할 수 있듯이, 전송할 데이터를 생성하여 리턴해주어야 한다.


보낼 데이터로 NDEFRecord를 만들고, 이 NDEFRecord로 NDEFMessage를 생성하여 리턴 해 주면 된다.


2) android.nfc.NfcAdapter.OnDefPushCompleteCallback

역시 메소드 이름 그대로 NFC송신이 끝난 상태에서 onNdefPushComplete(NfcEvent event) 메소드가 호출된다.

.....

               mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

               mNfcAdapter.setNdefPushMessageCallback(this, this);

               mNfcAdapter.setOnNdefPushCompleteCallback(this, this);


** CreateNdefMessageCallback와 OnNdefPushCompleteCallback Interface를 추가해줘야 하며, 이에 따라 각각

void onNdefPushComplete(NfcEvent event) 메소드와 NdefMessage createNdefMessage(NfcEvent event) 메소드를 구성해 줘야 한다


NfcAdapter.getDefaultAdapter() 호출시 기기에서 NFC 기능이 불가능하다면 null이 리턴된다.

하드웨어의 NFC 지원 여부는 AndroidManifest.xml에서 uses-feature 로도 선언이 가능하다.


.....

setNdefPushMessageCallback()과 setOnDefPushCompleteCallback() 이 두개의 메소드는 3개 이상의 인자를 받을 수 있는데, 3번째 인자부터는 등록할 추가 액티비티이다.

하지만 레퍼런스에서는 한번에 하나의 액티비티만 등록할 것을 권장하고 있다.


2-2. 읽기기능 구현

수신부에서의 동작은 세 가지의 Intent로 전달된다.


1) android.nfc.ACTION_NDEF_DISCOVERED ("android.nfc.action.NDEF_DISCOVERED")

NDEF payload 태그가 감지되었을때 발생하는 인텐트. payload가 있는 경우 발생

.....


3) android.nfc.ACTION_TECH_DISCOVERED ("android.nfc.action.TECH_DISCOVERED")

특정 기능을 위한 태깅시 발생.

즉, activity에 intent-filter를 걸고, 어떤 기능(tech)를 대상으로 하는지 meta-data로 정의를 해 주어야 한다.


3) android.nfc.ACTION_TAG_DISCOVERED ("android.nfc.action.TAG_DISCOVERED")

태그가 감지되었을때 발생한다.


* Intent발생 옵션과 흐름은 아래 그림을 참고(@developer.android.com)

* NDEF_DISCOVERED는 TNF의 Well-Known Type, Media Type, Absolute URI일때 발생, TECH_DISCOVERED는 그 외에 TNF의 NFC External Type일때, 그외 Empty등일 때 사용되며, 이것들이 다룰 액티비티가 등록되있지 않을 경우 나머지가 TAG_DISCORVERED로 정해진 액티비티가 받게 되어 있다.


.....


각 Intent를 받은 액티비티에서는

android.nfc.NfcAdapter.EXTRA_NDEF_MESSAGES 를 키로 하여

ParcelableArrayExtra를 받아 첫번째 배열에 대해 NdefMessage를 받은 후 데이터를 처리하면 된다.


API Level 19(4.4, 킷캣-KitKat)부터 NfcAdapter.ReaderCallback 인터페이스도 추가되었다. 

이 콜백은 NfcAdapter.enableReaderMode()와 같이 사용되어진다.