NdefMessage.java revision 590b73bc5b8e5f7b59bff1d9264a52388a5162e6
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 19dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellyimport android.nfc.NdefRecord; 20dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellyimport android.os.Parcel; 21dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellyimport android.os.Parcelable; 22dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 23dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly/** 24dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * NDEF Message data. 25dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 26dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Immutable data class. An NDEF message always contains zero or more NDEF 27dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * records. 28dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 29dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pellypublic class NdefMessage implements Parcelable { 30590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private static final byte FLAG_MB = (byte) 0x80; 31590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private static final byte FLAG_ME = (byte) 0x40; 32590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 33590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private final NdefRecord[] mRecords; 34590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 35590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly //TODO(npelly) FormatException 36dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 37dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Create an NDEF message from raw bytes. 38dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * <p> 39dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Validation is performed to make sure the Record format headers are valid, 40dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * and the ID + TYPE + PAYLOAD fields are of the correct size. 41590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * @throws FormatException 42dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * 43dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @hide 44dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 45590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly public NdefMessage(byte[] data) throws FormatException { 46590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mRecords = null; // stop compiler complaints about final field 47590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly if (parseNdefMessage(data) == -1) { 48590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly throw new FormatException("Error while parsing NDEF message"); 49590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 50dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 51dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 52dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 53dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Create an NDEF message from NDEF records. 54dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 55dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public NdefMessage(NdefRecord[] records) { 56590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly mRecords = new NdefRecord[records.length]; 57590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly System.arraycopy(records, 0, mRecords, 0, records.length); 58dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 59dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 60dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 61dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Get the NDEF records inside this NDEF message. 62dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * 63dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @return array of zero or more NDEF records. 64dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 65dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public NdefRecord[] getRecords() { 66590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return mRecords.clone(); 67dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 68dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 69dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly /** 70dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * Get a byte array representation of this NDEF message. 71dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * 72dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @return byte array 73dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly * @hide 74dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly */ 75dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public byte[] toByteArray() { 76590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly //TODO(nxp): do not return null 77590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly //TODO(nxp): allocate the byte array once, copy each record once 78590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly //TODO(nxp): process MB and ME flags outside loop 79590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly if ((mRecords == null) || (mRecords.length == 0)) 80590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return null; 81590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 82590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly byte[] msg = {}; 83590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 84590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly for (int i = 0; i < mRecords.length; i++) { 85590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly byte[] record = mRecords[i].toByteArray(); 86590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly byte[] tmp = new byte[msg.length + record.length]; 87590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 88590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /* Make sure the Message Begin flag is set only for the first record */ 89590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly if (i == 0) { 90590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly record[0] |= FLAG_MB; 91590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } else { 92590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly record[0] &= ~FLAG_MB; 93590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 94590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 95590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly /* Make sure the Message End flag is set only for the last record */ 96590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly if (i == (mRecords.length - 1)) { 97590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly record[0] |= FLAG_ME; 98590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } else { 99590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly record[0] &= ~FLAG_ME; 100590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 101590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 102590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly System.arraycopy(msg, 0, tmp, 0, msg.length); 103590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly System.arraycopy(record, 0, tmp, msg.length, record.length); 104590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 105590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly msg = tmp; 106590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly } 107590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 108590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return msg; 109dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 110dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 111dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public int describeContents() { 112dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly return 0; 113dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 114dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 115dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public void writeToParcel(Parcel dest, int flags) { 116590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeInt(mRecords.length); 117590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly dest.writeTypedArray(mRecords, flags); 118dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 119dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly 120dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public static final Parcelable.Creator<NdefMessage> CREATOR = 121dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly new Parcelable.Creator<NdefMessage>() { 122dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public NdefMessage createFromParcel(Parcel in) { 123590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly int recordsLength = in.readInt(); 124590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly NdefRecord[] records = new NdefRecord[recordsLength]; 125590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly in.readTypedArray(records, NdefRecord.CREATOR); 126590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return new NdefMessage(records); 127dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 128dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly public NdefMessage[] newArray(int size) { 129590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly return new NdefMessage[size]; 130dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly } 131dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly }; 132590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly 133590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly private native int parseNdefMessage(byte[] data); 134dc993791fc3cf7a270921f7419b0c6b875bbd92bNick Pelly}