| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.nfc.ndefpush; |
| |
| import android.util.Log; |
| |
| import android.nfc.NdefMessage; |
| import android.nfc.FormatException; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.DataInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.DataOutputStream; |
| |
| /** |
| * Implementation of the NDEF Push Protocol. |
| */ |
| public class NdefPushProtocol { |
| public static final byte ACTION_IMMEDIATE = (byte) 0x01; |
| public static final byte ACTION_BACKGROUND = (byte) 0x02; |
| |
| private static final String TAG = "NdefMessageSet"; |
| private static final byte VERSION = 1; |
| |
| private int mNumMessages; |
| private byte[] mActions; |
| private NdefMessage[] mMessages; |
| |
| public NdefPushProtocol(NdefMessage msg, byte action) { |
| mNumMessages = 1; |
| mActions = new byte[1]; |
| mActions[0] = action; |
| mMessages = new NdefMessage[1]; |
| mMessages[0] = msg; |
| } |
| |
| public NdefPushProtocol(byte[] actions, NdefMessage[] messages) { |
| if (actions.length != messages.length || actions.length == 0) { |
| throw new IllegalArgumentException( |
| "actions and messages must be the same size and non-empty"); |
| } |
| |
| // Keep a copy of these arrays |
| int numMessages = actions.length; |
| mActions = new byte[numMessages]; |
| System.arraycopy(actions, 0, mActions, 0, numMessages); |
| mMessages = new NdefMessage[numMessages]; |
| System.arraycopy(messages, 0, mMessages, 0, numMessages); |
| mNumMessages = numMessages; |
| } |
| |
| public NdefPushProtocol(byte[] data) throws FormatException { |
| ByteArrayInputStream buffer = new ByteArrayInputStream(data); |
| DataInputStream input = new DataInputStream(buffer); |
| |
| // Check version of protocol |
| byte version; |
| try { |
| version = input.readByte(); |
| } catch (java.io.IOException e) { |
| Log.w(TAG, "Unable to read version"); |
| throw new FormatException("Unable to read version"); |
| } |
| |
| if(version != VERSION) { |
| Log.w(TAG, "Got version " + version + ", expected " + VERSION); |
| throw new FormatException("Got version " + version + ", expected " + VERSION); |
| } |
| |
| // Read numMessages |
| try { |
| mNumMessages = input.readInt(); |
| } catch(java.io.IOException e) { |
| Log.w(TAG, "Unable to read numMessages"); |
| throw new FormatException("Error while parsing NdefMessageSet"); |
| } |
| if(mNumMessages == 0) { |
| Log.w(TAG, "No NdefMessage inside NdefMessageSet packet"); |
| throw new FormatException("Error while parsing NdefMessageSet"); |
| } |
| |
| // Read actions and messages |
| mActions = new byte[mNumMessages]; |
| mMessages = new NdefMessage[mNumMessages]; |
| for(int i = 0; i < mNumMessages; i++) { |
| // Read action |
| try { |
| mActions[i] = input.readByte(); |
| } catch(java.io.IOException e) { |
| Log.w(TAG, "Unable to read action for message " + i); |
| throw new FormatException("Error while parsing NdefMessageSet"); |
| } |
| // Read message length |
| int length; |
| try { |
| length = input.readInt(); |
| } catch(java.io.IOException e) { |
| Log.w(TAG, "Unable to read length for message " + i); |
| throw new FormatException("Error while parsing NdefMessageSet"); |
| } |
| byte[] bytes = new byte[length]; |
| // Read message |
| int lengthRead; |
| try { |
| lengthRead = input.read(bytes); |
| } catch(java.io.IOException e) { |
| Log.w(TAG, "Unable to read bytes for message " + i); |
| throw new FormatException("Error while parsing NdefMessageSet"); |
| } |
| if(length != lengthRead) { |
| Log.w(TAG, "Read " + lengthRead + " bytes but expected " + |
| length); |
| throw new FormatException("Error while parsing NdefMessageSet"); |
| } |
| // Create and store NdefMessage |
| try { |
| mMessages[i] = new NdefMessage(bytes); |
| } catch(FormatException e) { |
| throw e; |
| } |
| } |
| } |
| |
| public NdefMessage getImmediate() { |
| // Find and return the first immediate message |
| for(int i = 0; i < mNumMessages; i++) { |
| if(mActions[i] == ACTION_IMMEDIATE) { |
| return mMessages[i]; |
| } |
| } |
| return null; |
| } |
| |
| public byte[] toByteArray() { |
| ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024); |
| DataOutputStream output = new DataOutputStream(buffer); |
| |
| try { |
| output.writeByte(VERSION); |
| output.writeInt(mNumMessages); |
| for(int i = 0; i < mNumMessages; i++) { |
| output.writeByte(mActions[i]); |
| byte[] bytes = mMessages[i].toByteArray(); |
| output.writeInt(bytes.length); |
| output.write(bytes); |
| } |
| } catch(java.io.IOException e) { |
| return null; |
| } |
| |
| return buffer.toByteArray(); |
| } |
| } |