简体   繁体   English

如果不使用,则在蓝牙套接字上读取的输入流会挂起

[英]Inputstream read on bluetooth socket hangs if not used

I am developing an Android app that communicates with a Bluetooth device.我正在开发一个与蓝牙设备通信的 Android 应用程序。

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.无论按下多少次开始/停止按钮,与设备的连接都运行良好,但前提是用户不会让应用程序处于“停止”状态超过 5 秒。

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.如果用户让应用程序处于“停止”状态超过 5 秒,程序将在下次按下“开始”时卡在 inputstream.read() 中。

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.我知道 read() 是一个阻塞函数,但在这种情况下它不应该阻塞,因为设备不断发送数据。

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?问题真的有可能是因为socket在几秒钟内没有被使用吗?

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.我在阻止来自蓝牙套接字的 read() 时遇到了类似的问题,并通过生成一个新线程并在紧密循环中调用 read() 将数据读入循环缓冲区来解决该问题。 The thread you're currently calling read() on now reads data from the circular buffer so is non blocking eg您当前正在调用 read() 的线程现在从循环缓冲区读取数据,因此是非阻塞的,例如

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.谷歌在 Java 中的循环缓冲区实现,有很多。 Just make sure it's thread safe.只要确保它是线程安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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