项目场景:

在 UniApp 开发蓝牙设备联动应用(如智能硬件、设备控制、数据采集)时,蓝牙模块是兼容性问题最多、调试难度最大的功能之一。官方 API 封装虽简化了原生调用,但平台差异、权限机制、设备适配、连接稳定性等问题,很容易让新手踩坑。

本文基于 UniApp 官方 uni.openBluetoothAdapter 等蓝牙 API,适用APP 端(安卓 /iOS),小程序端逻辑基本通用,仅部分权限 / 生命周期略有差异。


问题6:发送数据失败 / 设备无响应,ArrayBuffer 转换错误

问题现象

调用 writeBLECharacteristicValue 发送数据,提示成功,但设备没反应;或直接报错invalid data。

原因分析:

  1. UniApp 蓝牙只支持 ArrayBuffer 格式数据,直接传字符串 / 十六进制会失效;
  2. 字符串 / 十六进制与 ArrayBuffer 转换错误。

解决方案:

1.提供通用转换工具函数

// 16进制字符串转ArrayBuffer
hex2arraybuffer(hex) {
  const length = hex.length / 2;
  const buffer = new ArrayBuffer(length);
  const dataView = new Uint8Array(buffer);
  for (let i = 0; i < length; i++) {
    dataView[i] = parseInt(hex.substr(i * 2, 2), 16);
  }
  return buffer;
},

// ArrayBuffer转16进制字符串
arraybuffer2hex(buffer) {
  return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}

// 发送数据
sendData(deviceId, serviceId, characteristicId, hexStr) {
  const buffer = this.hex2arraybuffer(hexStr);
  return uni.writeBLECharacteristicValue({
    deviceId, serviceId, characteristicId, value: buffer
  })
}

问题7:扫描不到蓝牙设备,iOS 能扫到,安卓扫不到

问题现象
  • 安卓:切后台、锁屏几分钟后,蓝牙自动断开,无法保活;
  • iOS:APP 进入后台立即休眠,蓝牙停止通信。

原因分析:

系统后台限制、电量优化、蓝牙无保活机制。

解决方案:

1.安卓保活

  • 开启前台服务(manifest 配置);
  • 监听系统休眠事件,发送心跳包;

2.iOS 后台模式

  • manifest 开启后台蓝牙权限;
  • 持续发送空数据包,避免系统休眠;

3.增加重连机制,断开后自动重试


问题8:重复初始化 / 重复连接,导致蓝牙模块崩溃

问题现象

多次点击初始化、连接按钮,APP 出现卡死、闪退、蓝牙 API 全部失效。

原因分析:

未做状态锁,重复调用系统蓝牙 API,造成资源冲突。

解决方案:

1.用全局变量做状态控制

export default {
  data() {
    return {
      isBluetoothOpen: false, // 蓝牙是否初始化
      isConnecting: false,    // 是否正在连接
      isConnected: false      // 是否已连接
    }
  },
  methods: {
    async connect() {
      // 加锁:正在连接时,禁止重复点击
      if(this.isConnecting) return;
      this.isConnecting = true;
      
      try {
        await this.connectDevice();
        this.isConnected = true;
      } finally {
        this.isConnecting = false;
      }
    }
  }
}

问题9:断开连接后,无法重新扫描 / 连接

问题现象

主动调用 closeBLEConnection 断开设备后,再次扫描、连接无反应。

原因分析:

未完整释放蓝牙资源,仅断开连接,未关闭适配器、停止监听。

解决方案:

1.标准断开流程:断开连接 → 停止监听 → 关闭适配器

async disconnectBluetooth(deviceId) {
  // 1. 断开连接
  await uni.closeBLEConnection({ deviceId });
  // 2. 关闭监听
  uni.offBLECharacteristicValueChange();
  // 3. 关闭蓝牙适配器
  await uni.closeBluetoothAdapter();
  this.isConnected = false;
  this.isBluetoothOpen = false;
}

更多推荐