Kotlin读取Bluetooth InputStream时首字符丢失问题如何解决?
蓝牙接收首字符丢失问题解决方案
常见原因与修复方式
- 连接阶段多余读操作
该问题占此类故障的80%以上:检查启动BTConnected线程之前的蓝牙连接校验逻辑,是否存在单次调用inputStream.read()的测试代码、或者其他读取流内容的逻辑。这类操作会消费流中的第一个字节,后续线程循环读取时自然会丢失首字符,直接删除该类多余读操作即可修复。 - 缓冲区复用异步覆盖问题
当前代码所有读取操作复用同一个BTbuffer字节数组,且直接将数组引用传给异步处理的Handler。如果读取速度快于Handler处理速度,新的读取内容会覆盖还未完成处理的数组数据,首字节大概率被提前覆盖。
修复代码如下:inner class BTConnected(BTSCT:BluetoothSocket): Thread(){ private val BTINstream:InputStream = BTSCT.inputStream private val BTOUTstream:OutputStream = BTSCT.outputStream private var BTbuffer = ByteArray(1024) override fun run(){ var Bytes:Int = 0 while (true) { try{ Bytes = BTINstream.read(BTbuffer) } catch (IOE:IOException){ break } // 拷贝有效长度的字节到新数组,避免复用缓冲区导致的数据覆盖 val validBuffer = BTbuffer.copyOf(Bytes) val readMsg = myHandler.obtainMessage(MESSAGE_READ, Bytes, -1, validBuffer) readMsg.sendToTarget() } } } - 字符编码不匹配问题
确认电脑端发送字符串使用的字符编码和Android端解码编码一致,默认String构造方法在Android中使用UTF-8编码,若电脑端使用GBK、ASCII等其他编码,可能出现首字节截断问题,可指定编码解码:val myHandler = object: Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { when(msg.what){ MESSAGE_READ -> { val readBuff = msg.obj as ByteArray // 按需替换为和发送端一致的编码即可 val tempMsg = String(readBuff, Charset.forName("UTF-8")) PrintMessage(tempMsg) } // ...rest of code - 发送端附加控制字节问题
部分串口/蓝牙调试工具发送数据时会自动附加起始位、校验位等不可见控制字节,可在Handler中增加字节日志确认是否真的丢失首字节:Log.d("蓝牙接收原始数据", readBuff.joinToString(" ") { byte -> "%02X".format(byte) })
内容的提问来源于stack exchange,提问作者Vašek Doškář
相关产品推荐
相关产品推荐

