package org.oobd.ui.android.bus; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.Set; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import org.oobd.base.bus.OobdBus; import org.oobd.base.port.OOBDPort; import org.oobd.base.port.PortInfo; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.os.Looper; import android.util.Log; import org.oobd.base.support.Onion; import org.oobd.ui.android.application.OOBDApp; public class ComPort implements OOBDPort { InputStream inputStream; OutputStream outputStream; static ComPort myInstance = null; Activity callingActivity; BluetoothAdapter mBluetoothAdapter; BluetoothDevice obdDevice; BluetoothSocket serialPort; String BTAddress = null; Thread myThread; OobdBus msgReceiver; public static final UUID MY_UUID = UUID .fromString("00001101-0000-1000-8000-00805F9B34FB"); // public InputStream getInputStream() { // if (serialPort != null) { // return inputStream; // } else { // return null; // } // } // // public OutputStream getOutputStream() { // if (serialPort != null) { // return outputStream; // } else { // return null; // } // } public ComPort(Activity callingActivity, String BTAddress) { myInstance = this; this.BTAddress = BTAddress; this.callingActivity = callingActivity; // Looper.prepare(); } public boolean connect(Onion options, OobdBus receiveListener) { msgReceiver = receiveListener; System.out.println("Starting Bluetooth Detection and Device Pairing"); if (mBluetoothAdapter == null) { mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { Log.w(this.getClass().getSimpleName(), "Bluetooth not supported."); return false; } if (!mBluetoothAdapter.isEnabled()) { Log.w(this.getClass().getSimpleName(), "Bluetooth switched off."); return false; } } obdDevice = mBluetoothAdapter.getRemoteDevice(BTAddress); if (obdDevice != null) { // Get a BluetoothSocket to connect // with the given BluetoothDevice try { Log.v(this.getClass().getSimpleName(), "Device " + obdDevice.getName()); java.lang.reflect.Method m = obdDevice.getClass().getMethod( "createRfcommSocket", new Class[] { int.class }); // "createInsecureRfcommSocket", new Class[] { int.class }); serialPort = null; serialPort = (BluetoothSocket) m.invoke(obdDevice, 1); if (serialPort != null) { try { //mBluetoothAdapter.cancelDiscovery(); serialPort.connect(); Log.d("OOBD:Bluetooth", "Bluetooth connected"); inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); OOBDApp.getInstance().displayToast( "Bluetooth connected"); myThread = new Thread() { @Override public void run() { byte[] buffer = new byte[1024]; // buffer store // for the // stream int bytes; // bytes returned from read() // Keep listening to the InputStream until an // exception occurs Log.d("OOBD:Bluetooth", "receiver task runs"); while (!isInterrupted()) { if (inputStream != null) { try { //first we need to make this call not blocking, otherways we could not end the thread in case of no incoming data.. if (inputStream.available()>0){ // Read from the InputStream bytes = inputStream.read(buffer); if (bytes > 0) { Log.v(this.getClass().getSimpleName(), "Debug: received something"); String recString=new String(buffer); recString=recString.substring(0, bytes); msgReceiver .receiveString(recString); } }else{ try { Thread.sleep(10); } catch (InterruptedException e) { break; } } } catch (IOException e) { } } else { try { Thread.sleep(100); } catch (InterruptedException e) { break; } } } Log.d("OOBD:Bluetooth", "receiver task interupted"); } }; myThread.start(); return true; } catch (IOException ex) { Log.e(this.getClass().getSimpleName(), "Error: Could not connect to socket.", ex); OOBDApp.getInstance().displayToast( "Bluetooth NOT connected!"); } } else { Log.e("OOBD:Bluetooth", "Bluetooth NOT connected!"); OOBDApp.getInstance().displayToast( "Bluetooth NOT connected!"); if (serialPort != null) { try { serialPort.close(); } catch (IOException closeEx) { } } return false; } // do not yet connect. Connect before calling the // socket. } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return false; } // public boolean available() { // try { // return inputStream != null && inputStream.available() > 0; // } catch (IOException ex) { // // broken socket: Close it.. // close(); // return false; // } // } public String connectInfo(){ if (inputStream != null){ return "BT Connect to "+BTAddress; }else{ return null; } } public void close() { Log.d("BT Socket", "Try to close socket"); if (myThread!=null){ myThread.interrupt(); try { myThread.join(); } catch (InterruptedException e) { } myThread=null; } if (serialPort != null) { try { inputStream.close(); inputStream = null; } catch (Exception e) { e.printStackTrace(); } try { outputStream.close(); outputStream = null; } catch (Exception e) { e.printStackTrace(); } // add delay between closing streams and socket itself // appears as very helpful to avoid reconnection fault because of not properly // closed previous connection // found at http://stackoverflow.com/a/22769260 try { Thread.sleep(1000); } catch (InterruptedException e1) { } try { serialPort.close(); serialPort = null; } catch (Exception e) { e.printStackTrace(); } } } public static String getUrlFormat() { return "bt://{connectid}"; } public static PortInfo[] getPorts() { System.out.println("Starting Bluetooth Detection and Device Pairing"); BluetoothAdapter mBluetoothAdapter = BluetoothAdapter .getDefaultAdapter(); if (mBluetoothAdapter == null) { Log.w("ComPort", "Bluetooth not supported."); PortInfo[] BTDeviceSet = new PortInfo[1]; BTDeviceSet[0] = new PortInfo("", "No Devices paired :-("); return BTDeviceSet; } Set<BluetoothDevice> pairedDevices = mBluetoothAdapter .getBondedDevices(); PortInfo[] BTDeviceSet = new PortInfo[pairedDevices.size()]; Log.v("ComPort", "Anzahl paired devices: " + pairedDevices.size()); // If there are paired devices if (pairedDevices.size() > 0) { // Loop through paired devices int i = 0; for (BluetoothDevice device : pairedDevices) { // Add the name and address to an array adapter to show in a // ListView Log.d("OOBD:BluetoothIntiWorker", "Found Bluetooth Device: " + device.getName() + "=" + device.getAddress()); BTDeviceSet[i] = new PortInfo(device.getAddress(), device.getName()); i++; } } return BTDeviceSet; } public void attachShutDownHook() { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { System.out.println("Inside Add Shutdown Hook"); close(); System.out.println("Serial line closed"); } }); System.out.println("Shut Down Hook Attached."); } public synchronized void write(String s) { Log.d("OOBD:Comport", "Write something "); if (serialPort != null) { try { serialPort.getOutputStream().write(s.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } else { System.err.println("NO comhandle:" + s); } } public int adjustTimeOut(int originalTimeout) { // leave the original timeout unchanged return originalTimeout; } }