NdefRecord.java revision e0180d053e956ac32c2a5ec60272927755f17251
1dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly/* 2dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Copyright (C) 2010 The Android Open Source Project 3dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * 4dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 5dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * you may not use this file except in compliance with the License. 6dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * You may obtain a copy of the License at 7dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * 8dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * http://www.apache.org/licenses/LICENSE-2.0 9dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * 10dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Unless required by applicable law or agreed to in writing, software 11dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 12dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * See the License for the specific language governing permissions and 14dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * limitations under the License. 15dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 16dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 17dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellypackage android.nfc; 18dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 19e0180d053e956ac32c2a5ec60272927755f17251Nick Pellyimport android.net.Uri; 20dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellyimport android.os.Parcel; 21dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellyimport android.os.Parcelable; 22dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 23dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellyimport java.lang.UnsupportedOperationException; 24e0180d053e956ac32c2a5ec60272927755f17251Nick Pellyimport java.nio.charset.Charsets; 25e0180d053e956ac32c2a5ec60272927755f17251Nick Pellyimport java.util.Arrays; 26dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 27dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly/** 28c9f7890a203a013646650a695157277df81b6a17Scott Main * Represents a logical (unchunked) NDEF (NFC Data Exchange Format) record. 29c9f7890a203a013646650a695157277df81b6a17Scott Main * <p>An NDEF record always contains: 30dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <ul> 31c9f7890a203a013646650a695157277df81b6a17Scott Main * <li>3-bit TNF (Type Name Format) field: Indicates how to interpret the type field 32c9f7890a203a013646650a695157277df81b6a17Scott Main * <li>Variable length type: Describes the record format 33c9f7890a203a013646650a695157277df81b6a17Scott Main * <li>Variable length ID: A unique identifier for the record 34c9f7890a203a013646650a695157277df81b6a17Scott Main * <li>Variable length payload: The actual data payload 35dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * </ul> 36c9f7890a203a013646650a695157277df81b6a17Scott Main * <p>The underlying record 37dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * representation may be chunked across several NDEF records when the payload is 38dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * large. 39c9f7890a203a013646650a695157277df81b6a17Scott Main * <p>This is an immutable data class. 40dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 4111b075e218b9921a953eeebe73fcd1a8a81f764bNick Pellypublic final class NdefRecord implements Parcelable { 42dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 43dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Indicates no type, id, or payload is associated with this NDEF Record. 44dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 45dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Type, id and payload fields must all be empty to be a valid TNF_EMPTY 46dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * record. 47dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 48dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final short TNF_EMPTY = 0x00; 49dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 50dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 51dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Indicates the type field uses the RTD type name format. 52dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 53dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Use this TNF with RTD types such as RTD_TEXT, RTD_URI. 54dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 55dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final short TNF_WELL_KNOWN = 0x01; 56dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 57dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 58dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Indicates the type field contains a value that follows the media-type BNF 59dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * construct defined by RFC 2046. 60dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 61dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final short TNF_MIME_MEDIA = 0x02; 62dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 63dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 64dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Indicates the type field contains a value that follows the absolute-URI 65dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * BNF construct defined by RFC 3986. 66dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 67dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final short TNF_ABSOLUTE_URI = 0x03; 68dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 69dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 70dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Indicates the type field contains a value that follows the RTD external 71dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * name specification. 72dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 73dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Note this TNF should not be used with RTD_TEXT or RTD_URI constants. 74dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Those are well known RTD constants, not external RTD constants. 75dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 76dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final short TNF_EXTERNAL_TYPE = 0x04; 77dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 78dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 79dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Indicates the payload type is unknown. 80dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 81dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * This is similar to the "application/octet-stream" MIME type. The payload 82dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * type is not explicitly encoded within the NDEF Message. 83dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 84dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * The type field must be empty to be a valid TNF_UNKNOWN record. 85dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 86dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final short TNF_UNKNOWN = 0x05; 87dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 88dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 89dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Indicates the payload is an intermediate or final chunk of a chunked 90dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * NDEF Record. 91dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 92dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * The payload type is specified in the first chunk, and subsequent chunks 93dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * must use TNF_UNCHANGED with an empty type field. TNF_UNCHANGED must not 94dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * be used in any other situation. 95dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 96dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final short TNF_UNCHANGED = 0x06; 97dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 98dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 99dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Reserved TNF type. 100dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 101dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * The NFC Forum NDEF Specification v1.0 suggests for NDEF parsers to treat this 102dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * value like TNF_UNKNOWN. 103dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @hide 104dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 105dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final short TNF_RESERVED = 0x07; 106dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 107dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 108dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * RTD Text type. For use with TNF_WELL_KNOWN. 109dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 110dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final byte[] RTD_TEXT = {0x54}; // "T" 111dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 112dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 113dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * RTD URI type. For use with TNF_WELL_KNOWN. 114dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 115dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final byte[] RTD_URI = {0x55}; // "U" 116dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 117dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 118dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * RTD Smart Poster type. For use with TNF_WELL_KNOWN. 119dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 120dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final byte[] RTD_SMART_POSTER = {0x53, 0x70}; // "Sp" 121dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 122dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 123dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * RTD Alternative Carrier type. For use with TNF_WELL_KNOWN. 124dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 125dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final byte[] RTD_ALTERNATIVE_CARRIER = {0x61, 0x63}; // "ac" 126dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 127dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 128dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * RTD Handover Carrier type. For use with TNF_WELL_KNOWN. 129dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 130dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final byte[] RTD_HANDOVER_CARRIER = {0x48, 0x63}; // "Hc" 131dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 132dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 133dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * RTD Handover Request type. For use with TNF_WELL_KNOWN. 134dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 135dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final byte[] RTD_HANDOVER_REQUEST = {0x48, 0x72}; // "Hr" 136dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 137dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 138dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * RTD Handover Select type. For use with TNF_WELL_KNOWN. 139dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 140dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final byte[] RTD_HANDOVER_SELECT = {0x48, 0x73}; // "Hs" 141dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 142590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private static final byte FLAG_MB = (byte) 0x80; 143590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private static final byte FLAG_ME = (byte) 0x40; 144590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private static final byte FLAG_CF = (byte) 0x20; 145590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private static final byte FLAG_SR = (byte) 0x10; 146590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private static final byte FLAG_IL = (byte) 0x08; 147590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 148e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly /** 149e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * NFC Forum "URI Record Type Definition" 150e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * 151e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * This is a mapping of "URI Identifier Codes" to URI string prefixes, 152e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * per section 3.2.2 of the NFC Forum URI Record Type Definition document. 153e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly */ 154e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly private static final String[] URI_PREFIX_MAP = new String[] { 155e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "", // 0x00 156e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "http://www.", // 0x01 157e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "https://www.", // 0x02 158e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "http://", // 0x03 159e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "https://", // 0x04 160e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "tel:", // 0x05 161e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "mailto:", // 0x06 162e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "ftp://anonymous:anonymous@", // 0x07 163e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "ftp://ftp.", // 0x08 164e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "ftps://", // 0x09 165e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "sftp://", // 0x0A 166e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "smb://", // 0x0B 167e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "nfs://", // 0x0C 168e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "ftp://", // 0x0D 169e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "dav://", // 0x0E 170e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "news:", // 0x0F 171e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "telnet://", // 0x10 172e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "imap:", // 0x11 173e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "rtsp://", // 0x12 174e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "urn:", // 0x13 175e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "pop:", // 0x14 176e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "sip:", // 0x15 177e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "sips:", // 0x16 178e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "tftp:", // 0x17 179e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "btspp://", // 0x18 180e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "btl2cap://", // 0x19 181e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "btgoep://", // 0x1A 182e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "tcpobex://", // 0x1B 183e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "irdaobex://", // 0x1C 184e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "file://", // 0x1D 185e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "urn:epc:id:", // 0x1E 186e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "urn:epc:tag:", // 0x1F 187e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "urn:epc:pat:", // 0x20 188e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "urn:epc:raw:", // 0x21 189e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly "urn:epc:", // 0x22 190e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly }; 191e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly 192590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private final byte mFlags; 193590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private final short mTnf; 194590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private final byte[] mType; 195590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private final byte[] mId; 196590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private final byte[] mPayload; 197590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 198dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 199dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Construct an NDEF Record. 200dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 201dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Applications should not attempt to manually chunk NDEF Records - the 202dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * implementation of android.nfc will automatically chunk an NDEF Record 203dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * when necessary (and only present a single logical NDEF Record to the 204dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * application). So applications should not use TNF_UNCHANGED. 205dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * 206dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @param tnf a 3-bit TNF constant 207dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @param type byte array, containing zero to 255 bytes, must not be null 208dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @param id byte array, containing zero to 255 bytes, must not be null 209dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @param payload byte array, containing zero to (2 ** 32 - 1) bytes, 210dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * must not be null 211dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 212dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload) { 2138bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen /* New NDEF records created by applications will have FLAG_MB|FLAG_ME 2148bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen * set by default; when multiple records are stored in a 2158bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen * {@link NdefMessage}, these flags will be corrected when the {@link NdefMessage} 2168bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen * is serialized to bytes. 2178bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen */ 2188bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen this(tnf, type, id, payload, (byte)(FLAG_MB|FLAG_ME)); 2198bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen } 2208bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen 2218bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen /** 2228bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen * @hide 2238bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen */ 2248bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen /*package*/ NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload, byte flags) { 225590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /* check arguments */ 226590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly if ((type == null) || (id == null) || (payload == null)) { 227590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly throw new IllegalArgumentException("Illegal null argument"); 228590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 229590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 2306df23609d4c1f257b11d67b965e5b63cbdf26fcdNick Kralevich if (tnf < 0 || tnf > 0x07) { 2316df23609d4c1f257b11d67b965e5b63cbdf26fcdNick Kralevich throw new IllegalArgumentException("TNF out of range " + tnf); 2326df23609d4c1f257b11d67b965e5b63cbdf26fcdNick Kralevich } 2336df23609d4c1f257b11d67b965e5b63cbdf26fcdNick Kralevich 234590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /* Determine if it is a short record */ 235590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly if(payload.length < 0xFF) { 236590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly flags |= FLAG_SR; 237590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 238590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 239590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /* Determine if an id is present */ 240590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly if(id.length != 0) { 241590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly flags |= FLAG_IL; 242590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 243590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 244590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mFlags = flags; 245590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mTnf = tnf; 246590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mType = type.clone(); 247590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mId = id.clone(); 248590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mPayload = payload.clone(); 249dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 250dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 251dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 252dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Construct an NDEF Record from raw bytes. 253dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 254dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Validation is performed to make sure the header is valid, and that 255dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * the id, type and payload sizes appear to be valid. 256dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * 257dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @throws FormatException if the data is not a valid NDEF record 258dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 259dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau public NdefRecord(byte[] data) throws FormatException { 260dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau /* Prevent compiler to complain about unassigned final fields */ 261dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau mFlags = 0; 262dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau mTnf = 0; 263dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau mType = null; 264dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau mId = null; 265dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau mPayload = null; 266dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau /* Perform actual parsing */ 267dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau if (parseNdefRecord(data) == -1) { 268dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau throw new FormatException("Error while parsing NDEF record"); 269dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau } 270dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 271dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 272dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 273dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Returns the 3-bit TNF. 274dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 275dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * TNF is the top-level type. 276dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 277dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public short getTnf() { 278590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return mTnf; 279dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 280dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 281dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 282dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Returns the variable length Type field. 283dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 284dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * This should be used in conjunction with the TNF field to determine the 285dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * payload format. 286dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 287dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public byte[] getType() { 288590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return mType.clone(); 289dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 290dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 291dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 292dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Returns the variable length ID. 293dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 294dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public byte[] getId() { 295590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return mId.clone(); 296dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 297dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 298dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 299dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Returns the variable length payload. 300dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 301dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public byte[] getPayload() { 302590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return mPayload.clone(); 303dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 304dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 305dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 306e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * Helper to return the NdefRecord as a URI. 307e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * TODO: Consider making a member method instead of static 308e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * TODO: Consider more validation that this is a URI record 309e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * TODO: Make a public API 310e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * @hide 311e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly */ 312e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly public static Uri parseWellKnownUriRecord(NdefRecord record) throws FormatException { 313e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly byte[] payload = record.getPayload(); 314e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly if (payload.length < 2) { 315e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly throw new FormatException("Payload is not a valid URI (missing prefix)"); 316e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly } 317e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly 318e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly /* 319e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * payload[0] contains the URI Identifier Code, per the 320e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * NFC Forum "URI Record Type Definition" section 3.2.2. 321e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * 322e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * payload[1]...payload[payload.length - 1] contains the rest of 323e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly * the URI. 324e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly */ 325e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly int prefixIndex = (payload[0] & 0xff); 326e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly if (prefixIndex < 0 || prefixIndex >= URI_PREFIX_MAP.length) { 327e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly throw new FormatException("Payload is not a valid URI (invalid prefix)"); 328e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly } 329e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly String prefix = URI_PREFIX_MAP[prefixIndex]; 330e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8), 331e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly Arrays.copyOfRange(payload, 1, payload.length)); 332e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly return Uri.parse(new String(fullUri, Charsets.UTF_8)); 333e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly } 334e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly 335e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly private static byte[] concat(byte[]... arrays) { 336e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly int length = 0; 337e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly for (byte[] array : arrays) { 338e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly length += array.length; 339e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly } 340e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly byte[] result = new byte[length]; 341e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly int pos = 0; 342e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly for (byte[] array : arrays) { 343e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly System.arraycopy(array, 0, result, pos, array.length); 344e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly pos += array.length; 345e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly } 346e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly return result; 347e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly } 348e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly 349e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly /** 350da83f513ca661cd2bb1e6f1c8b64b716205bae48Jeff Hamilton * Returns this entire NDEF Record as a byte array. 351dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 352dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public byte[] toByteArray() { 353590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return generate(mFlags, mTnf, mType, mId, mPayload); 354dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 355dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 356dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public int describeContents() { 357dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly return 0; 358dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 359dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 360dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public void writeToParcel(Parcel dest, int flags) { 3618bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen dest.writeInt(mFlags); 362590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeInt(mTnf); 363590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeInt(mType.length); 364590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeByteArray(mType); 365590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeInt(mId.length); 366590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeByteArray(mId); 367590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeInt(mPayload.length); 368590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeByteArray(mPayload); 369dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 370dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 371dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final Parcelable.Creator<NdefRecord> CREATOR = 372dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly new Parcelable.Creator<NdefRecord>() { 373dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public NdefRecord createFromParcel(Parcel in) { 3748bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen byte flags = (byte)in.readInt(); 375590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly short tnf = (short)in.readInt(); 376590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly int typeLength = in.readInt(); 377590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly byte[] type = new byte[typeLength]; 378590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly in.readByteArray(type); 379590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly int idLength = in.readInt(); 380590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly byte[] id = new byte[idLength]; 381590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly in.readByteArray(id); 382590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly int payloadLength = in.readInt(); 383590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly byte[] payload = new byte[payloadLength]; 384590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly in.readByteArray(payload); 385590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 3868bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen return new NdefRecord(tnf, type, id, payload, flags); 387dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 388dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public NdefRecord[] newArray(int size) { 389590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return new NdefRecord[size]; 390dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 391dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly }; 392590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 393dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau private native int parseNdefRecord(byte[] data); 394590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private native byte[] generate(short flags, short tnf, byte[] type, byte[] id, byte[] data); 3958bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen} 396