简体   繁体   中英

Inputstream read on bluetooth socket hangs if not used

I am developing an Android app that communicates with a Bluetooth device.

The device continuously sends information to the phone, but I chose to only read the data when the user wants to: by pressing a start/stop button. A reading service is started/stopped every time, but the connection stays open.

The connection to the device works well, no matter how many times the start/stop button is pressed, but only as long the user doesn't let the app in a "stop" state more than 5 seconds.

If the user lets the app in "stop" state more than 5 seconds, the program will get stuck in inputstream.read() the next time "start" is pressed.

I have checked that the socket is still open. I know that read() is a blocking function, but in this case it should not block as the device is continuously sending data.

Has anyone encountered a similar problem? Is it possible that the problem really comes from the fact that the socket is not used during a few seconds?

Here is the bit of code that I use for acquiring the data:

public void start() {
        if (isStarted()) {
            return;
        }
        task = taskService.submit(new Runnable() {
            @Override
            public void run() {
                int value;
                channel.reset();
                try {
                    while ((value = in.read()) != -1 && !Thread.currentThread().isInterrupted()) {
                        channel.put((byte) (value & 0xFF));
                    }
                } catch (IOException e) {
                    Log.d("STRS", "IO error : " + e.getMessage(), e);
                }
            }
        });

    }

  public void stop() {
        if (!isStarted()) {
            return;
        }
        task.cancel();
    }

    public boolean isStarted() {
        return task != null && !task.isDone();
    }

I've had a similar problem with blocking read() from a Bluetooth socket and fixed the issue by spawning a new thread and calling read() in a tight loop, reading the data into a circular buffer. The thread you're currently calling read() on now reads data from the circular buffer so is non blocking eg

private class ReceiveThread extends Thread {

    private boolean running = true;

    public void stopThread() {
        running = false;
    }

    @Override
    public void run() {
        byte[] readBuffer = new byte[4 * 1024]; 

        while (running) {
            try {
                // write bytes directly into a circular buffer
                int numBytes = socket.read(readBuffer);

                if (numBytes > 0) {
                    circularBuffer.put(readBuffer, 0, numBytes);
                }
            } catch (InterruptedIOException e) {
                running = false;
            } catch (Exception e) {
                // swallow
            }
        }
    }
}

You can then read directly from the circular buffer

circularBuffer.get(buffer, 0, bytesToRead);

Google for circular buffer implementations in Java, there are many. Just make sure it's thread safe.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM