Android蓝牙Native模块连接报错:read failed,socket可能关闭或超时
解决BluetoothSocket连接错误「read failed , socket might closed or timeout, read ret -1」及配对相关问题
一、错误「read failed...」的常见修复点
1. 补全蓝牙权限
Android不同版本对蓝牙权限要求不同,必须确保Manifest声明和运行时权限申请都完成:
- Android 12及以下:需声明
BLUETOOTH、BLUETOOTH_ADMIN权限 - Android 12+:需声明
BLUETOOTH_CONNECT、BLUETOOTH_SCAN权限
注意BLUETOOTH_CONNECT属于敏感权限,必须在运行时动态申请。
2. 处理设备配对状态
你的代码显示了设备bondState但未做逻辑处理,多数经典蓝牙设备需要配对后才能建立Socket连接:
// 连接前检查配对状态 if (device.getBondState() == BluetoothDevice.BOND_NONE) { // 触发配对流程 boolean isBondingStarted = device.createBond(); // 需注册BroadcastReceiver监听配对结果,配对成功后再执行connect() }
3. 确保UUID匹配
你使用的是通用SPP服务UUID(00001101-0000-1000-8000-00805F9B34FB),但并非所有设备都支持。可以通过以下代码获取设备实际支持的UUID列表:
ParcelUuid[] uuids = device.getUuids(); if (uuids != null) { for (ParcelUuid uuid : uuids) { Log.d("Bluetooth", "Supported UUID: " + uuid.getUuid()); } }
替换为设备支持的UUID后再尝试连接。
4. 避免主线程阻塞
socket.connect()是耗时操作,直接在@ReactMethod中调用会阻塞主线程导致超时,必须放到子线程执行:
@ReactMethod public void connectToDevice(String address, Callback callback) { new Thread(() -> { BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); if (device == null) { callback.invoke("Device not found"); return; } if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } try { BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); socket.connect(); callback.invoke(null, "Connected"); } catch (IOException e) { callback.invoke(e.getMessage()); } }).start(); }
5. 关闭旧Socket连接
如果之前存在未关闭的Socket实例,会导致新连接失败,建议每次连接前检查并关闭已存在的Socket。
二、BluetoothSocket能否无需配对直接连接?
多数经典蓝牙设备需要先完成配对(建立设备间信任关系)才能通过RFCOMM Socket连接。仅两种例外情况:
- 设备本身支持免配对模式(比如部分蓝牙串口模块可配置为无密码连接),需设备端提前设置。
- 低功耗蓝牙(BLE)无需配对即可连接服务,但你使用的是经典蓝牙的RFCOMM Socket,不属于此类场景。
因此,你当前的场景下,通常需要先完成设备配对,再执行Socket连接操作。
内容的提问来源于stack exchange,提问作者new learner
相关产品推荐
相关产品推荐

