Android InputStream dropping first two bytes (modified BluetoothChat)

后端 未结 5 924
长情又很酷
长情又很酷 2020-12-05 12:47

I\'ve used code from BluetoothChat example to send and receive byte data from a Bluetooth Scale. The scale receives the command from the device, then sends back a byte array

相关标签:
5条回答
  • 2020-12-05 12:54

    Not sure why this is happening, but it may be some weird race condition. One of the problems with your code is that it wants to read all the time data! Even when no data is there.

    So maybe you read the first 2 bytes, then a subsequent iteration you read the input buffer again without the first 2 bytes (the debugger shows you the wrong picture in this case).

    What you can try to improve is by adding these lines(don't try to copy paste, I am adapting the code to your previous one - it may or may not work):

    bytes = mmInStream.getAvailable();
    if (bytes>0) {
        Log.i("some hardcoded tag", "I am reading " + Integer.toString(bytes) + " bytes");
        //you could also print the entire bytearray
        /*
        Log.i("some hardcoded tag", "The entire array:");
        for(int i=0; i<bytes; i++)
             Log.i("some hardcoded tag", buffer[i] + " ");*/
        mmInStream.read(buffer);
    
        //and your code ..
        // Send the obtained bytes to the UI Activity
        mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget();
    
    }
    

    Notice I use Log.i instead of the debugger. It's better for multithreaded stuff if you can implement the logs and they don't bother you - plus it's faster to execute and more easy to debug.

    0 讨论(0)
  • 2020-12-05 12:54

    I was in the same position as you a few weeks ago.

    I discovered The read count is random when using read(buffer). So you will never truly predict how big the next data packet will be.

    The simple fix for me was to read a single byte at a time using read() and add it to a local buffer until every byte is received.

    Hope this helps.

    0 讨论(0)
  • 2020-12-05 13:06

    As said before the data is not guaranteed, bluetooth is an open stream of data like UDP.

    I suppose some understanding of rs232 is needed to know when bytes will be packaged together, or sent individually.

    with a microcontroller project, imagine something like:

    if (data_ready) echo read_byte();
    

    with PIC microchips, the resulting data is something like:

    0 0 0 0 0 0 0 h 0 0 0 0 e 0 0 0 0 0 0 l 0 0 0 0 0 0 l 0 0 0 0 0 0 o ...
    

    With the Android to microcontroller project I'm working on at the moment I'm doing something like:

    do {instream.read()} while (!DELIMETER)
    

    I've found that you need to be efficient with your code when reading a bluetooth data stream. Using inputstream methods other than read(), I would almost always miss the first byte.

    I've just started with bluetooth smart, which I guess is quite different since data is only sent when it's available.

    0 讨论(0)
  • 2020-12-05 13:14

    I have seen people run into this sort of problem before when using the Bluetooth Chat example. The problem with the example code is that the message object that is sent to the Handler simply contains a reference to the actual byte[] array that is used for each subsequent read() operation. This means that as soon as the Handler obtains the message and starts inspecting the array, the subsequent read() operation on the Bluetooth socket has already had the opportunity to write newer data to that array.

    In this line of code:

    mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget()
    

    The array is not being copied; but rather the message is simply conveying an object reference to the same array.

    The only reason why the Bluetooth Chat example works for its original purpose is because its purpose is to convey short bunches of characters at human typing speed. If you send anything faster than that, what the Handler reads from that array turns to garbage.

    The answer is to send a copy of the array (e.g. System.arraycopy()) or use a simple circular buffer, which is what my own Bluetooth application uses.

    The fact that the first two bytes are being mangled is a strange one, but it could just be down to the specific implementation of the underlying read operation in the Bluetooth stack on your particular device. The simple fact is that once you have called read() with that buffer, you should not be touching that buffer in the meantime or caring what's in it. Perhaps the particular Bluetooth socket read implementation on your device does something with those first few bytes in the buffer because of something to do with its internal operation. But you should not care what kind of funny intermediate state the buffer is in while read() is blocking, because no other thread should be trying to make sense of it at that time. All you care about is that the buffer is in a valid state with valid data when read() returns.

    The reason why using the sleep() operation apparently partly "cures" the problem is because it's a crude way of giving your Handler time to look at the array before the subsequent read() operation gets its hands on the array. This is not a good solution though.

    The second issue you have is due to the fact that in Java, byte is signed. That's why the debugger shows you the bytes as signed values. In your application, if you need to work with a given byte as an int and the byte is originally unsigned, you do something like:

    int someValue = myByteArray[someIndex] & 0xff;
    
    0 讨论(0)
  • 2020-12-05 13:17

    I think the issue you are seeing with e.g. the 198 turning into -58 is because Java uses signed bytes, so anything over 127 is a negative number. So 198 binary is seen as -(256 - 198) = -58.
    The solution is to convert it to an int using some code like the following:

    private int UByte(byte b){
            if(b<0) // if negative
                return (int)( (b&0x7F) + 128 );
            else
                return (int)b;
        }
    
    0 讨论(0)
提交回复
热议问题