NdefRecord.java revision 6df23609d4c1f257b11d67b965e5b63cbdf26fcd
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.nfc; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21 22import java.lang.UnsupportedOperationException; 23 24/** 25 * Represents a logical (unchunked) NDEF (NFC Data Exchange Format) record. 26 * <p>An NDEF record always contains: 27 * <ul> 28 * <li>3-bit TNF (Type Name Format) field: Indicates how to interpret the type field 29 * <li>Variable length type: Describes the record format 30 * <li>Variable length ID: A unique identifier for the record 31 * <li>Variable length payload: The actual data payload 32 * </ul> 33 * <p>The underlying record 34 * representation may be chunked across several NDEF records when the payload is 35 * large. 36 * <p>This is an immutable data class. 37 */ 38public class NdefRecord implements Parcelable { 39 /** 40 * Indicates no type, id, or payload is associated with this NDEF Record. 41 * <p> 42 * Type, id and payload fields must all be empty to be a valid TNF_EMPTY 43 * record. 44 */ 45 public static final short TNF_EMPTY = 0x00; 46 47 /** 48 * Indicates the type field uses the RTD type name format. 49 * <p> 50 * Use this TNF with RTD types such as RTD_TEXT, RTD_URI. 51 */ 52 public static final short TNF_WELL_KNOWN = 0x01; 53 54 /** 55 * Indicates the type field contains a value that follows the media-type BNF 56 * construct defined by RFC 2046. 57 */ 58 public static final short TNF_MIME_MEDIA = 0x02; 59 60 /** 61 * Indicates the type field contains a value that follows the absolute-URI 62 * BNF construct defined by RFC 3986. 63 */ 64 public static final short TNF_ABSOLUTE_URI = 0x03; 65 66 /** 67 * Indicates the type field contains a value that follows the RTD external 68 * name specification. 69 * <p> 70 * Note this TNF should not be used with RTD_TEXT or RTD_URI constants. 71 * Those are well known RTD constants, not external RTD constants. 72 */ 73 public static final short TNF_EXTERNAL_TYPE = 0x04; 74 75 /** 76 * Indicates the payload type is unknown. 77 * <p> 78 * This is similar to the "application/octet-stream" MIME type. The payload 79 * type is not explicitly encoded within the NDEF Message. 80 * <p> 81 * The type field must be empty to be a valid TNF_UNKNOWN record. 82 */ 83 public static final short TNF_UNKNOWN = 0x05; 84 85 /** 86 * Indicates the payload is an intermediate or final chunk of a chunked 87 * NDEF Record. 88 * <p> 89 * The payload type is specified in the first chunk, and subsequent chunks 90 * must use TNF_UNCHANGED with an empty type field. TNF_UNCHANGED must not 91 * be used in any other situation. 92 */ 93 public static final short TNF_UNCHANGED = 0x06; 94 95 /** 96 * Reserved TNF type. 97 * <p> 98 * The NFC Forum NDEF Specification v1.0 suggests for NDEF parsers to treat this 99 * value like TNF_UNKNOWN. 100 * @hide 101 */ 102 public static final short TNF_RESERVED = 0x07; 103 104 /** 105 * RTD Text type. For use with TNF_WELL_KNOWN. 106 */ 107 public static final byte[] RTD_TEXT = {0x54}; // "T" 108 109 /** 110 * RTD URI type. For use with TNF_WELL_KNOWN. 111 */ 112 public static final byte[] RTD_URI = {0x55}; // "U" 113 114 /** 115 * RTD Smart Poster type. For use with TNF_WELL_KNOWN. 116 */ 117 public static final byte[] RTD_SMART_POSTER = {0x53, 0x70}; // "Sp" 118 119 /** 120 * RTD Alternative Carrier type. For use with TNF_WELL_KNOWN. 121 */ 122 public static final byte[] RTD_ALTERNATIVE_CARRIER = {0x61, 0x63}; // "ac" 123 124 /** 125 * RTD Handover Carrier type. For use with TNF_WELL_KNOWN. 126 */ 127 public static final byte[] RTD_HANDOVER_CARRIER = {0x48, 0x63}; // "Hc" 128 129 /** 130 * RTD Handover Request type. For use with TNF_WELL_KNOWN. 131 */ 132 public static final byte[] RTD_HANDOVER_REQUEST = {0x48, 0x72}; // "Hr" 133 134 /** 135 * RTD Handover Select type. For use with TNF_WELL_KNOWN. 136 */ 137 public static final byte[] RTD_HANDOVER_SELECT = {0x48, 0x73}; // "Hs" 138 139 private static final byte FLAG_MB = (byte) 0x80; 140 private static final byte FLAG_ME = (byte) 0x40; 141 private static final byte FLAG_CF = (byte) 0x20; 142 private static final byte FLAG_SR = (byte) 0x10; 143 private static final byte FLAG_IL = (byte) 0x08; 144 145 private final byte mFlags; 146 private final short mTnf; 147 private final byte[] mType; 148 private final byte[] mId; 149 private final byte[] mPayload; 150 151 /** 152 * Construct an NDEF Record. 153 * <p> 154 * Applications should not attempt to manually chunk NDEF Records - the 155 * implementation of android.nfc will automatically chunk an NDEF Record 156 * when necessary (and only present a single logical NDEF Record to the 157 * application). So applications should not use TNF_UNCHANGED. 158 * 159 * @param tnf a 3-bit TNF constant 160 * @param type byte array, containing zero to 255 bytes, must not be null 161 * @param id byte array, containing zero to 255 bytes, must not be null 162 * @param payload byte array, containing zero to (2 ** 32 - 1) bytes, 163 * must not be null 164 */ 165 public NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload) { 166 /* check arguments */ 167 if ((type == null) || (id == null) || (payload == null)) { 168 throw new IllegalArgumentException("Illegal null argument"); 169 } 170 171 if (tnf < 0 || tnf > 0x07) { 172 throw new IllegalArgumentException("TNF out of range " + tnf); 173 } 174 175 /* generate flag */ 176 byte flags = FLAG_MB | FLAG_ME; 177 178 /* Determine if it is a short record */ 179 if(payload.length < 0xFF) { 180 flags |= FLAG_SR; 181 } 182 183 /* Determine if an id is present */ 184 if(id.length != 0) { 185 flags |= FLAG_IL; 186 } 187 188 mFlags = flags; 189 mTnf = tnf; 190 mType = type.clone(); 191 mId = id.clone(); 192 mPayload = payload.clone(); 193 } 194 195 /** 196 * Construct an NDEF Record from raw bytes. 197 * <p> 198 * Validation is performed to make sure the header is valid, and that 199 * the id, type and payload sizes appear to be valid. 200 * 201 * @throws FormatException if the data is not a valid NDEF record 202 */ 203 public NdefRecord(byte[] data) { 204 throw new UnsupportedOperationException(); 205 } 206 207 /** 208 * Returns the 3-bit TNF. 209 * <p> 210 * TNF is the top-level type. 211 */ 212 public short getTnf() { 213 return mTnf; 214 } 215 216 /** 217 * Returns the variable length Type field. 218 * <p> 219 * This should be used in conjunction with the TNF field to determine the 220 * payload format. 221 */ 222 public byte[] getType() { 223 return mType.clone(); 224 } 225 226 /** 227 * Returns the variable length ID. 228 */ 229 public byte[] getId() { 230 return mId.clone(); 231 } 232 233 /** 234 * Returns the variable length payload. 235 */ 236 public byte[] getPayload() { 237 return mPayload.clone(); 238 } 239 240 /** 241 * Return this NDEF Record as a byte array. 242 * @hide 243 */ 244 public byte[] toByteArray() { 245 return generate(mFlags, mTnf, mType, mId, mPayload); 246 } 247 248 public int describeContents() { 249 return 0; 250 } 251 252 public void writeToParcel(Parcel dest, int flags) { 253 dest.writeInt(mTnf); 254 dest.writeInt(mType.length); 255 dest.writeByteArray(mType); 256 dest.writeInt(mId.length); 257 dest.writeByteArray(mId); 258 dest.writeInt(mPayload.length); 259 dest.writeByteArray(mPayload); 260 } 261 262 public static final Parcelable.Creator<NdefRecord> CREATOR = 263 new Parcelable.Creator<NdefRecord>() { 264 public NdefRecord createFromParcel(Parcel in) { 265 short tnf = (short)in.readInt(); 266 int typeLength = in.readInt(); 267 byte[] type = new byte[typeLength]; 268 in.readByteArray(type); 269 int idLength = in.readInt(); 270 byte[] id = new byte[idLength]; 271 in.readByteArray(id); 272 int payloadLength = in.readInt(); 273 byte[] payload = new byte[payloadLength]; 274 in.readByteArray(payload); 275 276 return new NdefRecord(tnf, type, id, payload); 277 } 278 public NdefRecord[] newArray(int size) { 279 return new NdefRecord[size]; 280 } 281 }; 282 283 private native byte[] generate(short flags, short tnf, byte[] type, byte[] id, byte[] data); 284}