android - bluetooth adapter - message handler buff

2019-07-13 23:10发布

问题:

I'm using this tutorial for building a multiplayer game that uses Bluetooth for connection:

https://developer.android.com/samples/BluetoothChat/index.html

Since I'm sending long stings in JSON format (like 5500+ in length) the message handler method is not returning the entire strings I send, and instead it splits them into 989 character long strings (its always 989 characters in length). The problem is, when I try to parse the JSON string, obviously it throws an error, because the text is not complete. When I print out the string in console, it prints them in multiple rows split by 989 characters.

Also please note that the Buffer length is set to 1024, but when I increase the limit, the result won't differ, and its always 989 characters.

byte[] buffer = new byte[1024];

Any idea what's going on? Here's the message handler method. Note that the sent message form the host device looks fine (its not split), but when the client receives it, its split into multiple strings.

private static final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case BluetoothService.MESSAGE_STATE_CHANGE:
                switch (msg.arg1) {
                    case BluetoothService.STATE_CONNECTED:
                    case BluetoothService.STATE_CONNECTING:
                    case BluetoothService.STATE_LISTEN:
                    case BluetoothService.STATE_NONE:
                        break;
                }
                break;
            case BluetoothService.MESSAGE_WRITE:
                // BYTE LENGTH IS OK IN HERE!
                byte[] writeBuf = (byte[]) msg.obj;
                String writeMessage = new String(writeBuf);
                break;
            case BluetoothService.MESSAGE_READ:
                // BYTE LENGTH IS 1024 IN HERE!
                byte[] readBuf = (byte[]) msg.obj;
                message = new String(readBuf, 0, msg.arg1);
                break;
        }
    }
};

回答1:

Data passed through a Bluetooth socket is abstracted as a stream, but at the transport layer is broken into packets, which have a maximum size of roughly 1000 bytes. On the sender side, your can get the output stream and write a 5 Kbyte chunk of data, but the transport layer will break it into multiple packets before sending over the air. When the receiver reads its input stream, each call to read() will return the data for one packet. The transport layer does not reassemble the packets, your code needs to do that. This means you need to devise some scheme, such as a message header that contains the length of your message, which the receiver can to know when stop assembling packets and hand the complete message off to the consuming processing.

This issue is not addressed in the BluetoothChat sample app because it (silently) assumes that all chat messages will be smaller than the packet size, so no message reassembly is needed.