uniapp 低功耗蓝牙重复监听特征值无法写入数据如何解决?

在使用uniapp开发低功耗蓝牙功能时,遇到重复监听特征值后无法写入数据的问题。具体表现为:初次连接设备并写入特征值正常,但开启特征值变化监听后,再次调用writeBLECharacteristicValue()写入数据时失败,返回错误码或没有任何响应。尝试过关闭监听再写入、延时操作等方法均无效。请问如何在不影响监听功能的前提下解决数据写入失败的问题?环境为HBuilderX 3.6.18,测试机型为安卓12。

2 回复

检查是否已开启特征值通知,确保设备连接稳定。写入数据前确认特征值支持写入操作,避免重复监听冲突。可尝试使用uni.writeBLECharacteristicValue后延时再监听。


在 UniApp 中,低功耗蓝牙重复监听特征值导致无法写入数据的问题,通常是由于事件监听未正确移除或写入时机不当造成的。以下是解决方案:

1. 移除重复监听

在每次写入前,先移除之前的特征值变化监听,避免事件堆积。

// 移除已有监听
uni.offBLECharacteristicValueChange(this._listener);
// 重新监听特征值变化(如需要)
this._listener = (res) => {
  console.log('特征值变化:', res);
};
uni.onBLECharacteristicValueChange(this._listener);

2. 确保写入时机正确

writeBLECharacteristicValue 前,确认蓝牙连接和特征值准备就绪:

// 检查设备连接状态
if (this._connected) {
  uni.writeBLECharacteristicValue({
    deviceId: this._deviceId,
    serviceId: this._serviceId,
    characteristicId: this._characteristicId,
    value: arrayBuffer,
    success: (res) => {
      console.log('写入成功', res);
    },
    fail: (err) => {
      console.error('写入失败', err);
    }
  });
}

3. 使用队列控制写入

通过队列管理写入操作,避免并发冲突:

let writeQueue = [];
let isWriting = false;

function addWriteTask(data) {
  writeQueue.push(data);
  if (!isWriting) {
    processWriteQueue();
  }
}

function processWriteQueue() {
  if (writeQueue.length === 0) {
    isWriting = false;
    return;
  }
  isWriting = true;
  let data = writeQueue.shift();
  uni.writeBLECharacteristicValue({
    // 参数配置
    value: data,
    success: () => {
      processWriteQueue();
    },
    fail: (err) => {
      console.error('写入失败', err);
      processWriteQueue();
    }
  });
}

4. 检查特征值属性

确认特征值支持写入操作(通过 properties.writeproperties.writeWithoutResponse):

uni.getBLEDeviceCharacteristics({
  deviceId: this._deviceId,
  serviceId: this._serviceId,
  success: (res) => {
    let char = res.characteristics.find(c => c.uuid === this._characteristicId);
    if (char.properties.write) {
      // 执行写入
    }
  }
});

5. 错误处理与重试

在写入失败时加入错误处理和重试机制:

function writeWithRetry(data, retries = 3) {
  uni.writeBLECharacteristicValue({
    value: data,
    success: () => {
      console.log('写入成功');
    },
    fail: (err) => {
      if (retries > 0) {
        setTimeout(() => writeWithRetry(data, retries - 1), 100);
      } else {
        console.error('多次重试失败', err);
      }
    }
  });
}

总结步骤:

  1. 移除旧监听:使用 uni.offBLECharacteristicValueChange 清理事件。
  2. 检查连接与属性:确保设备已连接且特征值可写。
  3. 顺序写入:通过队列避免并发问题。
  4. 错误处理:添加重试逻辑应对临时故障。

按以上方法调整代码,通常可解决重复监听导致的写入问题。

回到顶部