NDEF(NFC Data Exchange Format)
ã¨ãããããç´è¿ã§ä½¿ããããªRTD TextãAAR, Mime Recordã«ã¤ãã¦ã ã調ã¹ãã
ä»ã®ã¬ã³ã¼ããAndroidBeamãªã©ã®å
容ã¯ã¾ãæ©ä¼ããã£ãã調ã¹ããã¨æãã
Android NFCããã°ã©ãã³ã°å®å
¨ã¬ã¤ãè²·ã£ã¦ã¿ãã
Android NFCããã°ã©ãã³ã°å®å ¨ã¬ã¤ã
- ä½è : æ ªå¼ä¼ç¤¾ Re:Kayo-System,é«å°¾å®å¥
- åºç社/ã¡ã¼ã«ã¼: ç¿æ³³ç¤¾
- çºå£²æ¥: 2013/10/30
- ã¡ãã£ã¢: Kindleç
- ãã®ååãå«ãããã° (3件) ãè¦ã
7 | 6 | 5 | 4 | 3 | 3 | 1 | 0 |
MB | ME | CF | SR | IL | TNF | ||
TYPE LENGTH (1 Byte) | |||||||
PAYLOAD LENGTH(1 Byte or 4 Byte) | |||||||
ID LENGTH (0â¦1 Byte) | |||||||
TYPE (0â¦n Byte) | |||||||
ID (0â¦n Byte) | |||||||
PAYLOAD (0â¦n Byte) |
NDEF Recordã®æ§æ
- MB(Message Begin: 1 bit):ãNDEFã¡ãã»ã¼ã¸ã®ã¯ããã®NDEFã¬ã³ã¼ããã©ããã示ããã©ã°ã
- ME(Message End: 1 bit):ãNDEFã¡ãã»ã¼ã¸ã®çµããNDEFã¬ã³ã¼ããã©ããã示ããã©ã°ã
- CF(Chunk Flag: 1 bit):ãåå²ãããã¬ã³ã¼ãã®æåãä¸éã§ãããã¨ã示ããã©ã°ã
- SR(Short Record: 1 bit):ãè¦é ãç¯ç´ãããã©ã°ããã®ãã©ã°ããã£ã¦ããã¨PAYLOAD_LENGTHã1 Byteã«ã§ããããã ããPAYLOADã255 Byte以ä¸ã«ããå¿ è¦ãããããã®ãã©ã°ããã£ã¦ããªãå ´åãPAYLOAD_LENGTHã¯4 Byteã
- IL(ID_LENGTH field is present: 1 bit): ID_LENGTHã¨IDããããã©ããã®ãã©ã°ã0ãæå®ããã¨ID_LENGTHã¨IDã¯çç¥ããªããã°ãªããªãã
- TNF(Type Name Format: 3 bit):ããã®ã¬ã³ã¼ããæã¤TYPE, ID, PAYLOADã«ã©ã®ãããªç¨®é¡ã®ãã¼ã¿ãå ¥ã£ã¦ããã®ãã示ãã
- TYPE LENGTH(1 Byte):ãByteåä½ã§TYPEã®é·ãã示ãã
- PAYLOAD LENGTH(1 Byte or 4 Byte):ãByteåä½ã§PAYLOADã®é·ãã示ãã
- ID_LENGTH(0..1 Byte):ãByteåä½ã§IDã®é·ãã示ãã
- TYPE(Payload Type 0..n Byte):ããã¤ãã¼ããã©ã®ãããªç¨®é¡ã§ãããã示ããTNFã«ãã£ã¦ãããå¤ãç°ãªãã
- ID(Payload ID: 0..n Byte):ãã¢ããªã±ã¼ã·ã§ã³ããã¤ãã¼ããèªèããå ´åã«å©ç¨ãããOptionalãªãã£ã¼ã«ãã
- PAYLOAD(0..n Byte)
Androidã§ã¯ãTNF, Type, ID, Payloadãæå®ããã¨ãæ®ãã®ãã£ã¼ã«ãã¯èªåçã«è£ã£ã¦ãããã®ã§ããã®ï¼ã¤æå¤ã¯ãã¾ãæèããªãã¦è¯ãã
ã
TNF(Type Name Format)
- 0x00(ENF_EMPTY)
- 0x01(TNF_WELL_KNOWN):ãNFC Forum RTD(Record Type Definition)ä»æ§ã«å®ç¾©ããã¦ããRTDã¿ã¤ããã©ã¼ãããã«å¾ãå¤ãã¿ã¤ãã«å«ã¾ãã¦ãããã¨ã示ãã
- 0x02(TNF_MIME_MEDIA):ãRFC(Request for Comments)2046ã«å®ç¾©ãããã¡ãã£ã¢ã¿ã¤ãã«å¾ãå¤ãã¿ã¤ãã«å«ã¾ãããã¨ã示ãã
- 0x03(TNF_ABSOLUTE_URI):ãRFC 3986ã«ãã£ã¦å®ç¾©ããã¦ãã絶対URIã«å¾ãå¤ãã¿ã¤ãã«å«ã¾ãããã¨ã示ããTNF_WELL_KNOWNã«ãå®ç¾©ããã¦ããããããã¾ã使ããã¨ããªãã
- 0x04(TNF EXTERNAL_TYPE):ãNFC Forum RTDä»æ§ã«å®ç¾©ããã¦ããå¤é¨ã¿ã¤ãåã«å¾ãå¤ãã¿ã¤ãã«å«ã¾ãã¦ãããã¨ã示ããååãä¸æã«èå¥ããå¿ è¦ãããå ´åã«ä½¿ç¨ãã(AAR etc.)
- 0x05(TNF_UNKNOWN
- 0x06(TNF_UNCHANGED):ãNDEFã¡ãã»ã¼ã¸ãè¤æ°ã«åå²ããå ´åã«å©ç¨ããTNFãåå²ããããã¤ãã¼ãã®ä¸éã§å©ç¨ããã
- 0x07 Reserved:
ã
TYPE(Payload Type)
æå®ããTNFã«ãã£ã¦ãããå¤ã¯å¤ããã
ã
TNFã0x01(TNF_WELL_KNOWN)ã®å ´å
- "ac"(RTD_ALTERNATIVE_CARRIER)
- "Hc"(RTD_HANDOVER_CARRIER)
- "Hr"(RTD_HANDOVER_REQUEST)
- "Hs"(RTD_HANDOVER_SELECT)
- "Sp"(RTD_SMART_POSTER)
- "T"(RTD_TEXT)
- "U"(RTD_URI)
ã
TNFã0x02(TNF_MIME_MEDIA)ã®å ´å
application/jsonã¨ãimage/pngã¨ã
NDEFãã¼ã¿ã®çæ/ãã¼ã¹
NdefRecordã®ã³ã³ã¹ãã©ã¯ã¿
public NdefRecord (short tnf, byte[] type, byte[] id, byte[] payload)
TNFã«ããä½ãæ¹ãç°ãªãã
代表çã¬ã³ã¼ãã®çæ/ãã¼ã¹ã®ä»æ¹ã¯æ¬¡ã®éãã
RTD Text Record
- TNF : 0x01(TNF_WELL_KNOWN)
- TYPE : "T"(RTD_TEXT)
æ¹è¡ã¯CRLFã§ãªããã°ãªããªãã¨ããã¹ãã¼ã¿ã¹ãã¤ããã¤ããªãã¨ãããªãã¨ãããããããªæ±ºã¾ããããã
MIME-Typeã§ããtext/plain; format=fixedã«ãªãããã«ããå¿
è¦ãããã
ãã¼ã¯ã¢ãããå«ãã§ã¯è¡ããªããå«ãå ´åã¯ãMIME Type Recordãå©ç¨ããã
æ¹è¡(0x0D, 0x0A)ã¨ã¿ã(0x08)ãé¤ããå¶å¾¡æå(UTF-8 0x00-0x1f)ã¯è¡¨ç¤ºåã«åé¤ããã¹ãã
public static NdefRecord createRTDTextNdefRecord(String txt, String id, Locale locale, boolean encodeInUtf8) { //lang code to byte[] byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); //text to byte[] txt = convertToCRLF(txt); Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); byte[] textBytes = txt.getBytes(utfEncoding); //status byte int utfBit = encodeInUtf8 ? 0 : 0x80; byte status = (byte) (utfBit | langBytes.length); //append status byte and text byte byte[] payload = concat(new byte[] { status }, langBytes, textBytes); NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, (id == null ? new byte[0] : id.getBytes()), payload); return record; } public static TextRecord parseRTDTextRecord(NdefRecord record) throws RuntimeException { if (!isRTDTextType(record)) throw new RuntimeException(FormatError); byte[] payload = record.getPayload(); byte status = payload[0]; final String encoding = ((status & 0x80) == 0) ? "UTF-8" : "UTF-16"; int langCodeLength = status & 0x3F; try { String text = new String(payload, langCodeLength + 1, payload.length - langCodeLength - 1, encoding); String langCode = new String(payload, 1, langCodeLength, Charset.forName("US-ASCII")); String id = new String(record.getId()); text = convertToLF(text); //Androidã®æ¹è¡ã³ã¼ãã«ãããã return new TextRecord(text, id, langCode, encoding); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e.toString()); } } public static byte[] concat(byte[]... bytesArray) { byte[] ret = null; for (byte[] bytes: bytesArray) { if (ret == null) { ret = bytes; } else { byte[] c = new byte[ret.length + bytes.length]; System.arraycopy(ret, 0, c, 0, ret.length); System.arraycopy(bytes, 0, c, ret.length, bytes.length); ret = c; } } return ret; } public static String convertToCRLF(String txt) { return txt.replaceAll("\r\n", "\n").replaceAll("\r", "\n").replace("\n", "\r\n"); } public static String convertToLF(String txt) { return txt.replaceAll("\r\n", "\n").replaceAll("\r", "\n"); } public static class TextRecord { public String text, id, langCode, encoding; public TextRecord(String text, String id, String langCode, String encoding) { this.text = text; this.id = id; this.langCode = langCode; this.encoding = encoding; } }
MIME Record
API Level 16ãªãNdefRecord.createMime(String mimeType, byte[] mimeData)ã§çæå¯è½ã
AAR(Android Application Record)
- TNF : 0x04(TNF EXTERNAL_TYPE)
- TYPE : android.com.pkg
- PAYLOAD : ããã±ã¼ã¸å
NDEFã®æ«å°¾ã«å«ãããã¨ãæ¨å¥¨ããã¦ããã
Android Gingerbread(API Level 10)ã§ã¯æ£ããèªèãããªãã
API Level 16ãªãNdefRecord.createApplicationRecord(String packageName)ã§çæå¯è½ã