Java 如果未使用,蓝牙套接字上读取的Inputstream将挂起

Java 如果未使用,蓝牙套接字上读取的Inputstream将挂起,java,android,sockets,bluetooth,inputstream,Java,Android,Sockets,Bluetooth,Inputstream,我正在开发一款Android应用程序,它可以与蓝牙设备进行通信 该设备不断向手机发送信息,但我选择只在用户需要时读取数据:按下启动/停止按钮。每次都会启动/停止阅读服务,但连接保持打开状态 无论启动/停止按钮按下多少次,与设备的连接都能正常工作,但前提是用户不让应用程序处于“停止”状态超过5秒 如果用户让应用程序处于“停止”状态超过5秒,程序将在下次按下“开始”时卡在inputstream.read()中。 我检查过插座是否还开着。 我知道read()是一个阻塞函数,但在这种情况下,它不应该阻塞

我正在开发一款Android应用程序,它可以与蓝牙设备进行通信

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

无论启动/停止按钮按下多少次,与设备的连接都能正常工作,但前提是用户不让应用程序处于“停止”状态超过5秒

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

我检查过插座是否还开着。 我知道read()是一个阻塞函数,但在这种情况下,它不应该阻塞,因为设备正在连续发送数据

有没有人遇到过类似的问题?这个问题是否真的可能是因为插座在几秒钟内没有使用

以下是我用于获取数据的代码位:

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

Google对于Java中的循环缓冲区实现,有很多。只需确保它是线程安全的。

我猜您通过中断线程来停止从流中读取,这可能是一个问题。另外,您如何跟踪状态(已启动/已停止)?此函数位于一个读取服务中,用户每次按start/stop时都会创建/销毁该服务,因此每次都会创建和销毁线程。为什么这会是个问题?我编辑了我的帖子以包含isStarted函数。这可能是一个问题,因为另一个线程可以清除
线程的中断标志,但从您发布的代码来看,情况似乎并非如此。我看到的一个问题是,您没有使用任何类型的同步来设置/检查状态。但为什么这会使程序卡在read()函数中?只有在程序处于非活动状态几秒钟的情况下,TCP套接字也可能发生类似的情况,如果您不打算使用它,则应在进入后台时关闭连接。