12

I try to set up a Bluetooth connection as follows:

private class ConnectThread extends Thread {

    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
    BluetoothSocket connection = null;

    public ConnectThread(BluetoothDevice device) {
        mmDevice = device;
        // Get a BluetoothSocket for a connection with the
        // given BluetoothDevice
        try {
            if(D)
                Log.i(TAG, "createRfcommSocket");
            Method m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
            connection = (BluetoothSocket) m.invoke(mmDevice, 1);

            Utils.pause(100);
        } catch (Exception e) {
            Log.e(TAG, "create() failed", e);
        }
        if(D) 
            Log.i(TAG, "Bluetooth socket initialised");
        mmSocket = connection;
    }

    public void run() {
        if(D) 
            Log.i(TAG, "BEGIN mConnectThread on Device: " + mmDevice);
        setName("ConnectThread");

        if (mmSocket != null) {
            // Always cancel discovery because it will slow down a connection
            if(mAdapter.isDiscovering()) {
                if(D) 
                    Log.i(TAG, "stop discovering before trying to connect");
                mAdapter.cancelDiscovery();
            }

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                if(D) 
                    Log.i(TAG, "start Bluetooth socket connection");
                mmSocket.connect();
                if(D) 
                    Log.i(TAG, "end of Bluetooth socket connection");
            } catch (Exception e1) {
                Log.e(TAG, "connect failed", e1);
                connectionFailed();

                // Reset the socket
                resetConnection(mmSocket);

                // Start the service over to restart listening mode
                if(D) 
                    Log.i(TAG, "restart connection");
                BluetoothConnectionService.this.start();
                if(D) 
                    Log.i(TAG, "return");
                return;
            }

            // Start the connected thread
            if(D) 
                Log.i(TAG, "The device is considered as connected, call connected thread");
            connected(mmSocket, mmDevice);
        } else {
            if(D) 
                Log.i(TAG, "connection fail");
            connectionFailed();
            BluetoothConnectionService.this.start();
        }
    }

    public void cancel() {
        if(D) 
            Log.i(TAG, "connect thread cancel");
        resetConnection(mmSocket);
    }
}

The connection seems to be OK, and I get this log:

DEBUG/BluetoothConnectionService(3439): **connect to: 00:18:E4:21:8B:5E**
INFO/BluetoothConnectionService(3439): createRfcommSocket
INFO/BluetoothConnectionService(3439): Bluetooth socket initialised
INFO/BluetoothConnectionService(3439): BEGIN mConnectThread on Device : 00:18:E4:21:8B:5E
INFO/BluetoothConnectionService(3439): **start Bluetooth socket connection**
INFO/BluetoothConnectionService(3439): setState() 1 -> 2
INFO/ProtectionService(3439): MESSAGE_STATE_CHANGE: 1
DEBUG/ProtectionService(3439): STATE_CHANGED to STATE_LISTEN
INFO/ProtectionService(3439): MESSAGE_STATE_CHANGE: 2
DEBUG/abtfilt(2772): **Conn complete**
INFO/bluetoothd(2776): link_key_request (sba=24:21:AB:F4:69:25, dba=00:18:E4:21:8B:5E)
INFO/bluetoothd(2776): link_key_request (sba=24:21:AB:F4:69:25, dba=00:18:E4:21:8B:5E)
INFO/BluetoothConnectionService(3439): **end of Bluetooth socket connection**
INFO/BluetoothConnectionService(3439): **The device is considered as connected, call connected thread**

The BluetoothSocket.connect() returns without error.

Then I manage the connection with this:

private class ConnectedThread extends Thread {

    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket) {
        if(D) Log.d(TAG, "create ConnectedThread");
        mmSocket = socket;

        // Get the BluetoothSocket input and output streams
        try {
            if(D) 
                Log.i(TAG, "Get input stream");
            tmpIn = socket.getInputStream();
            if(D) 
                Log.i(TAG, "Get output stream");
            tmpOut = socket.getOutputStream();
            if(D) 
                Log.i(TAG, "isConnected = true");
            isConnected = true;
        } catch (IOException e) {
            Log.e(TAG, "Input and Output sockets not created", e);
            isConnected = false;
        }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    public void run() {
        if(D) 
            Log.i(TAG, "BEGIN mConnectedThread");
        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
        while(true) {
            try {
                // Read from the InputStream
                if(D) 
                    Log.i(TAG, "start read mmInStream");
                bytes = mmInStream.read(buffer);
                if(D) 
                    Log.i(TAG, "Bytes read: " + bytes);

                // Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "ConnectedThread: disconnected", e);
                break;
            }
        }
    }

    /**
     * Write to the connected OutStream.
     *
     * @param buffer
     *            The bytes to write
     */
    public void write(byte[] buffer) {
        try {
            mmOutStream.write(buffer);

            // Share the sent message back to the UI Activity
            mHandler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
            // mmOutStream.flush();
        } catch (IOException e) {
            Log.e(TAG, "Exception during write", e);
            connectionFailed();
        }
    }

    public void cancel() {
        if(D) 
            Log.i(TAG, "connected Thread cancel");
        resetConnection(mmSocket);
    }

}

And I receive this error:

DEBUG/BluetoothConnectionService(3439): create ConnectedThread
INFO/BluetoothConnectionService(3439): Get input stream
INFO/BluetoothConnectionService(3439): Get output stream
INFO/BluetoothConnectionService(3439): isConnected = true
INFO/BluetoothConnectionService(3439): BEGIN mConnectedThread
INFO/BluetoothConnectionService(3439): start read mmInStream
INFO/BluetoothConnectionService(3439): setState() 2 -> 3
INFO/ProtectionService(3439): MESSAGE_STATE_CHANGE: 3
DEBUG/ProtectionService(3439): connectionEstablished
**ERROR/BluetoothConnectionService(3439): ConnectedThread : disconnected
ERROR/BluetoothConnectionService(3439): java.io.IOException: Software caused connection abort
ERROR/BluetoothConnectionService(3439):     at android.bluetooth.BluetoothSocket.readNative(Native Method)
ERROR/BluetoothConnectionService(3439):     at android.bluetooth.BluetoothSocket.read(BluetoothSocket.java:307)
ERROR/BluetoothConnectionService(3439):     at android.bluetooth.BluetoothInputStream.read(BluetoothInputStream.java:96)
ERROR/BluetoothConnectionService(3439):     at java.io.InputStream.read(InputStream.java:133)**
INFO/ProtectionService(3439): Send Bluetooth message
**ERROR/BluetoothConnectionService(3439): Exception during write
ERROR/BluetoothConnectionService(3439): java.io.IOException: Transport endpoint is not connected
ERROR/BluetoothConnectionService(3439):     at android.bluetooth.BluetoothSocket.writeNative(Native Method)
ERROR/BluetoothConnectionService(3439):     at android.bluetooth.BluetoothSocket.write(BluetoothSocket.java:317)**

The error clearly come when I am doing this:

bytes = mmInStream.read(buffer);

What am I doing wrong?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Laurent
  • 1,710
  • 4
  • 25
  • 46
  • can you help in this issue http://stackoverflow.com/questions/40559549/android-bluetooth-java-io-ioexception-bt-socket-closed-read-return-1?noredirect=1#comment68358423_40559549 – Achin Nov 12 '16 at 07:39

2 Answers2

17

I had a very similar problem some days ago...

Try adding this check to your code:

if(mmInStream.available() > 0){
   bytes = mmInStream.read(buffer);
   mHandler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
}

This fixed my problem...

Good Luck ;)

Swordfish90
  • 446
  • 5
  • 11
  • Nice, exactly the problem I was having. – Shawn Lauzon Sep 26 '11 at 17:05
  • 5
    Actually, adding this code does prevent the exception, but in the case of the connection actually being lost, it prevents the thread from being restarted and getting fixed up. So while I agree with the answer, I ultimately decided not to use it. – Shawn Lauzon Sep 26 '11 at 17:42
  • 2
    What if the problem comes when writting, and not when receiving? Just at the mmOutStream.write(buffer) – Roman Rdgz Oct 31 '11 at 19:16
  • 2
    @Shawn Lauzon, So what did you end up doing? – vanevery Jul 01 '13 at 18:01
  • And if `available()` is zero? What then? How does this solve the problem? – user207421 Oct 26 '15 at 09:15
  • even i am getting the same issue http://stackoverflow.com/questions/40559549/android-bluetooth-java-io-ioexception-bt-socket-closed-read-return-1?noredirect=1#comment68358423_40559549 – Achin Nov 12 '16 at 07:39
-1

This is how I solved the issue: by implementing some sort of timeout. in my case 3 seconds. The code is not mine, but it works great. What basically happens is that there is a second loop waiting for something to get in the inputStream. when there is something in the inputStream, it goes ahead and reads it. This way you should avoid blocking in the mmInputstream.read() method.

I think it is a great solution. It worked nice for me: I am not the author.

ByteArrayOutputStream baos = new ByteArrayOutputStream();
                baos.reset();

                while (true) {
                treshHold = 0;
                    try {
                        try {
                            while (mmInStream.available() == 0 && treshHold < 3000) { // if there is something in the inputStream or after 3 seconds 
                                Thread.sleep(1);
                                treshHold++;
                            }
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                        if (treshHold < 3000) { // if less than 3 seconds timeout 
                            treshHold = 0;
                            b = mmInStream.read();
                            readBytes++;
                        } else {
                            break;
                        }

                        baos.write(b);
                        Thread.sleep(1);

                        if (b == 255) {
                            break; // this is how I know I have got the whole response
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                        break;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }

The while(true) can be changed, depending of what you expect to receive. In my case I go out of while when I receive an 0xFF or 255. Hope that it helps.

As for the writing to the outputStream I used the following:

if(mmOutStream !=null)
{
    try {
        mmOutStream.flush();
    } catch (IOException e1) {
        // log here ...
        e1.printStackTrace();
    }
    try {
        mmOutStream.write(send, 0, sendLength);
    } catch (IOException e) {
        // log here ...
        setState(STATE_NONE);
    }
}

Please mark the answer as correct if it helps :)

bboydflo
  • 907
  • 1
  • 15
  • 24