Android蓝牙接收Arduino发送字符X失败问题排查咨询
问题根因
Android端无法收到Arduino发送的X字符、无法实现对应标签更新,由3个代码逻辑问题直接导致:
- 数据接收被复选框状态拦截:现有逻辑只有勾选
chkReceiveText复选框时才会处理读到的蓝牙数据,未勾选状态下所有收到的数据都会被直接丢弃,不会进入任何业务判断流程 - 流读取逻辑存在漏读缺陷:当前采用
inputStream.available() > 0加50ms线程休眠的轮询方式读数据,单字节短字符(比如单个X)很容易在轮询间隙被漏掉;另外代码中定义的ComunicaThread类从未被实例化调用,属于冗余无效代码 - 缺失字符匹配与标签更新逻辑:现有代码读到数据后仅会向
mTxtReceive文本框追加内容,没有对收到的内容做字符判断,自然无法触发「收到X时标签显示123」的逻辑
修复方案
按以下顺序修改代码即可:
- 移除数据处理对复选框状态的强依赖:所有收到的蓝牙数据先进入字符匹配流程,再根据复选框状态决定是否追加到接收文本框
- 替换蓝牙流读取逻辑:改用阻塞式读方法替代轮询+休眠的方案,从根本上避免单字节数据漏读问题
- 增加字符匹配分支:读到包含
X的内容时,直接更新目标标签文本为123 - 删除未使用的
ComunicaThread冗余类,避免不必要的流资源冲突
核心修改代码
将原有ReadInput类的run方法替换为以下实现:
@Override public void run() { InputStream inputStream; try { inputStream = mBTSocket.getInputStream(); byte[] buffer = new byte[256]; int bytesRead; // 阻塞式读取,无数据时线程挂起,不会漏读 while (!bStop && (bytesRead = inputStream.read(buffer)) != -1) { // 按实际读到的字节长度转字符串,剔除首尾空白字符避免匹配失败 final String strInput = new String(buffer, 0, bytesRead).trim(); // 切到主线程更新UI runOnUiThread(new Runnable() { @Override public void run() { // 匹配收到的X字符,更新标签 if(strInput.contains("X")){ // 替换为你实际用来显示123的标签控件ID durum.setText("123"); } // 根据复选框状态决定是否展示接收到的原始文本 if (chkReceiveText.isChecked()) { mTxtReceive.append(strInput); int txtLength = mTxtReceive.getEditableText().length(); if(txtLength > mMaxChars){ mTxtReceive.getEditableText().delete(0, txtLength - mMaxChars); } if (chkScroll.isChecked()) { scrollView.post(new Runnable() { @Override public void run() { scrollView.fullScroll(View.FOCUS_DOWN); } }); } } } }); } } catch (IOException e) { e.printStackTrace(); } }
额外注意事项
- 确认蓝牙连接使用的是标准SPP串口UUID:
00001101-0000-1000-8000-00805F9B34FB,UUID配置错误会导致收发异常 - 安卓6.0及以上版本需要动态申请
BLUETOOTH_CONNECT、BLUETOOTH_SCAN、ACCESS_FINE_LOCATION权限,权限缺失会导致蓝牙读操作静默失败 - Arduino端发送
X时如果携带了换行、回车等特殊字符,使用contains("X")的匹配方式不受影响,不需要严格匹配全量字符串
内容的提问来源于stack exchange,提问作者Aslan Bey
相关产品推荐
相关产品推荐

