0

I am trying to pass data from my Android phone to Glass.

I found this: https://stackoverflow.com/a/20414642/318800 and ported it into an small application.

However, when I run my application the seek thread hangs on the

socket = mmServerSocket.accept();

Therefore I do not get any connections. Did something change that this no longer works to connect/detect bluetooth connections?

Can anyone point me to something that may help me get data from and Android 4.4 device to glass?

Community
  • 1
  • 1
N_tro_P
  • 673
  • 5
  • 15

1 Answers1

1

I can make my Nexus 7 tablet running Android 4.4.2 and Glass XE 17.2 exchange data without problem. You can run ClassicBluetoothServer.java either on Glass or another Android device, then run ClassicBluetoothClient.java on the other device. In the client code, you need to change CBT_SERVER_DEVICE_NAME's value to your paired Glass or Android device name (as seen in the device's Bluetooth Setting).

Client code:

public class ClassicBluetoothClient extends Activity {

    public final static String TAG = "ClassicBluetoothClient";
    public static final int REQUEST_TO_ENABLE_BT = 100;
    private BluetoothAdapter mBluetoothAdapter;
    private TextView mTvInfo;
    private UUID MY_UUID = UUID.fromString("D04E3068-E15B-4482-8306-4CABFA1726E7"); 
    private final static String FILE_PATH_RECEIVED = Environment.getExternalStorageDirectory().getPath()  +"/filefromCBTserver"; 

    // replace this with your own device names  
    private final static String CBT_SERVER_DEVICE_NAME = "Jeff Tang's Glass"; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTvInfo = (TextView) findViewById(R.id.info);
        mTvInfo.setText("Classic Bluetooth Client");
        //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();      

