0

I am getting java.io.IOException: read failed, socket might closed or timeout, read ret: -1 this error for 2-3 days and not able to resolve it. I tried other solutions on stackoverflow but they didn't work. It seems that problem is generated at socket.connect(); When I followed the methods, I found out that the error is thrown by this piece of code in library:

private int readAll(InputStream is, byte[] b) throws IOException {
    int left = b.length;
    while (left > 0) {
        int ret = is.read(b, b.length - left, left);
        if (ret <= 0) {
            throw new IOException("read failed, socket might closed or timeout, read ret: "
                    + ret);
        }
        left -= ret;
        if (left != 0) {
            Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left)
                    + ", expect size: " + b.length);
        }
    }
    return b.length;
}

I am not able to debug it even after trying so many times.

public void run(){
    Log.i("UUID",device.getUuids()[0].getUuid().toString());
    Log.i("TAG", "BEGIN mConnectThread");
    // Always cancel discovery because it will slow down a connection
    bluetoothAdapter.cancelDiscovery();

    try{
        Log.i("TAG","Connecting to socket...");
        socket.connect();
    }catch (IOException e){
        Log.e("Connect->Run:",e.toString());
//                e.printStackTrace();
        try{
            Log.i("TAG","Trying fallback...");
            socket = (BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(device,1);
            socket.connect();
            Log.i("TAG","Connected");
        }catch (IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException er){
            Log.i("TAG","Cannot connect");
            try{
                socket.close();
            } catch (IOException ex) {
                Log.e("Connect->Close:",er.toString());
                ex.printStackTrace();
            }
            connectionFailed();
            return;
        }

    }
    ChatUtils.this.start();
    synchronized ( ChatUtils.this){
        connectThread = null;
    }

    connected(device);
}

This is where I am trying to connect to the socket. And following is my whole file:

package com.example.robomonkee_bt;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.content.Context;
import android.os.Message;
import android.util.Log;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.UUID;

public class ChatUtils {

    private Context context;
    private final Handler handler;
    private BluetoothAdapter bluetoothAdapter;
    private ConnectThread connectThread;
    private AcceptThred acceptThred;

    private final String APP_NAME = "RoboMonkee-bt";
    private final UUID APP_UUID = UUID.fromString("0000110a-0000-1000-8000-00805f9b34fb");

    public static final int STATE_NONE = 0;
    public static final int STATE_LISTEN = 1;
    public static final int STATE_CONNECTING = 2;
    public static final int STATE_CONNECTED = 3;

    public int state;

    public ChatUtils(Context context, Handler handler){
        this.context = context;
        this.handler = handler;

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        state = STATE_NONE;
    }

    public int getState() {
        return state;
    }

    public synchronized void setState(int state) {
        this.state = state;
        handler.obtainMessage(MainActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
    }

    private synchronized void start(){
        if(connectThread != null){
            connectThread.cancel();
            connectThread = null;
        }

        if(acceptThred == null){
            acceptThred = new AcceptThred();
            acceptThred.start();
        }

        setState(STATE_LISTEN);
    }

    public synchronized void stop(){
        if(connectThread!= null){
            connectThread.cancel();
            connectThread = null;
        }
        if(acceptThred != null){
            acceptThred.cancel();
            acceptThred = null;
        }

        setState(STATE_NONE);
    }
    public void connect(BluetoothDevice device){
        if(state == STATE_CONNECTING){
            if (connectThread != null) {
                connectThread.cancel();
                connectThread = null;
            }
        }
        connectThread = new ConnectThread(device);
        connectThread.start();

        setState(STATE_CONNECTING);

    }

    private class AcceptThred extends Thread{
        private BluetoothServerSocket serverSocket;

        public AcceptThred(){
            BluetoothServerSocket tmp = null;
            try{
                tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(APP_NAME, APP_UUID);
            }catch(IOException e){
                Log.e("Accept->Constructor:",e.toString());
            }

            serverSocket = tmp;

        }

        public void run(){
            BluetoothSocket socket = null;
            while (state != STATE_CONNECTED) {
                try {
                    socket = serverSocket.accept();
                } catch (IOException e) {
                    Log.e("Accept->Run:",e.toString());

                }
            }

            if(socket != null){
                switch (state){
                    case STATE_LISTEN:
                    case STATE_CONNECTING:
                        connect(socket.getRemoteDevice());
                        break;
                    case STATE_NONE:
                    case STATE_CONNECTED:
                        try{
                            socket.close();
                        }catch (IOException e){
                            Log.e("Accept-> Close Socket", e.toString());
                        }
                }
            }
        }

        public void cancel(){
            try{
                serverSocket.close();
            }catch (IOException e){
                Log.e("Accpet-> Close Server",e.toString());
            }
        }

    }

    private class ConnectThread extends Thread{
        private BluetoothSocket socket;
        private final BluetoothDevice device;

        public ConnectThread(BluetoothDevice device){
            this.device = device;

            BluetoothSocket tmp = null;
            try{
                tmp = device.createRfcommSocketToServiceRecord(APP_UUID);
            }catch (IOException e){
                Log.e("Connect->Constructor:",e.toString());
            }

            socket = tmp;
        }
        public void run(){
            Log.i("UUID",device.getUuids()[0].getUuid().toString());
            Log.i("TAG", "BEGIN mConnectThread");
            // Always cancel discovery because it will slow down a connection
            bluetoothAdapter.cancelDiscovery();

            try{
                Log.i("TAG","Connecting to socket...");
                socket.connect();
            }catch (IOException e){
                Log.e("Connect->Run:",e.toString());
        //                e.printStackTrace();
                try{
                    Log.i("TAG","Trying fallback...");
                    socket = (BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(device,1);
                    socket.connect();
                    Log.i("TAG","Connected");
                }catch (IOException | NoSuchMethodException | IllegalAccessException | InvocationTargetException er){
                    Log.i("TAG","Cannot connect");
                    try{
                        socket.close();
                    } catch (IOException ex) {
                        Log.e("Connect->Close:",er.toString());
                        ex.printStackTrace();
                    }
                    connectionFailed();
                    return;
                }

            }
            ChatUtils.this.start();
            synchronized ( ChatUtils.this){
                connectThread = null;
            }

            connected(device);
        }
        public void cancel(){
            try{
                socket.close();
            }catch (IOException e){
                Log.e("Connect->Close:",e.toString());
            }
        }
    }
    private synchronized void connectionFailed(){
        Message message = handler.obtainMessage(MainActivity.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(MainActivity.TOAST, "Can't connect to device");
        message.setData(bundle);
        handler.sendMessage(message);

        ChatUtils.this.start();
    }
    private synchronized void connected(BluetoothDevice device){
        if (connectThread!=null){
            connectThread.cancel();
            connectThread = null;
        }

        Message message = handler.obtainMessage(MainActivity.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(MainActivity.DEVICE_NAME, device.getName());
        message.setData(bundle);
        handler.sendMessage(message);

        setState(STATE_CONNECTED);
    }
}

I got the UUID from device.getUuids()[0].getUuid(); Also, I would like to add that when I attempt to connect, it gets connected for 2-3 seconds and then gets disconnected again. I can see on another device that it gets connected and then gets disconnected automatically. I have already tried all the solutions at IOException: read failed, socket might closed - Bluetooth on Android 4.3 . Please help.

virteanchi
  • 169
  • 1
  • 14
  • `I am getting this error for 2-3 days` About which error are you talking? Put all info in your post please. – blackapps May 01 '21 at 10:41
  • `ChatUtils.this.start();` Before that line you try to connect and catch a lot of possible exceptions which is very good. But... if there was an exception you still call ChatUtils.this.start();. No good. You should stop/return then. – blackapps May 01 '21 at 10:46
  • Yes but that won't solve the main problem right? – virteanchi May 01 '21 at 10:50
  • That i do not know as i do not know how all goes and what all happens. I do not know if you got those exceptions. Please adapt your code (also here) and then try again. – blackapps May 01 '21 at 10:51
  • Do you want me to post the whole project's code? I am getting only one IOException which I have titled in question. – virteanchi May 01 '21 at 10:55
  • No. I only like you to adapt the code the way i proposed. And you are throwing that exception yourself. So the real problem is different. You better tell when and why you throw that exception. And.. what library are you talking about? Should not you have that mentioned before? – blackapps May 01 '21 at 10:56
  • No! I am not throwing that exception. It is thrown by the inbuilt library which I have imported. The `readAll()` method is from the inbuild Bluetooth library and not my own method. – virteanchi May 01 '21 at 10:59
  • Can be but which library are you talking about? And if that library throws that exception then still you could better tell why and when that library throws it. Get to the real problem! But .... first adapt your code... – blackapps May 01 '21 at 11:01
  • The inbuilt Bluetooth library of android. Forgive me if I am using the wrong word. What you mean by adapting my code? – virteanchi May 01 '21 at 11:03
  • My god... read my second comment: `No good. You should stop/return then.` – blackapps May 01 '21 at 11:04
  • If I use `ChatUtils.this.start();` after return statement, it won't be reachable right? – virteanchi May 01 '21 at 12:03
  • 1
    I dont know what you mean. And i asked you to update your code here. Only then we can see what you did. – blackapps May 01 '21 at 12:04
  • I did the changes. – virteanchi May 01 '21 at 12:07
  • But now you also return when the second call to socket.connect(); goes ok – blackapps May 01 '21 at 12:15
  • Should I move the `return` statement to the upper catch block? – virteanchi May 01 '21 at 12:22
  • What you have to do is that you return if you cannot connect. How you implement that is up to you. – blackapps May 01 '21 at 12:34
  • Okay. I've done it properly now. But error is not resolved yet. – virteanchi May 01 '21 at 17:42
  • I dont understand your code. `socket.connect();` That looks like a client socket which tries to connect with a server. `BluetoothServerSocket tmp = null;` But you want to be a server too? You should first explain what your app should do i think. – blackapps May 01 '21 at 18:11
  • `I am getting java.io.IOException: read failed, socket might closed or timeout, read ret: -1 ` That is thrown after `int ret = is.read(b, b.length - left, left);` So what you should have asked is "Why is read() returning -1?". And where are you calling `readAll()` ? – blackapps May 01 '21 at 18:11
  • `ChatUtils.this.start(); synchronized ( ChatUtils.this){ connectThread = null; }` Why would you set that to null when you just started the bunch but nothing happened yet. – blackapps May 01 '21 at 18:15
  • As you can see I am assigning `device.createRfcommSocketToServiceRecord(APP_UUID);` to `tmp` variable below `BluetoothServerSocket tmp = null;`. I want to communicate with bluetooth module hc05 for which first of all I am trying to connect to a device which I am failing to do. – virteanchi May 02 '21 at 06:08
  • I know the exact place which is throwing the error. I am not calling the method `readAll()` explicitly but it is being called when I use `socket.connect();`. If you want how `conntect()` method leads to `readAll()` I'll tell you that too. But since that is inbuilt library code, it must be correct. – virteanchi May 02 '21 at 06:12
  • I am assigning `connectThread = null;` after having all things done. I want to stop all connection activities once I connect to device. I have referred Google's chat app example https://android.googlesource.com/platform/development/+/eclair-passion-release/samples/BluetoothChat/src/com/example/android/BluetoothChat/BluetoothChatService.java – virteanchi May 02 '21 at 06:14

0 Answers0