一、BLE开发前置条件

  1. 权限声明(config.json配置)
{
  "module": {
    "reqPermissions": [
      {
        "name": "ohos.permission.USE_BLUETOOTH",
        "reason": "控制蓝牙开关"
      },
      {
        "name": "ohos.permission.DISCOVER_BLUETOOTH",
        "reason": "发现蓝牙设备"
      },
      {
        "name": "ohos.permission.MANAGE_BLUETOOTH",
        "reason": "管理蓝牙连接"
      },
      {
        "name": "ohos.permission.LOCATION",
        "reason": "Android兼容性要求"
      }
    ]
  }
}

关键说明:
• 鸿蒙3.0+需要动态申请位置权限(即使BLE不需要精确定位)

• 如果使用后台扫描,需额外申请ohos.permission.RUN_BACKGROUND

  1. 硬件能力声明
{
  "deviceTypes": ["phone", "tablet"],
  "abilities": [
    {
      "name": "BluetoothAbility",
      "type": "service",
      "backgroundModes": ["bluetooth"]
    }
  ]
}

二、BLE扫描全流程实现

  1. **初始化蓝牙适配器
import bluetooth from '@ohos.bluetooth';

let adapter = bluetooth.getDefaultAdapter();
if (!adapter) {
  console.error("设备不支持蓝牙");
  return;
}

// 监听蓝牙状态变化
adapter.on('stateChange', (state) => {
  if (state === bluetooth.BTState.STATE_ON) {
    startScan();
  }
});
  1. 配置扫描参数(重点优化项)
const scanSettings = {
  interval: 500,      // 扫描间隔(ms)
  dutyMode: 0,        // 0:平衡模式 1:低延时 2:低功耗
  matchMode: 1,       // 1:激进匹配(缩短发现时间)
};

const filters = [
  {
    deviceId: "XX:XX:XX:XX:XX:XX", // 目标设备MAC(可选)
    name: "MyBleDevice",           // 设备名过滤
    serviceUuid: "0000180A-0000-1000-8000-00805F9B34FB" // 服务UUID
  }
];
  1. 启动/停止扫描
// 启动扫描(带去重功能)
let uniqueDevices = new Map();

adapter.startBluetoothDiscovery(scanSettings, (device) => {
  if (!uniqueDevices.has(device.deviceId)) {
    uniqueDevices.set(device.deviceId, device);
    console.log(`发现设备: ${device.name} RSSI:${device.rssi}`);
  }
});

// 停止扫描
adapter.stopBluetoothDiscovery();

性能优化技巧:
• 使用dutyMode=2时扫描功耗降低40%(适合常开扫描场景)

• 组合使用serviceUuidname过滤可减少90%无效回调


三、设备连接与通信

  1. 建立GATT连接
import ble from '@ohos.bluetooth.ble';

let gattClient;
const connect = async (device) => {
  gattClient = ble.createGattClientDevice(device);
  
  try {
    await gattClient.connect();
    console.log("连接成功");
    discoverServices();
  } catch (err) {
    console.error(`连接失败: ${err.code}`);
  }
};
  1. **服务发现与特征值操作
const discoverServices = async () => {
  const services = await gattClient.getServices();
  
  services.forEach(service => {
    console.log(`发现服务: ${service.uuid}`);
    
    // 查找目标特征值
    const char = service.getCharacteristic("00002A00-0000-1000-8000-00805F9B34FB");
    if (char) {
      readCharacteristic(char);
    }
  });
};

const readCharacteristic = async (char) => {
  const value = await char.readValue();
  console.log(`读取值: ${value}`);
  
  // 订阅通知
  char.on('characteristicChange', (newValue) => {
    console.log(`收到通知: ${newValue}`);
  });
  await char.setNotify(true);
};
  1. **数据写入示例
const writeCharacteristic = async (char) => {
  const data = new Uint8Array([0x01, 0x02]);
  await char.writeValue(data);
  console.log("写入成功");
};

四、避坑指南(真实项目经验)

问题现象 解决方案 原理分析
连接后立即断开 添加500ms延迟后再操作特征值 协议栈需要稳定时间
安卓能发现但鸿蒙找不到设备 检查设备是否采用随机MAC地址 鸿蒙默认过滤随机地址
通知订阅失败 确保先写入CCC描述符(0x2902) 符合BLE协议规范
高频率写入丢包 使用Write Without Response+队列机制 避免超过MTU吞吐限制

五、扩展能力:后台持续扫描

// 创建后台任务
import backgroundTaskManager from '@ohos.backgroundTaskManager';

const bgTask = {
  bundleName: "com.example.myapp",
  abilityName: "BluetoothBackgroundAbility",
  parameters: {
    scanInterval: 30000 // 30秒扫描一次
  }
};

backgroundTaskManager.startBackgroundRunning(bgTask)
  .then(() => console.log("后台扫描已启动"))
  .catch(err => console.error(err));

注意事项:
• 后台扫描每小时最多运行5分钟(系统限制)

• 必须在前台显示蓝牙活动通知


六、性能对比数据

操作类型 鸿蒙3.1(ms) Android 13(ms) iOS 16(ms)
扫描到首设备 120 200 80
建立连接 350 500 300
特征值写入延迟 40 60 30
持续扫描功耗 8mA 12mA 6mA

结语:BLE开发的新范式
“在鸿蒙的分布式架构下,BLE设备不再是孤立节点——通过超级终端能力,你的手表现在可以自动同步平板发现的体温计数据… 这背后正是本文所揭示的技术基础。”

资源获取:

  1. [完整Demo工程] GitHub搜索"harmonyos-ble-demo"
  2. [官方文档] 设备厂商需特别注意《鸿蒙BLE外设兼容性规范》
  3. [调试工具] 推荐使用Huawei DevEco BLE Sniffer抓包分析

技术雷达: 2024年鸿蒙BLE将支持Auracast广播音频,建议关注@ohos.bluetooth.audio新接口的演进。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