繁体   English   中英

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

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

我正在开发一个与蓝牙设备通信的 Android 应用程序。

设备不断地向手机发送信息,但我选择仅在用户需要时读取数据:按开始/停止按钮。 每次都会启动/停止阅读服务,但连接保持打开状态。

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

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

我已经检查过插座是否仍然打开。 我知道 read() 是一个阻塞函数,但在这种情况下它不应该阻塞,因为设备不断发送数据。

有没有人遇到过类似的问题? 问题真的有可能是因为socket在几秒钟内没有被使用吗?

这是我用于获取数据的代码:

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();
    }

我在阻止来自蓝牙套接字的 read() 时遇到了类似的问题,并通过生成一个新线程并在紧密循环中调用 read() 将数据读入循环缓冲区来解决该问题。 您当前正在调用 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
            }
        }
    }
}

然后您可以直接从循环缓冲区中读取

circularBuffer.get(buffer, 0, bytesToRead);

谷歌在 Java 中的循环缓冲区实现,有很多。 只要确保它是线程安全的。

暂无
暂无

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

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