package com.dappervision.wearscript.glassbt; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.util.Log; import com.google.glass.companion.CompanionMessagingUtil; import com.google.glass.companion.GlassProtocol; import com.google.glass.companion.Proto; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public final class GlassDevice { private static GlassDevice mInstance = null; private static final UUID SECURE_UUID = UUID.fromString("F15CC914-E4BC-45CE-9930-CB7695385850"); private static final String TAG = "GlassDevice"; private String mac; private BluetoothSocket mSocket; private BluetoothAdapter mBluetoothAdapter; private final ExecutorService mWriteThread = Executors.newSingleThreadExecutor(); private final Object STREAM_WRITE_LOCK = new Object(); private List<GlassConnectionListener> mListeners = new ArrayList<GlassConnectionListener>(); private GlassReaderThread mGlassReaderThread; private GlassDevice() { mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); Log.d(TAG, "Creating GlassDevice"); if (mBluetoothAdapter == null) { Log.e(TAG, "No bluetooth"); return; } if (!mBluetoothAdapter.isEnabled()) { Log.e(TAG, "Bluetooth is not enabled"); } mac = findMac(); if (mac == null || mac.length() < 1) throw new RuntimeException("No Glass Paired"); Log.d(TAG, "Using " + mac); BluetoothDevice bluetoothDevice = mBluetoothAdapter.getRemoteDevice(mac); try { mSocket = bluetoothDevice.createRfcommSocketToServiceRecord(SECURE_UUID); } catch (IOException e) { Log.e(TAG, "Connect Error: ", e); return; } // Cancel discovery because it will slow down the connection mBluetoothAdapter.cancelDiscovery(); try { // Connect the device through the socket. This will block // until it succeeds or throws an exception mSocket.connect(); Log.i(TAG, "Socket connected"); } catch (IOException connectException) { // Unable to connect; close the socket and get out Log.e(TAG, "Didn't connect"); try { mSocket.close(); } catch (IOException closeException) { } return; } //mGlassReaderThread = new GlassReaderThread(mSocket, mListeners); //mGlassReaderThread.start(); } public static GlassDevice getInstance() { if (mInstance == null) { mInstance = new GlassDevice(); } return mInstance; } public void close() { if (mSocket != null) { try { mSocket.close(); } catch (IOException e) { Log.e(TAG, "Disconnect Error: ", e); } mSocket = null; } mInstance = null; } public String findMac() { Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { for (BluetoothDevice d : pairedDevices) { if (d.getAddress().startsWith("F8:8F:CA")) { return d.getAddress(); } } } Log.w(TAG, "No Glass paired"); return null; } public static boolean hasInstance() { return mInstance != null; } public interface GlassConnectionListener { public abstract void onReceivedEnvelope(Proto.Envelope envelope); } public void registerListener(GlassConnectionListener glassConnectionListener) { if (glassConnectionListener == null) { return; } synchronized (mListeners) { final int size = mListeners.size(); for (int i = 0; i < size; i++) { GlassConnectionListener listener = mListeners.get(i); if (listener == glassConnectionListener) { return; } } this.mListeners.add(glassConnectionListener); } } public void unregisterListener(GlassConnectionListener glassConnectionListener) { if (glassConnectionListener == null) { return; } synchronized (mListeners) { final int size = mListeners.size(); for (int i = 0; i < size; i++) { GlassConnectionListener listener = mListeners.get(i); if (listener == glassConnectionListener) { mListeners.remove(i); break; } } } } // Native Interface commands send to Glass public void swipeLeft() { writeAsync(GlassMessagingUtil.getSwipeLeftEvents()); } public void swipeRight() { writeAsync(GlassMessagingUtil.getSwipeRightEvents()); } public void swipeDown() { writeAsync(GlassMessagingUtil.getSwipeDownEvents()); } public void tap() { writeAsync(GlassMessagingUtil.getTapEvents()); } public void postMessage(String text) { writeAsync(GlassMessagingUtil.createTimelineMessage(text)); } public void requestScreenshot() { Proto.Envelope envelope = CompanionMessagingUtil.newEnvelope(); Proto.ScreenShot screenShot = new Proto.ScreenShot(); screenShot.startScreenshotRequestC2G = true; envelope.screenshot = screenShot; writeAsync(envelope); } public void write(Proto.Envelope envelope) { synchronized (STREAM_WRITE_LOCK) { try { OutputStream outStream = mSocket.getOutputStream(); if (mSocket != null) { GlassProtocol.writeMessage(envelope, outStream); } } catch (IOException e) { Log.e(TAG, "Write Error:", e); } } } public void writeAsync(final Proto.Envelope envelope) { mWriteThread.execute(new Runnable() { @Override public void run() { write(envelope); } }); } public void writeAsync(final List<Proto.Envelope> envelopes) { mWriteThread.execute(new Runnable() { @Override public void run() { for (Proto.Envelope envelope : envelopes) { write(envelope); } } }); } } class GlassReaderThread extends Thread { private static final String TAG = "GlassReaderThread"; private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; private final List<GlassDevice.GlassConnectionListener> mListeners; public GlassReaderThread(BluetoothSocket socket, List<GlassDevice.GlassConnectionListener> listeners) { mmSocket = socket; mListeners = listeners; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams, using temp objects because // member streams are final try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "Streams broke"); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { while (true) { try { InputStream inStream = mmSocket.getInputStream(); Proto.Envelope envelope = (Proto.Envelope) GlassProtocol.readMessage(new Proto.Envelope(), inStream); if (envelope.screenshot == null) { Log.i(TAG, "RX'd from Glass: " + envelope.toString()); } else { Log.i(TAG, "RX'd Screenshot from Glass"); } if (envelope != null) { synchronized (mListeners) { for (GlassDevice.GlassConnectionListener listener : mListeners) { listener.onReceivedEnvelope(envelope); } } } }catch (IOException e){ Log.e(TAG, "IOException"); e.printStackTrace(); break; } } } ; }