简体   繁体   English

用于捕获BluetoothSocket InputStream.read()超时的线程

[英]Thread to catch a BluetoothSocket InputStream.read() timeout

I have been using InputStream.read( byte[] b, int off, int len ) method to read in data, but now have run into a timeout problem. 我一直在使用InputStream.read( byte[] b, int off, int len )方法读入数据,但现在已经遇到了超时问题。 I am sometimes expecting timeouts from reading, and should have the program adjust itself accordingly after a timeout. 我有时会期待阅读超时,并且应该让程序在超时后相应地调整自己。 I have tried to implement a Thread but I really know nothing about Threads and cannot get it to work. 我试图实现一个Thread,但我对Threads一无所知,也无法让它工作。 I also want to add that this thread is being initialized within another thread . 我还想补充一点,这个线程正在另一个线程中初始化。 I'm not sure what the implications of this are but it may cause a problem. 我不确定这是什么意思,但它可能会导致问题。

My initial code had worked for the majority of times I need to read, but whenever I'm expecting a timeout, my program freezes at the read() call and never times out. 我的初始代码在我需要阅读的大部分时间都有效,但每当我预计超时时,我的程序会在read()调用时冻结,并且永远不会超时。 When I implemented this new code, the times when my initial code worked now time out. 当我实现这个新代码时,我的初始代码工作的时间现在超时了。 I use Thread.wait(500) which I assume is 500 milliseconds, but I cannot find any Javadocs including the wait() function. 我使用Thread.wait(500) ,我假设是500毫秒,但我找不到任何Javadocs,包括wait()函数。 Here and Here . 这里这里

Other posts relating to this: 1 , 2 , 3 . 有关此的其他职位: 123

I have also looked into declaring a timeout for the BluetoothSocket , but I cannot find it anywhere in the documentation . 我还考虑过声明BluetoothSocket的超时,但我在文档中的任何地方都找不到它。

Here is what my initial code looks like: 这是我的初始代码:

public void run(int length) throws IOException {
        buffer = new byte[1024];
        try {
                bytes = mmInStream.read(buffer, 0, length);
                mHandler.obtainMessage(MainMenu.MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();
        } catch (IOException e) {
                Message msg = mHandler.obtainMessage(MainMenu.MESSAGE_TOAST);
                Bundle bundle = new Bundle();
                bundle.putString( TOAST, "Device has disconnected from the Bluetooth Module." );
                msg.setData(bundle);
                mHandler.sendMessage(msg);
                connectionLost();
                BluetoothService.this.start();
        }

This is what I have tried to implement: 这是我试图实现的:

public void run(int length) throws IOException {
        buffer = new byte[1024];
        length1 = length;
        Thread myThread = new Thread(new Runnable() {
            public void run() {
                try {
                    bytes = mmInStream.read( buffer, 0, length1 );
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

        synchronized (myThread) {
            myThread.start();
            try {
                myThread.wait(500);
                if(myThread.isAlive()) {
                    mmInStream.close();
                    Log.i( "InStream", "Timeout exceeded!");
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
       try {
            myThread.run();
            mHandler.obtainMessage(MainMenu.MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();
       } catch (IOException e) {
                Message msg = mHandler.obtainMessage(MainMenu.MESSAGE_TOAST);
                Bundle bundle = new Bundle();
                bundle.putString( TOAST, "Device has disconnected from the Bluetooth Module." );
                msg.setData(bundle);
                mHandler.sendMessage(msg);
                connectionLost();
                BluetoothService.this.start();
       }

EDIT: 编辑:

So I'm trying to recreate 所以我正在尝试重新创建

buffer = new byte[1024];
bytes = mmInStream.read(buffer, 0, length);

I have done the following: 我做了以下事情:

Scanner scan = new Scanner(new InputStreamReader(mmInStream));
String readIn;
try {
    readIn = scan.next();
    bytes = 5; // I tried with or without this, since I do not think it matters...
    buffer = readIn.getBytes( Charset.forName( "US-ASCII" ) );
}

Later in my code I make this call....Sorry edit again, the buf=read( 5 ) call goes to what is shown above. 稍后在我的代码中我打了这个电话....抱歉再次编辑, buf=read( 5 )调用转到上面显示的内容。

byte[] buf  = buffer;
write( a );
buf = read( 5 );
Log.i(TAG,  "Before buf[5]" );
try {
     buf[5] = '\0';
} catch( NullPointerException e ) {
    return false;
}

When I use the original method, It passes this buf[5] call fine. 当我使用原始方法时,它会将此buf[5]调用通过。 But when I use the new method, it gives me an IndexOutOfBoundsException at that spot. 但是当我使用new方法时,它会在那个位置给我一个IndexOutOfBoundsException Am I missing something? 我错过了什么吗? The expected input should be CMD\\r\\n 预期输入应为CMD\\r\\n

The bluetooth chat example is really poor in this respect, you should use an input scanner instead of mmInStream.read. 蓝牙聊天示例在这方面确实很差,你应该使用输入扫描器而不是mmInStream.read。 Here's what I use and it works reasonably well... 这是我使用的,它运作得相当好......

For your use case you skip the entire buffer and byte and write and read (no need to use any of those when you are using a scanner and inputstreamreader as those handle that stuff for you)... in other words the below code takes care of all that for you. 对于您的用例,您可以跳过整个缓冲区和字节并进行写入和读取(当您使用扫描仪和输入流程读取器时,不需要使用任何这些,因为那些处理那些东西)...换句话说,下面的代码需要注意这一切都适合你。 I changed the delimiter for you to CRLF. 我把你的分隔符更改为CRLF。 What the code below does is you send a string and it writes it and then reads. 下面的代码是你发送一个字符串然后写入然后读取。 If you don't need to send anything to the remote device, just start at scan = new Scanner. 如果您不需要向远程设备发送任何内容,只需从scan = new Scanner开始。 Each time a line is read and it ends with \\r\\n it will store it in the string instring. 每次读取一行并以\\ r \\ n结束时,它会将其存储在字符串instring中。

So if you want to send "a", you would write 所以如果你想发送“a”,你会写

String readIn = beginListenForData("a");

The a will be sent under the mmOutStream and then the scanner will read the mmInStream and collect all the characters, then once it sees a CRLF it will return the characters it read and return them in your readIn string. a将在mmOutStream下发送,然后扫描器将读取mmInStream并收集所有字符,然后一旦看到CRLF,它将返回它读取的字符并将它们返回到readIn字符串中。 Make sense? 合理?

private String beginListenForData(String msg0) {
    msg0 += "\r"; //this adds a return character to the string, you can omit this if you just send an a and the remote device understands what that means.
    String instring = "";
    try {
        mmOutStream.write(msg0.getBytes());
    } catch (IOException ex) {              
        stop();
    }
    scan = new Scanner(new InputStreamReader(mmInStream));
    scan.useDelimiter(Pattern.compile("[\\r\\n]+"));
    instring = scan.next();
    scan = null;
    return instring;
}

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

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