NdefMessage.java revision a356bf1cd81614a94ef6c720998792480ade4c84
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
19a356bf1cd81614a94ef6c720998792480ade4c84Nick Pellyimport java.nio.ByteBuffer;
20a356bf1cd81614a94ef6c720998792480ade4c84Nick Pellyimport java.util.Arrays;
21a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
22dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellyimport android.os.Parcel;
23dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellyimport android.os.Parcelable;
24dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
25a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
26dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly/**
27a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * Represents an immutable NDEF Message.
28a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * <p>
29a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * NDEF (NFC Data Exchange Format) is a light-weight binary format,
30a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * used to encapsulate typed data. It is specified by the NFC Forum,
31a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * for transmission and storage with NFC, however it is transport agnostic.
32a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * <p>
33a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * NDEF defines messages and records. An NDEF Record contains
34a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * typed data, such as MIME-type media, a URI, or a custom
35a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * application payload. An NDEF Message is a container for
36a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * one or more NDEF Records.
37a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * <p>
38a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * When an Android device receives an NDEF Message
39a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * (for example by reading an NFC tag) it processes it through
40a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * a dispatch mechanism to determine an activity to launch.
41a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * The type of the <em>first</em> record in the message has
42a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * special importance for message dispatch, so design this record
43a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * carefully.
44a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * <p>
45a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * Use {@link #NdefMessage(byte[])} to construct an NDEF Message from
46a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * binary data, or {@link #NdefMessage(NdefRecord[])} to
47a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * construct from one or more {@link NdefRecord}s.
48a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * <p class="note">
49a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * {@link NdefMessage} and {@link NdefRecord} implementations are
50a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * always available, even on Android devices that do not have NFC hardware.
51a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * <p class="note">
52a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * {@link NdefRecord}s are intended to be immutable (and thread-safe),
53a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * however they may contain mutable fields. So take care not to modify
54a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * mutable fields passed into constructors, or modify mutable fields
55a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * obtained by getter methods, unless such modification is explicitly
56a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * marked as safe.
57a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly *
58a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * @see NfcAdapter#ACTION_NDEF_DISCOVERED
59a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly * @see NdefRecord
60dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */
6111b075e218b9921a953eeebe73fcd1a8a81f764bNick Pellypublic final class NdefMessage implements Parcelable {
62590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    private final NdefRecord[] mRecords;
63590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
64dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
65a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Construct an NDEF Message by parsing raw bytes.<p>
66a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Strict validation of the NDEF binary structure is performed:
67a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * there must be at least one record, every record flag must
68a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * be correct, and the total length of the message must match
69a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * the length of the input data.<p>
70a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * This parser can handle chunked records, and converts them
71a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * into logical {@link NdefRecord}s within the message.<p>
72a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Once the input data has been parsed to one or more logical
73a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * records, basic validation of the tnf, type, id, and payload fields
74a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * of each record is performed, as per the documentation on
75a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * on {@link NdefRecord#NdefRecord(short, byte[], byte[], byte[])}<p>
76a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * If either strict validation of the binary format fails, or
77a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * basic validation during record construction fails, a
78a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * {@link FormatException} is thrown<p>
79a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Deep inspection of the type, id and payload fields of
80a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * each record is not performed, so it is possible to parse input
81a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * that has a valid binary format and confirms to the basic
82a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * validation requirements of
83a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * {@link NdefRecord#NdefRecord(short, byte[], byte[], byte[])},
84a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * but fails more strict requirements as specified by the
85a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * NFC Forum.
86a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     *
87a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * <p class="note">
88a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * It is safe to re-use the data byte array after construction:
89a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * this constructor will make an internal copy of all necessary fields.
90a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     *
91a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * @param data raw bytes to parse
92a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * @throws FormatException if the data cannot be parsed
93dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
94590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    public NdefMessage(byte[] data) throws FormatException {
95a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        if (data == null) {
96a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            throw new NullPointerException("null data");
97a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        }
98a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        ByteBuffer buffer = ByteBuffer.wrap(data);
99a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
100a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        mRecords = NdefRecord.parse(buffer, false);
101a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
102a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        if (buffer.remaining() > 0) {
103a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            throw new FormatException("trailing data");
104590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
105dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
106dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
107dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
108a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Construct an NDEF Message from one or more NDEF Records.
109a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     *
110a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * @param record first record (mandatory)
111a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * @param records additional records (optional)
112a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     */
113a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    public NdefMessage(NdefRecord record, NdefRecord ... records) {
114a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        // validate
115a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        if (record == null) {
116a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            throw new NullPointerException("record cannot be null");
117a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        }
118a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        for (NdefRecord r : records) {
119a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            if (r == null) {
120a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly                throw new NullPointerException("record cannot be null");
121a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            }
122a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        }
123a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
124a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        mRecords = new NdefRecord[1 + records.length];
125a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        mRecords[0] = record;
126a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        System.arraycopy(records, 0, mRecords, 1, records.length);
127a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    }
128a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
129a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    /**
130a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Construct an NDEF Message from one or more NDEF Records.
131a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     *
132a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * @param records one or more records
133dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
134dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public NdefMessage(NdefRecord[] records) {
135a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        // validate
136a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        if (records.length < 1) {
137a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            throw new IllegalArgumentException("must have at least one record");
138a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        }
139a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        for (NdefRecord r : records) {
140a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            if (r == null) {
141a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly                throw new NullPointerException("records cannot contain null");
142a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            }
143a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        }
144a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
145a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        mRecords = records;
146dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
147dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
148dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
149a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Get the NDEF Records inside this NDEF Message.<p>
150a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * An NDEF Message always has one or more NDEF Records.
151dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     *
152a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * @return array of one or more NDEF records.
153dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
154dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public NdefRecord[] getRecords() {
155a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        return mRecords;
156dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
157dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
158dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    /**
159a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Return this NDEF MEssage as raw bytes.<p>
160a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * The NDEF Message is formatted as per the NDEF 1.0 specification,
161a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * and the byte array is suitable for network transmission or storage
162a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * in an NFC Forum NDEF compatible tag.<p>
163a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * This method will not chunk any records, and will always use the
164a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * short record (SR) format and omit the identifier field when possible.
165a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     *
166a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * @return NDEF Message in binary format
167dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly     */
168dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public byte[] toByteArray() {
169a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        int length = 0;
170a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        for (NdefRecord r : mRecords) {
171a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            length += r.getByteLength();
172a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        }
173590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
174a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        ByteBuffer buffer = ByteBuffer.allocate(length);
175590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
176a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        for (int i=0; i<mRecords.length; i++) {
177a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            boolean mb = (i == 0);  // first record
178a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            boolean me = (i == mRecords.length - 1);  // last record
179a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly            mRecords[i].writeToByteBuffer(buffer, mb, me);
180590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
181590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
182a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        return buffer.array();
183dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
184dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
1853ebd59bb5dc9f421fd2b9b789ea824746d58fff7Jason parks    @Override
186dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public int describeContents() {
187dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        return 0;
188dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
189dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
1903ebd59bb5dc9f421fd2b9b789ea824746d58fff7Jason parks    @Override
191dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public void writeToParcel(Parcel dest, int flags) {
192590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeInt(mRecords.length);
193590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        dest.writeTypedArray(mRecords, flags);
194dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    }
195dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly
196dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    public static final Parcelable.Creator<NdefMessage> CREATOR =
197dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly            new Parcelable.Creator<NdefMessage>() {
1983ebd59bb5dc9f421fd2b9b789ea824746d58fff7Jason parks        @Override
199dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        public NdefMessage createFromParcel(Parcel in) {
200590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            int recordsLength = in.readInt();
201590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            NdefRecord[] records = new NdefRecord[recordsLength];
202590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            in.readTypedArray(records, NdefRecord.CREATOR);
203590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            return new NdefMessage(records);
204dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        }
2053ebd59bb5dc9f421fd2b9b789ea824746d58fff7Jason parks        @Override
206dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        public NdefMessage[] newArray(int size) {
207590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            return new NdefMessage[size];
208dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly        }
209dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly    };
210590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
211a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    @Override
212a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    public int hashCode() {
213a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        return Arrays.hashCode(mRecords);
214a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    }
215a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
216a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    /**
217a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * Returns true if the specified NDEF Message contains
218a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     * identical NDEF Records.
219a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly     */
220a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    @Override
221a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    public boolean equals(Object obj) {
222a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        if (this == obj) return true;
223a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        if (obj == null) return false;
224a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        if (getClass() != obj.getClass()) return false;
225a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        NdefMessage other = (NdefMessage) obj;
226a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        return Arrays.equals(mRecords, other.mRecords);
227a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    }
228a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly
229a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    @Override
230a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    public String toString() {
231a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly        return "NdefMessage " + Arrays.toString(mRecords);
232a356bf1cd81614a94ef6c720998792480ade4c84Nick Pelly    }
233dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly}