flutter_bluetooth_serial icon indicating copy to clipboard operation
flutter_bluetooth_serial copied to clipboard

IOException: read failed, socket might closed or timeout, read ret: -1

Open vaibhiarora03 opened this issue 3 years ago • 5 comments

I've been facing this issue while connecting OBDII devices. This issue's occurrence is very random varied across cheap Chinese OBD devices to expensive branded ones.

For Bluetooth communication in flutter, I'm using the Flutter Bluetooth Serial package https://pub.dev/packages/flutter_bluetooth_serial

What I'm doing is initially creating a socket via createRfcommSocketToServiceRecord method. When IOException occurs, then the socket is created via createRfcommSocket reflection method. If still, the IOException occurs, then the Input and Output streams and socket are closed manually and then the connection is tried again. I try connection a total of 3 times.

Here is the connect function which I changed in the package.

public void connect() throws IOException {
        if (isConnected()) {
            throw new IOException("already connected");
        }

        BluetoothSocket fallbackSocket = null;
        boolean isConnectionEstablished = false;

        BluetoothDevice device = bluetoothAdapter.getRemoteDevice(mRemoteAddress);
        if (device == null) {
            throw new IOException("device not found");
        }

        mBluetoothSocket = device.createRfcommSocketToServiceRecord(DEFAULT_UUID); // @TODO . introduce ConnectionMethod
        if (mBluetoothSocket == null) {
            throw new IOException("socket connection not established");
        }

        // Cancel discovery, even though we didn't start it
        bluetoothAdapter.cancelDiscovery();

        if (mFirstConnection == 0)
            mFirstConnection = 1;
        try {
            mBluetoothSocket.connect();
            isConnectionEstablished = true;
        } catch (IOException ioException) {
            Log.e(TAG, "IO exception: " + ioException.getMessage());
          
            try {
                Class<?> clazz = mBluetoothSocket.getRemoteDevice().getClass();
                Class<?>[] paramTypes = new Class<?>[] {Integer.TYPE};
                Method m = clazz.getMethod("createRfcommSocket", paramTypes);
                Object[] params = new Object[] {Integer.valueOf(1)};
                mFallBackSocket = (BluetoothSocket)m.invoke(mBluetoothSocket.getRemoteDevice(), params);
                mBluetoothSocket = mFallBackSocket;
                if (mBluetoothSocket != null) {
                    mBluetoothSocket.connect();
                    isConnectionEstablished = true;
                }else{
                    Log.d(TAG, "fallback_socket received null....: " + mBluetoothSocket);
                }
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | IOException e) {
                Log.e(TAG, "exception_in_code....: " + e);
                e.printStackTrace();
            }
        }

        if (isConnectionEstablished) {
            connectionThread = new ConnectionThread(mBluetoothSocket);
            connectionThread.start();
        } else {
            if (mFirstConnection == 1) {
                mFirstConnection = 2;
                resetFallBackSocket();
                reconnectSocket();
            } else if (mFirstConnection == 2) {
                mFirstConnection = 3;
                resetFallBackSocket();
                reconnectSocket();
            } else {
                mFirstConnection = 0;
                resetFallBackSocket();
                throw new IOException("socket connection not established...");
            }
        }
    }

public void resetFallBackSocket() {
        mFallBackSocket = null;
    }

reconnectSocket is the function in which the Input and Output streams and Socket is closed manually and connection is tried again.

public void reconnectSocket() throws IOException  {
        Log.e(TAG, "debug13. Reconnection Bluetooth socket..");
        dataLogsFinal = dataLogsFinal + "debug13. Reconnection Bluetooth socket..$";
        Log.d(TAG, "Reconnection Bluetooth socket...");
        if (mBluetoothSocket == null)
            throw new IOException("Bluetooth Socket is NULL!" + dataLogsFinal);

        StringBuilder errorBuilder = new StringBuilder();

        try {
            mBluetoothSocket.getInputStream().close();
        } catch (IOException | NullPointerException e) {
            e.printStackTrace();
            Log.e(TAG, "Error closing input stream: " + e.getMessage());
            errorBuilder.append("Error closing input stream: ").append(e.getMessage()).append(" | ");
        }

        try {
            mBluetoothSocket.getOutputStream().close();
        } catch (IOException | NullPointerException e) {
            e.printStackTrace();
            Log.e(TAG, "Error closing output stream: " + e.getMessage());
            errorBuilder.append("Error closing output stream: ").append(e.getMessage()).append(" | ");
        }

        try {
            mBluetoothSocket.close();
            Thread.sleep(1000);
        } catch (IOException | InterruptedException | NullPointerException e) {
            e.printStackTrace();
            Log.e(TAG, "Error closing bluetooth socket: " + e.getMessage());
            errorBuilder.append("Error closing bluetooth socket: ").append(e.getMessage()).append(" | ");
        }
        try {
            connect();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "Error starting service: " + e.getMessage());
            errorBuilder.append("Error starting service: ").append(e.getMessage());
            throw new IOException(errorBuilder.toString());
        }
    }

I've tried changing the channel value for the port ranging from 1-5 for the reflection method.

Port-1:- Most of the time the connection gets created. Port-2:- As soon as the device gets connected, it gets disconnected. Port-3:- Device gets connected but unexpected responses are received. Port-4:- java.io.IOException: bt socket closed, read return: -1 Port-5:- java.io.IOException: bt socket closed, read return: -1 How do we figure out that port number has to be used for creating the connection via the reflection method?

Previously we had faced a similar kind of issue with the native android app and the issue was resolved with the help of the exact same methods which I've mentioned above.

With all the possible tries, now ran out of ideas. Any help will be very much appreciated.

Thanks

vaibhiarora03 avatar Feb 09 '22 05:02 vaibhiarora03

@AgainPsychoX can you please help me out in this? Any help will be highly appreciated.

Thanks

vaibhiarora03 avatar Feb 09 '22 15:02 vaibhiarora03

@AgainPsychoX can you please help me out in this? Any help will be highly appreciated.

Thanks

RRohitM avatar Jun 16 '22 10:06 RRohitM

@RRohitM are you also facing the same issue? What's the occurrence pattern of the issue?

vaibhiarora03 avatar Jun 16 '22 10:06 vaibhiarora03

Hello @vaibhiarora03 please replace this code i have resolve this error

You can change BluetoothConnection.java class you can replace connect method

/// Connects to given device by hardware address (default UUID used) public void connect(String address) throws IOException { BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); BluetoothDevice device = btAdapter.getRemoteDevice(address); ParcelUuid[] uuids = (ParcelUuid[]) device.getUuids(); connect(address, uuids[0].getUuid()); }

RRohitM avatar Jun 17 '22 06:06 RRohitM

Hi @RRohitM thanks for sharing your input.

The nature and occurrence of this issue is something different for me. 1.For some users the code was working perfectly fine without any disconnection issue. 2.For some users, this error occurred randomly, sometime it worked and sometime if got error. After multiple tries it started working. 3.For some users, it was a complete blockage. Each time they attempted connection, this error occurred. Not even a single time the connection was made for them. The bluetooth devices used by all 3 user-type were almost similar and in some cases the devices were from the same manufacturer as well.

Were you facing a complete blockage with this error or was the error-case like mine?

Regards Vaibhav

vaibhiarora03 avatar Jun 17 '22 06:06 vaibhiarora03