/* * Copyright (C) 2011 Stanford University MobiSocial Lab * http://mobisocial.stanford.edu * * 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 mobisocial.ndefexchange; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import mobisocial.comm.DuplexSocket; import android.nfc.NdefMessage; import android.util.Log; /** * Runs a thread during a connection handover with a remote device over a * {@see DuplexSocket}, transmitting the given Ndef message. */ public class NdefExchangeThread extends Thread { public static final String TAG = "ndefexchange"; public static final byte HANDOVER_VERSION = 0x19; private final DuplexSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; private final NdefExchangeContract mmNfcInterface; private boolean mmIsWriteDone = false; private boolean mmIsReadDone = false; public NdefExchangeThread(DuplexSocket socket, NdefExchangeContract nfcInterface) { mmNfcInterface = nfcInterface; mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; try { socket.connect(); tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "temp sockets not created", e); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { try { if (mmInStream == null || mmOutStream == null) { return; } // Read on this thread, write on a new one. new SendNdefThread().start(); DataInputStream dataIn = new DataInputStream(mmInStream); byte version = (byte) dataIn.readByte(); if (version != HANDOVER_VERSION) { throw new Exception("Bad handover protocol version."); } int length = dataIn.readInt(); if (length > 0) { byte[] ndefBytes = new byte[length]; int read = 0; while (read < length) { read += dataIn.read(ndefBytes, read, (length - read)); } NdefMessage ndef = new NdefMessage(ndefBytes); mmNfcInterface.handleNdef(new NdefMessage[]{ndef}); } } catch (Exception e) { Log.e(TAG, "Failed to issue handover.", e); } finally { synchronized(NdefExchangeThread.this) { mmIsReadDone = true; if (mmIsWriteDone) { cancel(); } } } } public void cancel() { try { mmSocket.close(); } catch (IOException e) {} } private class SendNdefThread extends Thread { @Override public void run() { try { NdefMessage outbound = mmNfcInterface.getForegroundNdefMessage(); DataOutputStream dataOut = new DataOutputStream(mmOutStream); dataOut.writeByte(HANDOVER_VERSION); if (outbound != null) { byte[] ndefBytes = outbound.toByteArray(); dataOut.writeInt(ndefBytes.length); dataOut.write(ndefBytes); } else { dataOut.writeInt(0); } dataOut.flush(); } catch (IOException e) { Log.e(TAG, "Error writing to socket", e); } finally { synchronized(NdefExchangeThread.this) { mmIsWriteDone = true; if (mmIsReadDone) { cancel(); } } } } } }