简体   繁体   中英

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. 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. 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. 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. Here and Here .

Other posts relating to this: 1 , 2 , 3 .

I have also looked into declaring a timeout for the BluetoothSocket , but I cannot find it anywhere in the documentation .

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.

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. But when I use the new method, it gives me an IndexOutOfBoundsException at that spot. Am I missing something? The expected input should be CMD\\r\\n

The bluetooth chat example is really poor in this respect, you should use an input scanner instead of 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. 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. Each time a line is read and it ends with \\r\\n it will store it in the string instring.

So if you want to send "a", you would write

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. 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;
}

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