Search code examples
androidarrayskotlinbluetoothinputstream

Android Bluetooth Socket Read String From InputStream Skips Lines


I am developing an Android bluetooth app that will have a terminal communication between Arduino and Android. The communication works but the inputstream reads and creates seperate strings from the bluetooth socket.

Ex. Command to be received in 1 line is: LED On

The current implementation I have gives me:
L
ED On

Or if longer string:
S
ervo Cente
R

val buffer = ByteArray(1024)
                var numBytes: Int
                inputStream = mSocket.inputStream
                while (mSocket.isConnected) {
                   
                    numBytes = inputStream.read(buffer)
                    mHandler.obtainMessage(
                        HandlerConstant.MESSAGE_READ,
                        String(buffer, 0, numBytes)
                    ).sendToTarget()
                }

Any suggestions would be greatly appreciated.

I have tried to read each byte into an array and create a string from that. I keep getting seperator lines.

Ex:
L
E
D

O
n

I looked at the Google Bluetooth Chat on how to implement and it is similar to what I am using.

Thinking maybe my threads were blocking, I tried utilizing the terminal on PC to send strings over bluetooth with the same result.

It seems I can't break from the inputStream.read(buffer) to validate or loop through received data before handing it over to the Handler.

I have also tried the below code with better success. When the string is a bit longer, the same issue happens.

Ex:
Servo Cente
r

val buffer = ByteArray(1024)
                var numBytes: Int
                inputStream = mSocket.inputStream
                while (true) {
                    loop = 0
                    val avail = inputStream.available()
                    if (avail > 1) {
                        numBytes = inputStream.read(buffer)
                        if(numBytes > 0) {
                            mHandler.obtainMessage(
                                HandlerConstant.MESSAGE_READ,
                                String(buffer, 0, numBytes)
                            ).sendToTarget()
                        }
                    }
                }

-----------UPDATE----------

I have attempted a different approach with better results but still same issue.

inputStream.buffered().read(buffer).let {
                    val sb = StringBuilder()
                    if (it > 0) {
                        sb.append(String(buffer, 0, it))
                    }
                    mHandler.obtainMessage(
                        HandlerConstant.MESSAGE_READ,
                        sb.toString()
                    ).sendToTarget()
                    sb.clear()

                }

It will reach each line without issue but if the line is over 10 characters longs, the problem starts again.

Ex.

Servo Left (No problem) Servo Cente
r (issue)


Solution

  • After different approaches, I found the issue may just the connections with the bluetooth device and the socket. I created an escape char in the data transmission to know when the stream is complete from the bluetooth device. Below works as expected.

                   var sb = StringBuilder()
                   inputStream.read().let {
                        if (it.toChar().toString() == "#") {
                            mHandler.obtainMessage(
                                HandlerConstant.MESSAGE_READ,
                                sb.toString()
                            ).sendToTarget()
                            sb.clear()
                        } else {
                            sb.append(it.toChar())
                        }
                    }
    

    Thanks for the help. This link helped me land on this approach Android Bluetooth InputStream read in realtime