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

Web Bluetooth API:如何检测Mac权限弹窗取消/连接已配对设备?

Web Bluetooth API 问题解决:权限拒绝检测与已连接设备连接

一、检测用户是否拒绝蓝牙权限弹窗

在Mac系统中,Web Bluetooth的二次权限弹窗属于系统级操作,API没有直接提供弹窗取消的回调,但可以通过后续连接验证步骤间接判断用户是否拒绝了权限:

  • 检查GATT服务器连接状态:调用device.gatt.connect()后,立即校验server.connected属性,若为false则判定连接未授权。
  • 尝试读取特征值:权限被拒时,读取蓝牙特征值会抛出错误,可通过捕获该错误确认权限被拒绝。
  • 监听连接断开事件:用户取消权限后,设备会快速触发ongattserverdisconnected事件,可通过标记状态识别该场景。

修改你的连接代码如下:

const connectMicrobit = async () => {
  try {
    const device = await navigator?.bluetooth?.requestDevice(bluetoothSearchOptions);
    if (!device) {
      throw new Error("无法获取设备信息,可能浏览器不支持Web Bluetooth");
    }

    let connectionRejected = false;
    // 临时绑定断开事件,用于检测权限取消
    device.ongattserverdisconnected = () => {
      connectionRejected = true;
      disconnectMicrobit();
    };

    const server = await device.gatt.connect();
    // 验证服务器真实连接状态
    if (!server.connected || connectionRejected) {
      throw new Error("用户拒绝了蓝牙连接权限");
    }

    // 获取服务,权限被拒时此处会抛出错误
    const service = await server.getPrimaryService(MBIT_UART_SERVICE);
    const rxCharacteristic = await service.getCharacteristic(MBIT_UART_RX_CHARACTERISTIC);
    
    // 尝试读取特征值,验证权限有效性
    try {
      await rxCharacteristic.readValue();
    } catch (readErr) {
      throw new Error("权限被拒绝,无法访问设备特征");
    }

    const txCharacteristic = await service.getCharacteristic(MBIT_UART_TX_CHARACTERISTIC);
    const uart = new MicroBitUART(rxCharacteristic, txCharacteristic);
    microbitUARTRef.current = uart;

    // 重置断开事件为正常业务逻辑
    device.ongattserverdisconnected = () => {
      console.log("Microbit 已断开连接");
      disconnectMicrobit();
    };

  } catch (error) {
    console.error("连接Microbit时出错:", error);
    disconnectMicrobit();
  }
};

二、连接已配对的蓝牙设备

要连接用户电脑上已配对/之前授权过的设备,可通过以下两种方式实现:

方式1:直接获取已授权设备连接

使用navigator.bluetooth.getDevices()获取用户之前通过Web Bluetooth授权过的设备,无需再次弹出选择窗口:

const connectPairedMicrobit = async () => {
  try {
    const devices = await navigator.bluetooth.getDevices();
    // 根据设备名称筛选micro:bit
    const microbitDevice = devices.find(dev => dev.name?.includes("micro:bit"));
    if (!microbitDevice) {
      throw new Error("未找到已授权的micro:bit设备");
    }

    const server = await microbitDevice.gatt.connect();
    // 后续步骤与正常连接一致
    const service = await server.getPrimaryService(MBIT_UART_SERVICE);
    const rxCharacteristic = await service.getCharacteristic(MBIT_UART_RX_CHARACTERISTIC);
    const txCharacteristic = await service.getCharacteristic(MBIT_UART_TX_CHARACTERISTIC);
    const uart = new MicroBitUART(rxCharacteristic, txCharacteristic);
    microbitUARTRef.current = uart;

    microbitDevice.ongattserverdisconnected = () => {
      console.log("Microbit 已断开连接");
      disconnectMicrobit();
    };
  } catch (error) {
    console.error("连接已配对设备失败:", error);
    disconnectMicrobit();
  }
};

方式2:在设备选择器中包含已配对设备

调用requestDevice时,确保optionalServices包含你需要访问的服务UUID,这样已配对且支持该服务的设备会出现在选择列表中:

const bluetoothSearchOptions = {
  filters: [{ namePrefix: "micro:bit" }],
  optionalServices: [MBIT_UART_SERVICE] // 必须指定需要访问的服务UUID
};

注意:Web Bluetooth无法访问系统中所有已配对设备,只能获取用户之前授权过的设备,或通过选择器让用户重新选择已配对设备。

内容的提问来源于stack exchange,提问作者ktt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:53:13