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

如何重启Android BLE HID外设后重新连接至中心设备?

Android BLE HID绝对鼠标外设应用重启后稳定重连方案

问题背景

我基于开源BLE HID外设项目修改代码,实现了Android 14 Pixel 7 Pro通过BluetoothGattServer直接处理GATT特征,作为BLE绝对鼠标控制Win11笔记本。但应用重启后,没法稳定和已配对的Win11设备重连,目前只能靠两端删除配对后重新配对才能恢复功能。

试过的无效操作:

  • 应用重启后直接重新广播:GATT服务器回调没成功连接通知,Win11蓝牙面板显示设备从“其他设备”转成“输入设备”但一直显示“未连接”;偶尔从Win11“设备和打印机”面板连接能成,但没法稳定复现。
  • 保存配对设备地址,通过BluetoothManager.getAdapter().getBondedDevices()或getRemoteDevice()拿已绑定的BluetoothDevice,调用gattServer.connect(device, false/true)主动连接:onConnectionStateChange()返回newState=0(断开),Win11没特征查询,但蓝牙对话框显示已连接。
  • 主线程调用gattServer.connect(),甚至用隐藏API强制TRANSPORT_LE传输,问题依旧。
  • 不广播直接发起首次配对:两端弹出配对框,但Win11识别不了鼠标移动指令。

可行重连策略

1. 严格复刻GATT服务结构

应用重启重建BluetoothGattServer时,必须完全和首次配对时的GATT服务、特征、描述符结构、属性保持一致,包括UUID、权限(PERMISSION_*)、特征属性(PROPERTY_*)、描述符初始值。结构或属性有差异的话,Win11会拒绝完成GATT连接。

示例代码:

// 重启后重建HID服务,必须和首次创建时完全一致
BluetoothGattService hidService = new BluetoothGattService(
    UUID.fromString("00001812-0000-1000-8000-00805f9b34fb"),
    BluetoothGattService.SERVICE_TYPE_PRIMARY
);

// 绝对鼠标的HID报告特征
BluetoothGattCharacteristic reportChar = new BluetoothGattCharacteristic(
    UUID.fromString("00002a4d-0000-1000-8000-00805f9b34fb"),
    BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
    BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE
);

// 添加CCCD描述符,初始值设为开启通知
BluetoothGattDescriptor cccd = new BluetoothGattDescriptor(
    UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"),
    BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE
);
cccd.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
reportChar.addDescriptor(cccd);

hidService.addCharacteristic(reportChar);
// 别忘了添加Protocol Mode、Report Map等其他必要特征,结构要和首次一致
gattServer.addService(hidService);

2. 让Win11主动发起连接,别自己主动连

BLE HID外设的连接逻辑本来就是中央设备(Win11)主动发起,不是外设(Android)主动连。应用重启后正确流程:

  • 先初始化BluetoothGattServer,加全所有HID相关服务和特征
  • 开启BLE广播,广播包必须包含HID服务UUID(00001812-0000-1000-8000-00805f9b34fb)
  • 等着Win11发连接请求,别主动调用gattServer.connect()

原因:Win11对BLE HID设备的连接管理靠自身蓝牙数据库,主动发起连接会绕过它的HID初始化流程,就算连上也识别不了HID报告。

3. 触发Win11重新同步GATT特征

如果Win11还是显示“未连接”,在onConnectionStateChange()收到连接成功(newState=2)时,主动触发特征通知的开关,强制Win11重新查询GATT特征:

@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
    super.onConnectionStateChange(device, status, newState);
    if (newState == BluetoothProfile.STATE_CONNECTED) {
        // 获取HID报告特征
        BluetoothGattCharacteristic reportChar = gattServer.getService(UUID.fromString("00001812-0000-1000-8000-00805f9b34fb"))
                .getCharacteristic(UUID.fromString("00002a4d-0000-1000-8000-00805f9b34fb"));
        // 先关通知再打开,强制Win11重新同步
        BluetoothGattDescriptor cccd = reportChar.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
        cccd.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        gattServer.notifyCharacteristicChanged(device, reportChar, false);
        cccd.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        gattServer.notifyCharacteristicChanged(device, reportChar, false);
    }
}

4. 重置配对信息(极端情况)

如果绑定状态显示BOND_BONDED但连不上,可能是两端配对密钥不一致。应用重启后,要是连接失败超过3次,主动触发重新配对:

// 检查绑定状态,尝试重新配对
if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
    // 先解绑
    removeBond(device);
    // 等解绑完成后重新发起配对
    device.createBond();
}

// 反射调用隐藏API实现解绑
private boolean removeBond(BluetoothDevice device) {
    try {
        Method method = device.getClass().getMethod("removeBond");
        return (boolean) method.invoke(device);
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

关键注意事项

  • Android 14对BLE权限要求严,必须申请BLUETOOTH_ADVERTISE、BLUETOOTH_CONNECT、BLUETOOTH_SCAN权限,还要动态授权。
  • 广播包要符合BLE HID规范,必须包含HID服务UUID,广播名称得和首次配对时一样。
  • 别在应用重启后立刻主动连,让Win11主导连接流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 06:45:53