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;
24a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenenimport java.nio.charset.Charset;
25e0180d053e956ac32c2a5ec60272927755f17251Nick Pellyimport java.nio.charset.Charsets;
26e0180d053e956ac32c2a5ec60272927755f17251Nick Pellyimport java.util.Arrays;
27dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
28dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly/**
29c9f7890a203a013646650a695157277df81b6a17Scott Main * Represents a logical (unchunked) NDEF (NFC Data Exchange Format) record.
30c9f7890a203a013646650a695157277df81b6a17Scott Main * <p>An NDEF record always contains:
31dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <ul>
32c9f7890a203a013646650a695157277df81b6a17Scott Main * <li>3-bit TNF (Type Name Format) field: Indicates how to interpret the type field
33c9f7890a203a013646650a695157277df81b6a17Scott Main * <li>Variable length type: Describes the record format
34c9f7890a203a013646650a695157277df81b6a17Scott Main * <li>Variable length ID: A unique identifier for the record
35c9f7890a203a013646650a695157277df81b6a17Scott Main * <li>Variable length payload: The actual data payload
36dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * </ul>
37c9f7890a203a013646650a695157277df81b6a17Scott Main * <p>The underlying record
38dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * representation may be chunked across several NDEF records when the payload is
39dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * large.
40c9f7890a203a013646650a695157277df81b6a17Scott Main * <p>This is an immutable data class.
41dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */
4211b075e218b9921a953eeebe73fcd1a8a81f764bNick Pellypublic final class NdefRecord implements Parcelable {
43dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
44dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Indicates no type, id, or payload is associated with this NDEF Record.
45dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
46dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Type, id and payload fields must all be empty to be a valid TNF_EMPTY
47dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * record.
48dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
49dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final short TNF_EMPTY = 0x00;
50dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
51dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
52dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Indicates the type field uses the RTD type name format.
53dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
54dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Use this TNF with RTD types such as RTD_TEXT, RTD_URI.
55dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
56dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final short TNF_WELL_KNOWN = 0x01;
57dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
58dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
59dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Indicates the type field contains a value that follows the media-type BNF
60dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * construct defined by RFC 2046.
61dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
62dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final short TNF_MIME_MEDIA = 0x02;
63dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
64dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
65dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Indicates the type field contains a value that follows the absolute-URI
66dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * BNF construct defined by RFC 3986.
67dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
68dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final short TNF_ABSOLUTE_URI = 0x03;
69dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
70dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
71dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Indicates the type field contains a value that follows the RTD external
72dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * name specification.
73dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
74dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Note this TNF should not be used with RTD_TEXT or RTD_URI constants.
75dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Those are well known RTD constants, not external RTD constants.
76dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
77dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final short TNF_EXTERNAL_TYPE = 0x04;
78dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
79dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
80dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Indicates the payload type is unknown.
81dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
82dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * This is similar to the "application/octet-stream" MIME type. The payload
83dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * type is not explicitly encoded within the NDEF Message.
84dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
85dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * The type field must be empty to be a valid TNF_UNKNOWN record.
86dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
87dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final short TNF_UNKNOWN = 0x05;
88dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
89dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
90dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Indicates the payload is an intermediate or final chunk of a chunked
91dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * NDEF Record.
92dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
93dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * The payload type is specified in the first chunk, and subsequent chunks
94dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * must use TNF_UNCHANGED with an empty type field. TNF_UNCHANGED must not
95dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * be used in any other situation.
96dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
97dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final short TNF_UNCHANGED = 0x06;
98dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
99dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
100dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Reserved TNF type.
101dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
102dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * The NFC Forum NDEF Specification v1.0 suggests for NDEF parsers to treat this
103dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * value like TNF_UNKNOWN.
104dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * @hide
105dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
106dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final short TNF_RESERVED = 0x07;
107dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
108dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
109dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * RTD Text type. For use with TNF_WELL_KNOWN.
110dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
111dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final byte[] RTD_TEXT = {0x54};  // "T"
112dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
113dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
114dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * RTD URI type. For use with TNF_WELL_KNOWN.
115dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
116dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final byte[] RTD_URI = {0x55};   // "U"
117dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
118dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
119dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * RTD Smart Poster type. For use with TNF_WELL_KNOWN.
120dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
121dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final byte[] RTD_SMART_POSTER = {0x53, 0x70};  // "Sp"
122dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
123dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
124dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * RTD Alternative Carrier type. For use with TNF_WELL_KNOWN.
125dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
126dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final byte[] RTD_ALTERNATIVE_CARRIER = {0x61, 0x63};  // "ac"
127dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
128dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
129dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * RTD Handover Carrier type. For use with TNF_WELL_KNOWN.
130dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
131dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final byte[] RTD_HANDOVER_CARRIER = {0x48, 0x63};  // "Hc"
132dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
133dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
134dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * RTD Handover Request type. For use with TNF_WELL_KNOWN.
135dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
136dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final byte[] RTD_HANDOVER_REQUEST = {0x48, 0x72};  // "Hr"
137dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
138dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
139dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * RTD Handover Select type. For use with TNF_WELL_KNOWN.
140dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
141dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final byte[] RTD_HANDOVER_SELECT = {0x48, 0x73}; // "Hs"
142dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
143a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen    /**
144a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * RTD Android app type. For use with TNF_EXTERNAL.
145a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * <p>
146a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * The payload of a record with type RTD_ANDROID_APP
147a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * should be the package name identifying an application.
148a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * Multiple RTD_ANDROID_APP records may be included
149a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * in a single {@link NdefMessage}.
150a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * <p>
151a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * Use {@link #createApplicationRecord(String)} to create
152a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * RTD_ANDROID_APP records.
153a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * @hide
154a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     */
155a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen    public static final byte[] RTD_ANDROID_APP = "android.com:pkg".getBytes();
156a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen
157590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private static final byte FLAG_MB = (byte) 0x80;
158590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private static final byte FLAG_ME = (byte) 0x40;
159590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private static final byte FLAG_CF = (byte) 0x20;
160590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private static final byte FLAG_SR = (byte) 0x10;
161590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private static final byte FLAG_IL = (byte) 0x08;
162590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
163e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly    /**
164e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     * NFC Forum "URI Record Type Definition"
165e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     *
166e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
167e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
168e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     */
169e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly    private static final String[] URI_PREFIX_MAP = new String[] {
170e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "", // 0x00
171e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "http://www.", // 0x01
172e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "https://www.", // 0x02
173e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "http://", // 0x03
174e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "https://", // 0x04
175e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "tel:", // 0x05
176e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "mailto:", // 0x06
177e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "ftp://anonymous:anonymous@", // 0x07
178e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "ftp://ftp.", // 0x08
179e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "ftps://", // 0x09
180e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "sftp://", // 0x0A
181e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "smb://", // 0x0B
182e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "nfs://", // 0x0C
183e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "ftp://", // 0x0D
184e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "dav://", // 0x0E
185e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "news:", // 0x0F
186e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "telnet://", // 0x10
187e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "imap:", // 0x11
188e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "rtsp://", // 0x12
189e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "urn:", // 0x13
190e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "pop:", // 0x14
191e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "sip:", // 0x15
192e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "sips:", // 0x16
193e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "tftp:", // 0x17
194e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "btspp://", // 0x18
195e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "btl2cap://", // 0x19
196e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "btgoep://", // 0x1A
197e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "tcpobex://", // 0x1B
198e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "irdaobex://", // 0x1C
199e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "file://", // 0x1D
200e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "urn:epc:id:", // 0x1E
201e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "urn:epc:tag:", // 0x1F
202e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "urn:epc:pat:", // 0x20
203e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "urn:epc:raw:", // 0x21
204e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            "urn:epc:", // 0x22
205e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly    };
206e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly
207590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private final byte mFlags;
208590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private final short mTnf;
209590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private final byte[] mType;
210590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private final byte[] mId;
211590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private final byte[] mPayload;
212590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
213dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
214dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Construct an NDEF Record.
215dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
216dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Applications should not attempt to manually chunk NDEF Records - the
217dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * implementation of android.nfc will automatically chunk an NDEF Record
218dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * when necessary (and only present a single logical NDEF Record to the
219dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * application). So applications should not use TNF_UNCHANGED.
220dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     *
221dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * @param tnf  a 3-bit TNF constant
222dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * @param type byte array, containing zero to 255 bytes, must not be null
223dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * @param id   byte array, containing zero to 255 bytes, must not be null
224dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * @param payload byte array, containing zero to (2 ** 32 - 1) bytes,
225dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     *                must not be null
226dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
227dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload) {
2288bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen        /* New NDEF records created by applications will have FLAG_MB|FLAG_ME
2298bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen         * set by default; when multiple records are stored in a
2308bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen         * {@link NdefMessage}, these flags will be corrected when the {@link NdefMessage}
2318bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen         * is serialized to bytes.
2328bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen         */
2338bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen        this(tnf, type, id, payload, (byte)(FLAG_MB|FLAG_ME));
2348bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen    }
2358bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen
2368bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen    /**
2378bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen     * @hide
2388bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen     */
2398bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen    /*package*/ NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload, byte flags) {
240590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        /* check arguments */
241590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        if ((type == null) || (id == null) || (payload == null)) {
242590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            throw new IllegalArgumentException("Illegal null argument");
243590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
244590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
2456df23609d4c1f257b11d67b965e5b63cbdf26fcdNick Kralevich        if (tnf < 0 || tnf > 0x07) {
2466df23609d4c1f257b11d67b965e5b63cbdf26fcdNick Kralevich            throw new IllegalArgumentException("TNF out of range " + tnf);
2476df23609d4c1f257b11d67b965e5b63cbdf26fcdNick Kralevich        }
2486df23609d4c1f257b11d67b965e5b63cbdf26fcdNick Kralevich
249590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        /* Determine if it is a short record */
250590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        if(payload.length < 0xFF) {
251590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            flags |= FLAG_SR;
252590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
253590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
254590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        /* Determine if an id is present */
255590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        if(id.length != 0) {
256590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            flags |= FLAG_IL;
257590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
258590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
259590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mFlags = flags;
260590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mTnf = tnf;
261590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mType = type.clone();
262590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mId = id.clone();
263590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        mPayload = payload.clone();
264dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
265dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
266dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
267dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Construct an NDEF Record from raw bytes.
268dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
269dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Validation is performed to make sure the header is valid, and that
270dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * the id, type and payload sizes appear to be valid.
271dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     *
272dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * @throws FormatException if the data is not a valid NDEF record
273dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
274dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    public NdefRecord(byte[] data) throws FormatException {
275dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        /* Prevent compiler to complain about unassigned final fields */
276dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        mFlags = 0;
277dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        mTnf = 0;
278dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        mType = null;
279dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        mId = null;
280dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        mPayload = null;
281dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        /* Perform actual parsing */
282dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        if (parseNdefRecord(data) == -1) {
283dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau            throw new FormatException("Error while parsing NDEF record");
284dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau        }
285dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
286dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
287dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
288dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Returns the 3-bit TNF.
289dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
290dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * TNF is the top-level type.
291dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
292dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public short getTnf() {
293590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return mTnf;
294dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
295dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
296dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
297dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Returns the variable length Type field.
298dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * <p>
299dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * This should be used in conjunction with the TNF field to determine the
300dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * payload format.
301dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
302dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public byte[] getType() {
303590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return mType.clone();
304dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
305dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
306dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
307dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Returns the variable length ID.
308dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
309dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public byte[] getId() {
310590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return mId.clone();
311dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
312dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
313dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
314dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     * Returns the variable length payload.
315dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
316dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public byte[] getPayload() {
317590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return mPayload.clone();
318dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
319dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
320dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
321e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     * Helper to return the NdefRecord as a URI.
322e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     * TODO: Consider making a member method instead of static
323e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     * TODO: Consider more validation that this is a URI record
324e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     * TODO: Make a public API
325e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     * @hide
326e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly     */
327e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly    public static Uri parseWellKnownUriRecord(NdefRecord record) throws FormatException {
328e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        byte[] payload = record.getPayload();
329e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        if (payload.length < 2) {
330e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            throw new FormatException("Payload is not a valid URI (missing prefix)");
331e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        }
332e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly
333e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        /*
334e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly         * payload[0] contains the URI Identifier Code, per the
335e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly         * NFC Forum "URI Record Type Definition" section 3.2.2.
336e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly         *
337e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly         * payload[1]...payload[payload.length - 1] contains the rest of
338e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly         * the URI.
339e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly         */
340e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        int prefixIndex = (payload[0] & 0xff);
341e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        if (prefixIndex < 0 || prefixIndex >= URI_PREFIX_MAP.length) {
342e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            throw new FormatException("Payload is not a valid URI (invalid prefix)");
343e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        }
344e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        String prefix = URI_PREFIX_MAP[prefixIndex];
345e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        byte[] fullUri = concat(prefix.getBytes(Charsets.UTF_8),
346e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly                Arrays.copyOfRange(payload, 1, payload.length));
347e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        return Uri.parse(new String(fullUri, Charsets.UTF_8));
348e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly    }
349e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly
3503da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson    /**
351a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * Creates an Android application NDEF record.
352a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * <p>
35382328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * This record indicates to other Android devices the package
35482328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * that should be used to handle the rest of the NDEF message.
35582328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * You can embed this record anywhere into your NDEF message
35682328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * to ensure that the intended package receives the message.
35782328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * <p>
358a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * When an Android device dispatches an {@link NdefMessage}
359a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * containing one or more Android application records,
360a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * the applications contained in those records will be the
361a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * preferred target for the NDEF_DISCOVERED intent, in
362a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * the order in which they appear in the {@link NdefMessage}.
36382328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * This dispatch behavior was first added to Android in
36482328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * Ice Cream Sandwich.
365a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * <p>
366a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * If none of the applications are installed on the device,
367a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * a Market link will be opened to the first application.
368a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * <p>
369a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     * Note that Android application records do not overrule
37082328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * applications that have called
37182328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * {@link NfcAdapter#enableForegroundDispatch}.
37282328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     *
37382328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * @param packageName Android package name
37482328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * @return Android application NDEF record
375a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen     */
376a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen    public static NdefRecord createApplicationRecord(String packageName) {
377a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen        return new NdefRecord(TNF_EXTERNAL_TYPE, RTD_ANDROID_APP, new byte[] {},
378a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen                packageName.getBytes(Charsets.US_ASCII));
379a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen    }
380a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen
381a37fcbce59c8a746f641936b4de99867dbfabac9Martijn Coenen    /**
3823da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson     * Creates an NDEF record of well known type URI.
3833da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson     */
3843da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson    public static NdefRecord createUri(Uri uri) {
3851584af9d4e96282f0b4f4e8e647fd6a6d18594fbJeff Hamilton        return createUri(uri.toString());
3861584af9d4e96282f0b4f4e8e647fd6a6d18594fbJeff Hamilton    }
3871584af9d4e96282f0b4f4e8e647fd6a6d18594fbJeff Hamilton
3881584af9d4e96282f0b4f4e8e647fd6a6d18594fbJeff Hamilton    /**
3891584af9d4e96282f0b4f4e8e647fd6a6d18594fbJeff Hamilton     * Creates an NDEF record of well known type URI.
3901584af9d4e96282f0b4f4e8e647fd6a6d18594fbJeff Hamilton     */
3911584af9d4e96282f0b4f4e8e647fd6a6d18594fbJeff Hamilton    public static NdefRecord createUri(String uriString) {
3923da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson        byte prefix = 0x0;
3933da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson        for (int i = 1; i < URI_PREFIX_MAP.length; i++) {
3943da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson            if (uriString.startsWith(URI_PREFIX_MAP[i])) {
3953da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson                prefix = (byte) i;
3963da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson                uriString = uriString.substring(URI_PREFIX_MAP[i].length());
3973da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson                break;
3983da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson            }
3993da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson        }
4003da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson        byte[] uriBytes = uriString.getBytes(Charsets.UTF_8);
4013da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson        byte[] recordBytes = new byte[uriBytes.length + 1];
4023da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson        recordBytes[0] = prefix;
4033da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson        System.arraycopy(uriBytes, 0, recordBytes, 1, uriBytes.length);
4043da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson        return new NdefRecord(TNF_WELL_KNOWN, RTD_URI, new byte[0], recordBytes);
4053da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson    }
4063da3a4582c0793f59a1fd897a992e5e4fd57b6caBen Dodson
407e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly    private static byte[] concat(byte[]... arrays) {
408e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        int length = 0;
409e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        for (byte[] array : arrays) {
410e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            length += array.length;
411e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        }
412e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        byte[] result = new byte[length];
413e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        int pos = 0;
414e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        for (byte[] array : arrays) {
415e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            System.arraycopy(array, 0, result, pos, array.length);
416e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly            pos += array.length;
417e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        }
418e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly        return result;
419e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly    }
420e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly
421e0180d053e956ac32c2a5ec60272927755f17251Nick Pelly    /**
422da83f513ca661cd2bb1e6f1c8b64b716205bae48Jeff Hamilton     * Returns this entire NDEF Record as a byte array.
423dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
424dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public byte[] toByteArray() {
425590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        return generate(mFlags, mTnf, mType, mId, mPayload);
426dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
427dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
428dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public int describeContents() {
429dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        return 0;
430dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
431dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
432dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public void writeToParcel(Parcel dest, int flags) {
4338bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen        dest.writeInt(mFlags);
434590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeInt(mTnf);
435590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeInt(mType.length);
436590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeByteArray(mType);
437590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeInt(mId.length);
438590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeByteArray(mId);
439590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeInt(mPayload.length);
440590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeByteArray(mPayload);
441dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
442dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
443dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final Parcelable.Creator<NdefRecord> CREATOR =
444dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly            new Parcelable.Creator<NdefRecord>() {
445dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        public NdefRecord createFromParcel(Parcel in) {
4468bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen            byte flags = (byte)in.readInt();
447590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            short tnf = (short)in.readInt();
448590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            int typeLength = in.readInt();
449590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            byte[] type = new byte[typeLength];
450590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            in.readByteArray(type);
451590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            int idLength = in.readInt();
452590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            byte[] id = new byte[idLength];
453590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            in.readByteArray(id);
454590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            int payloadLength = in.readInt();
455590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            byte[] payload = new byte[payloadLength];
456590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            in.readByteArray(payload);
457590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
4588bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen            return new NdefRecord(tnf, type, id, payload, flags);
459dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        }
460dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        public NdefRecord[] newArray(int size) {
461590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            return new NdefRecord[size];
462dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        }
463dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    };
464590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
465dd7341f775ca4d86091f4106d6dfef9214073a7dSylvain Fonteneau    private native int parseNdefRecord(byte[] data);
466590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private native byte[] generate(short flags, short tnf, byte[] type, byte[] id, byte[] data);
4678bede1704717f594a0f924a57ff46f6300347e30Martijn Coenen}
468