如何在Android Studio中通过蓝牙读取ESP32数据?解决APP冻结问题
问题分析与解决方案
核心问题
APP冻结的直接原因是mmInStream.read()是阻塞式IO操作,如果在主线程调用这个方法,会直接卡住UI线程,导致APP失去响应。另外代码里还有两个明显逻辑问题:
receber方法用传入的dadosLidos字符串转字节数组当读取缓冲区,逻辑完全错误,应该创建独立的读取缓冲区。- 直接在IO操作线程里调用
Toast.makeText,Android不允许子线程更新UI,会触发异常。
修复步骤
- 将蓝牙读取操作移到子线程:永远不要在主线程执行阻塞式IO(蓝牙、网络读写等)。
- 修正读取缓冲区逻辑:创建固定大小的字节数组作为读取缓冲区,不要依赖传入的字符串。
- 通过主线程更新UI:所有UI操作(Toast、更新TextView等)必须切换到主线程执行。
修改后的代码示例
public class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; private final Context mContext; private static final String TAG = "BluetoothThread"; public ConnectedThread(BluetoothSocket socket, Context context) { mmSocket = socket; mContext = context; InputStream tmpIn = null; OutputStream tmpOut = null; try { tmpIn = socket.getInputStream(); } catch (IOException e) { Log.e(TAG, "创建输入流失败", e); } try { tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "创建输出流失败", e); } mmInStream = tmpIn; mmOutStream = tmpOut; // 启动子线程自动持续读取数据 start(); } @Override public void run() { byte[] buffer = new byte[1024]; // 1KB缓冲区,可根据ESP32发送的数据大小调整 int bytesRead; // 持续读取直到连接断开 while (true) { try { // 阻塞式读取,有数据时才会返回 bytesRead = mmInStream.read(buffer); final String receivedData = new String(buffer, 0, bytesRead); // 切换到主线程更新UI ((Activity) mContext).runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(mContext, receivedData, Toast.LENGTH_SHORT).show(); // 这里可以添加更新TextView等UI组件的代码 } }); } catch (IOException e) { Log.e(TAG, "读取失败,连接可能已断开", e); break; } } } public void enviar(String dadosEnviar) { byte[] msgBuffer = dadosEnviar.getBytes(); try { mmOutStream.write(msgBuffer); } catch (IOException e) { Log.e(TAG, "发送数据失败", e); } } // 关闭连接,释放资源 public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "关闭套接字失败", e); } } }
额外说明
- 无需手动调用读取方法,
ConnectedThread会自动在子线程持续监听ESP32发送的数据。 - 当不需要蓝牙连接时,务必调用
cancel()方法关闭套接字,避免资源泄漏。 - 如果ESP32发送的数据有特定结束符(比如换行符
\n),可以在读取时按结束符分割数据,避免粘包问题。
内容的提问来源于stack exchange,提问作者Elvio Prado
相关产品推荐
相关产品推荐

