基于react-native-ble-plx的蓝牙设备数据中断与断开连接问题咨询
解决React Native蓝牙应用的两个连接与数据流问题
我来帮你拆解并解决这两个react-native-ble-plx使用中的常见问题:
问题1:调用stopConnection时报错「Cannot read property 'cancelConnection' of undefined」
问题原因
你在render里传给stopConnection的device是this.model_dx(this.props.deviceModel),这应该是设备名称字符串,而不是react-native-ble-plx提供的Device实例对象。cancelConnection是Device实例的专属方法,给字符串调用这个方法自然会报错。
解决方案
你需要在连接设备时,把真实的Device实例保存下来(存在组件的实例属性或状态里),而不是只靠设备名称来“冒充”设备对象。
修改步骤:
- 在构造函数里初始化一个存储设备实例的对象:
constructor(props) { super(props); this.manager = new BleManager(); this.devices = { dx: null, // 第一台设备实例 sx: null // 第二台设备实例 }; this.state = { acc: [], gyr: [], mg: [], // ... 其他状态 }; }
- 连接设备成功后,把实例存到
this.devices里:
scanDx() { this.manager.startDeviceScan(null, null, (error, device) => { if (error) { return; } if (device.name == this.model_dx(this.props.ModelDevice)) { this.manager.stopDeviceScan(); device .connect() .then((connectedDevice) => { console.log("ConnectedDX."); this.devices.dx = connectedDevice; // 保存第一台设备实例 return this.scanSx(); }) .then(() => { this.deviceService_Dx(this.devices.dx); }) .catch(() => { Alert.alert("Alert."); Actions.homepage(); }); } }); }
(同理,在scanSx连接第二台设备时,也要把实例存到this.devices.sx)
- 修改
stopConnection和按钮点击事件,使用保存的设备实例:
stopConnection() { // 断开第一台设备 if (this.devices.dx) { this.devices.dx.cancelConnection() .then(() => console.log("第一台设备已断开")) .catch(err => console.error("断开第一台设备失败:", err)); } // 断开第二台设备 if (this.devices.sx) { this.devices.sx.cancelConnection() .then(() => console.log("第二台设备已断开")) .catch(err => console.error("断开第二台设备失败:", err)); } } // 按钮 onPress 修改为 <TouchableOpacity style={[style.button, style.buttonOK]} onPress={() => this.stopConnection()} > <Text style={style.buttonTesto}>Stop</Text> </TouchableOpacity>
问题2:点击Stop后数据流需等待约10秒才停止
问题原因
你直接调用了cancelConnection,但之前通过monitorCharacteristicForService(或类似方法)开启的特征值监听订阅还在运行。即使蓝牙连接断开,已经建立的订阅回调不会立刻停止,要等到连接彻底失效才会终止,所以出现延迟。
解决方案
在断开连接前,先主动取消所有正在运行的特征值监听订阅,再断开设备连接。
修改步骤:
- 在构造函数里初始化一个存储订阅的数组:
constructor(props) { super(props); this.manager = new BleManager(); this.devices = { dx: null, sx: null }; this.subscriptions = []; // 存储所有特征值监听订阅 this.state = { acc: [], gyr: [], mg: [], // ... 其他状态 }; }
- 在订阅特征值时,把订阅对象存入数组:
比如在deviceService_Dx方法中:
deviceService_Dx(device) { // 假设你在监听某个特征值 const subscription = device.monitorCharacteristicForService( "你的服务UUID", "你的特征值UUID", (error, characteristic) => { // 处理数据流的逻辑 if (characteristic) { // 更新状态等操作 } } ); this.subscriptions.push(subscription); // 保存订阅 }
(第二台设备的订阅也要做同样的处理)
- 在
stopConnection中先取消所有订阅,再断开连接:
stopConnection() { // 第一步:取消所有特征值监听订阅 this.subscriptions.forEach(subscription => { subscription.remove(); // 取消订阅 }); this.subscriptions = []; // 清空订阅数组 // 第二步:断开设备连接 if (this.devices.dx) { this.devices.dx.cancelConnection() .then(() => console.log("第一台设备已断开")) .catch(err => console.error("断开第一台设备失败:", err)); } if (this.devices.sx) { this.devices.sx.cancelConnection() .then(() => console.log("第二台设备已断开")) .catch(err => console.error("断开第二台设备失败:", err)); } }
这样修改后,两个问题应该都能解决:既不会再出现cancelConnection的报错,点击Stop后数据流也会立刻停止,不会有延迟。
内容的提问来源于stack exchange,提问作者Jack23
相关产品推荐
相关产品推荐