        if (mBluetoothAdapter == null) {
            Log.v(TAG, "Device does not support Bluetooth");
            Toast.makeText(ClassicBluetoothClient.this, "Device does not support Bluetooth", Toast.LENGTH_LONG).show();         
            return;
        }
        else { 
            if (!mBluetoothAdapter.isEnabled()) {
                Log.v(TAG, "Bluetooth supported but not enabled");
                Toast.makeText(ClassicBluetoothClient.this, "Bluetooth supported but not enabled", Toast.LENGTH_LONG).show();                           
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_TO_ENABLE_BT); 
            }else{
                Log.v(TAG, "Bluetooth supported and enabled");
                // discover new Bluetooth devices
                discoverBluetoothDevices();

                // find devices that have been paired 
                getBondedDevices();
            }           
        }        

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_TO_ENABLE_BT) { 
            discoverBluetoothDevices();
            getBondedDevices();
            return;
        }
    }   

    void discoverBluetoothDevices () {
        // register a BroadcastReceiver for the ACTION_FOUND Intent 
        // to receive info about each device discovered.
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);       
        registerReceiver(mReceiver, filter); 
        mBluetoothAdapter.startDiscovery();
    }

    // for each device discovered, the broadcast info is received
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                Log.v(TAG, "BroadcastReceiver on Receive - " + device.getName() + ": " + device.getAddress());
                String name = device.getName();

                // found another Android device of mine and start communication
                if (name != null && name.equalsIgnoreCase(CBT_SERVER_DEVICE_NAME)) {
                    new ConnectThread(device).start();
                }
            }           
        }
    };

    protected void onDestroy() {
        unregisterReceiver(mReceiver);
        super.onDestroy();
    }   

    // bonded devices are those that have already paired with the current device sometime in the past (and have not been unpaired)  
    void getBondedDevices () {
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                Log.v(TAG, "bonded device - " + device.getName() + ": " + device.getAddress());
                if (device.getName().equalsIgnoreCase(CBT_SERVER_DEVICE_NAME)) {
                    Log.d(TAG, CBT_SERVER_DEVICE_NAME);
                    new ConnectThread(device).start();
                    break;
                }
            }
        }       
        else {
            Toast.makeText(ClassicBluetoothClient.this, "No bonded devices", Toast.LENGTH_LONG).show();         
        }
    }

    private class ConnectThread extends Thread {
        int bytesRead;
        int total;      
        private final BluetoothSocket mmSocket;
        public ConnectThread(BluetoothDevice device) {
            BluetoothSocket tmp = null;
            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                // MY_UUID is the app's UUID string, also used by the server code
                Log.v(TAG, "before createRfcommSocketToServiceRecord");
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
                Log.v(TAG, "after createRfcommSocketToServiceRecord");
            } catch (IOException e) { 
                Log.v(TAG, " createRfcommSocketToServiceRecord exception: "+ e.getMessage());
            }
            mmSocket = tmp;
        }
        public void run() {
            // 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
                mmSocket.connect();
            } catch (IOException e) {
                Log.v(TAG, e.getMessage());
                try {
                    mmSocket.close();
                } catch (IOException closeException) { }
                return;
            }
            manageConnectedSocket(mmSocket);
        }   

        private void manageConnectedSocket(BluetoothSocket socket) {
            int bufferSize = 1024;
            byte[] buffer = new byte[bufferSize];
            FileOutputStream fos = null;
            BufferedOutputStream bos = null;

            try {
                InputStream instream = socket.getInputStream();
                fos = new FileOutputStream( FILE_PATH_RECEIVED );
                bos = new BufferedOutputStream(fos);
                bytesRead = -1;
                total = 0;
                while ((bytesRead = instream.read(buffer)) > 0) {
                    total += bytesRead;
                    bos.write(buffer, 0, bytesRead);
                    Log.i(TAG, "bytesRead="+bytesRead+",bufferSize="+bufferSize+",total="+total);
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mTvInfo.setText("bytesRead="+bytesRead+", total="+total);
                        }
                    });                     
                }
                runOnUiThread(new Runnable() {
                    public void run() {
                        mTvInfo.setText(total + " bytes of file " + FILE_PATH_RECEIVED + "has been received");
                    }
                });                             
                bos.close();
                socket.close();
            } catch (IOException e) {
                try {
                    socket.close(); 
                    bos.close();}
                catch (IOException e2) {
                    Log.e(TAG, "socket close exception:", e2);
                }
            }
        }   
    }
}

Server code:

public class ClassicBluetoothServer extends Activity {

    public final static String TAG = "ClassicBluetoothServer";
    BluetoothAdapter mBluetoothAdapter;
    BluetoothServerSocket mBluetoothServerSocket;
    public static final int REQUEST_TO_START_BT = 100;
    public static final int REQUEST_FOR_SELF_DISCOVERY = 200;
    private TextView mTvInfo;

    UUID MY_UUID = UUID.fromString("D04E3068-E15B-4482-8306-4CABFA1726E7");

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTvInfo = (TextView) findViewById(R.id.info);

        // initialize Bluetooth and retrieve info about the BT radio interface
        //mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        final BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();      

