You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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实例保存下来(存在组件的实例属性或状态里),而不是只靠设备名称来“冒充”设备对象。

修改步骤:

  1. 在构造函数里初始化一个存储设备实例的对象:
constructor(props) {
  super(props);
  this.manager = new BleManager();
  this.devices = {
    dx: null, // 第一台设备实例
    sx: null  // 第二台设备实例
  };
  this.state = {
    acc: [],
    gyr: [],
    mg: [],
    // ... 其他状态
  };
}
  1. 连接设备成功后,把实例存到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)

  1. 修改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(或类似方法)开启的特征值监听订阅还在运行。即使蓝牙连接断开,已经建立的订阅回调不会立刻停止,要等到连接彻底失效才会终止,所以出现延迟。

解决方案

在断开连接前,先主动取消所有正在运行的特征值监听订阅,再断开设备连接。

修改步骤:

  1. 在构造函数里初始化一个存储订阅的数组:
constructor(props) {
  super(props);
  this.manager = new BleManager();
  this.devices = { dx: null, sx: null };
  this.subscriptions = []; // 存储所有特征值监听订阅
  this.state = {
    acc: [],
    gyr: [],
    mg: [],
    // ... 其他状态
  };
}
  1. 在订阅特征值时,把订阅对象存入数组:
    比如在deviceService_Dx方法中:
deviceService_Dx(device) {
  // 假设你在监听某个特征值
  const subscription = device.monitorCharacteristicForService(
    "你的服务UUID",
    "你的特征值UUID",
    (error, characteristic) => {
      // 处理数据流的逻辑
      if (characteristic) {
        // 更新状态等操作
      }
    }
  );
  this.subscriptions.push(subscription); // 保存订阅
}

(第二台设备的订阅也要做同样的处理)

  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:45:46