0

In a program I'm working on, I have two devices talking to each other over Bluetooth. When the application is first started, both devices connect fine, but when the connection is severed and re-initialized (i.e. the server thread is killed and then recreated), it fails despite the BluetoothServerSocket readily accepting connections. On the server side I have

void handleConnection() throws Exception {
    bss = BluetoothAdapter.getDefaultAdapter().listenUsingRfcommWithServiceRecord(Constants.BITMAP_NAME,
                        UUID.fromString(Constants.BITMAP_UUID));
    running.set(true);
    Logger.logE("accepting");
    BluetoothSocket socket = bss.accept();
    Logger.logE("accepted");
    context.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            if (connectionCallback != null)
                connectionCallback.onConnectionMade();
        }
    });
    //handle connection in a loop...
    try {
        is.close();
        is = null;
    } catch (IOException ignored) {
        Logger.exception(ignored);
    }
    try {
        socket.close();
        socket = null;
    } catch (IOException ignored) {
        Logger.exception(ignored);
    }
}

And on the client side I have

void handleConnection() throws Exception {
    BluetoothSocket socket = connect.
            createRfcommSocketToServiceRecord(UUID.fromString(Constants.BITMAP_UUID));
    Logger.logE("preparing to connect");
    socket.connect();
    Logger.logE("Connected");
    if (connectionCallback != null) {
        context.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                connectionCallback.onConnectionMade();
            }
        });
        Logger.logE("callback fired");
    }
    //Handle the connection...
    Logger.logE("closing client");
    try {
        os.close();
        os = null;
    } catch (Exception ex) {
        Logger.exception(ex);
    }
    try {
        socket.close();
        socket = null;
    } catch (Exception ex) {
        Logger.exception(ex);
    }
}

After restarting the Server and attempting to reconnect, the client times out with the message

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

on the socket.connect(); line. I see the message preparing to connect in Logcat when monitoring the client, and the message accepting when monitoring the server, but it never advances beyond that point.

sjyn
  • 99
  • 2
  • 9
  • Could you elaborate "when the connection is severed and re-initialized" and at which statement the error (java.io.IOException: read failed, socket might closed or timeout, read ret: -1) is thrown? – solosodium Jun 28 '16 at 18:23
  • @solosodium updated it for you. – sjyn Jun 28 '16 at 18:27

1 Answers1

1

The client side code seems fine. I think the problem is from the server.

If you go to Android documentation for Bluetooth, you will see an example for Bluetooth server:

private class AcceptThread extends Thread {
    private final BluetoothServerSocket mmServerSocket;

    public AcceptThread() {
        // Use a temporary object that is later assigned to mmServerSocket,
        // because mmServerSocket is final
        BluetoothServerSocket tmp = null;
        try {
            // MY_UUID is the app's UUID string, also used by the client code
            tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
        } catch (IOException e) { }
        mmServerSocket = tmp;
    }

    public void run() {
        BluetoothSocket socket = null;
        // Keep listening until exception occurs or a socket is returned
        while (true) {
            try {
                socket = mmServerSocket.accept();
            } catch (IOException e) {
                break;
            }
            // If a connection was accepted
            if (socket != null) {
                // Do work to manage the connection (in a separate thread)
                manageConnectedSocket(socket);
                mmServerSocket.close();
                break;
            }
        }
    }

    /** Will cancel the listening socket, and cause the thread to finish */
    public void cancel() {
        try {
            mmServerSocket.close();
        } catch (IOException e) { }
    }
}

The point being you need to run the server in a thread to keep track of all the incoming connections. As you need the handle of incoming socket for communication.

It's also very important to remember to CLOSE THE SOCKET when you are done with communication. Not properly closed socket may result in dangling hardware connection without the software layer knowing, which could also be the cause of your current problem (it's inconclusive due to the lack of the code for actual communication). Please see this post for more information.

Community
  • 1
  • 1
solosodium
  • 723
  • 5
  • 15
  • You were 100% right. I believe that the socket wasn't being closed properly, which was having the exact effect you described. – sjyn Jun 29 '16 at 11:57