        if (mBluetoothAdapter == null) {
            mTvInfo.setText("Device does not support Bluetooth");
            return;
        } else {
            if (!mBluetoothAdapter.isEnabled()) {
                mTvInfo.setText("Bluetooth supported but not enabled");
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_TO_START_BT);
            } else {
                mTvInfo.setText("Bluetooth supported and enabled");             
                new AcceptThread().start();
            }
        }
    }

    private class AcceptThread extends Thread {
        private BluetoothServerSocket mServerSocket;

        public AcceptThread() {
            try {
                mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("ClassicBluetoothServer", MY_UUID);
            } 
            catch (IOException e) {
                final IOException ex = e;
                runOnUiThread(new Runnable() {
                    public void run() {
                        mTvInfo.setText(ex.getMessage());
                    }
                });
            }
        }

        public void run() {
            BluetoothSocket socket = null;
            // Keep listening until exception occurs or a socket is returned
            while (true) {
                try {
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mTvInfo.setText(mTvInfo.getText() + "\n\nWaiting for Bluetooth Client ...");
                        }
                    });

                    socket = mServerSocket.accept(); // blocking call

                } catch (IOException e) {
                    Log.v(TAG, e.getMessage());
                    break;
                }
                // If a connection was accepted
                if (socket != null) {
                    // Do work in a separate thread
                    new ConnectedThread(socket).start();

                    try {
                        mServerSocket.close();                      
                    } catch (IOException e) {
                        Log.v(TAG, e.getMessage());
                    }
                    break;
                }
            }
        }
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mSocket;
        private final OutputStream mOutStream;
        private int bytesRead;
        final private String FILE_TO_BE_TRANSFERRED = "marchmadness.png";
        final private String PATH = Environment.getExternalStorageDirectory().toString() + "/nbsocial/";        

        public ConnectedThread(BluetoothSocket socket) {
            mSocket = socket;
            OutputStream tmpOut = null;

            try {
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, e.getMessage());
            }
            mOutStream = tmpOut;
        }

        String copyAsset(String filename) {
            File dir = new File(PATH);
            if (!dir.exists()) {
                if (!dir.mkdirs()) {
                    return null;
                }
            }

            if (!(new File( PATH + filename).exists())) {
                try {

                    AssetManager assetManager = getAssets();
                    InputStream in = assetManager.open(filename);
                    OutputStream out = new FileOutputStream(PATH + filename);

                    // Transfer bytes from in to out
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    in.close();
                    out.close();

                } catch (IOException e) {
                    Log.e(TAG, "Was unable to copy " + filename + e.toString());
                    return null;
                }
            }       
            return PATH + filename; 
        }       


        public void run() {
            byte[] buffer = new byte[1024];

            // transfer a file
            if (mOutStream != null) {
                File myFile = new File( copyAsset("test.png") );
                FileInputStream fis = null;

                try {
                    fis = new FileInputStream(myFile);
                } catch (FileNotFoundException e) {
                    Log.e(TAG, e.getMessage());
                }
                BufferedInputStream bis = new BufferedInputStream(fis);
                runOnUiThread(new Runnable() {
                    public void run() {
                        mTvInfo.setText(mTvInfo.getText() + "\nbefore sending file "+  PATH + FILE_TO_BE_TRANSFERRED + " of " + new File(  PATH + FILE_TO_BE_TRANSFERRED ).length() + " bytes");
                    }
                });
                try {
                    bytesRead = 0;
                    for (int read = bis.read(buffer); read >= 0; read = bis.read(buffer))
                    {
                        mOutStream.write(buffer, 0, read);
                        bytesRead += read;
                    }

                    mSocket.close();
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mTvInfo.setText(bytesRead + " bytes of file " +  PATH + FILE_TO_BE_TRANSFERRED + " has been sent.");
                        }
                    });                 

                } catch (IOException e) {
                    Log.e(TAG, e.getMessage());
                }
            }

            new AcceptThread().start();             
        }
    }
}
Jeff Tang
  • 1,804
  • 15
  • 16
  • Looks great! I am having some issues still though :-( Specifically I had thought my phone was 4.4 (woops) but it is 4.3, and the client code bombs on copyAsset (I did make a bogus image test.png with in my resource directory drawable). I am not sure if it is bombing because of version. Also, I do have a Nexus running 4.4 but I am unable to pair even. I downloaded MyGLass to my nexus and severed from my phone but it still can't find it. Any ideas? I would prefer the client code on my 4.3 phone. – N_tro_P Jun 10 '14 at 12:44
  • At this point what I really want to do is just send a numeric value I enter on my phone to glass for glass to do some plotting with. So if it is easier to not send a file stream and send a string I would greatly appreciate it if you explained it. – N_tro_P Jun 10 '14 at 13:04