解决ESP32 BleKeyboard库与Android设备BLE配对失败问题

最近使用ESP32 C3开发BLE键盘时,遇到一个典型问题:设备能被Android手机正常发现,但配对环节始终失败,系统提示“配对请求被拒绝”或“安全错误”,导致连接中断。本文记录完整排查过程与实用解决方案。

问题现象

  • 硬件:ESP32 C3
  • 库版本:BleKeyboard 0.3.2(基于ESP32 BLE Arduino)
  • 复现步骤
    1. 手机蓝牙扫描可见设备"ESP32_Keyboard"
    2. 点击配对后立即失败,Android日志显示 bt_btif : bta_dm_ble_sec_req_evt 安全拒绝
    3. ESP32串口无配对请求日志,连接直接断开
  • 关键线索:Android 10+ 对BLE HID设备强制要求加密绑定(Bonding),而BleKeyboard默认使用Just Works模式(无绑定),触发安全策略拦截。

根本原因

Android系统自8.0起对HID类设备实施严格安全策略:

  • 要求必须启用加密绑定(Bonding)
  • 禁止Just Works模式(ESP_LE_AUTH_NO_BOND)用于HID服务
  • 默认IO Capability为KeyboardDisplay,期望用户交互验证

而BleKeyboard库默认配置:

// BleKeyboard.cpp 内部默认设置
pSecurity->setAuthenticationMode(ESP_LE_AUTH_NO_BOND); // 无绑定
pSecurity->setCapability(ESP_IO_CAP_NONE);             // 无交互能力

此配置与Android安全策略冲突,导致配对被拒绝。

解决方案(按安全性排序)

方案一:启用安全绑定(推荐)

保留加密保护,通过Passkey方式完成配对:

main.ino

#include <Arduino.h>
#include <BleKeyboard.h>
#include <BLEDevice.h>
#include <BLESecurity.h>

BleKeyboard bleKeyboard("ESP32_Keyboard", "ESP32_Dev", 100);
const uint32_t PASSKEY = 123456; // 固定配对码

void setup() {
  Serial.begin(115200);
  
  BLEDevice::init("ESP32_Keyboard");
  BLESecurity *pSecurity = new BLESecurity();
  
  // 启用绑定 + Passkey验证
  pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND); // 安全绑定
  pSecurity->setCapability(ESP_IO_CAP_KEYBOARD_ONLY);            // 键盘输入能力
  pSecurity->setKeySize(16);                                     // 密钥长度
  pSecurity->setPassKey(PASSKEY);                                // 设置固定配对码
  
  bleKeyboard.begin();
  Serial.println("BLE Keyboard ready. Pairing code: 123456");
}

效果:Android弹出6位数字配对码输入框,输入123456后成功绑定。后续连接自动加密,符合安全规范。

方案二:临时调试方案(仅限开发)

如需快速验证功能,可临时禁用绑定(存在安全风险):

main.ino(调试用)

#include <Arduino.h>
#include <BleKeyboard.h>
#include <BLEDevice.h>
#include <BLESecurity.h>

BleKeyboard bleKeyboard("ESP32_Keyboard", "ESP32_Dev", 100);

void setup() {
  Serial.begin(115200);
  
  BLEDevice::init("ESP32_Keyboard");
  BLESecurity *pSecurity = new BLESecurity();
  
  // 仅调试使用:禁用绑定(Android可能仍拒绝HID类设备)
  pSecurity->setAuthenticationMode(ESP_LE_AUTH_NO_BOND);
  pSecurity->setCapability(ESP_IO_CAP_NONE);
  pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK); // 仅启用加密密钥
  
  bleKeyboard.begin();
}

⚠️ 注意:Android 12+ 可能完全拒绝无绑定的HID设备,此方案兼容性有限。

版本兼容性说明

Android版本 安全策略 推荐方案
≤8.0 允许Just Works 方案二可用
9.0~11 强制HID绑定 必须用方案一
≥12 严格校验IO Capability 方案一+固定Passkey
posted @ 2026-02-01 22:13  乌清远wqy  阅读(6)  评论(0)    收藏  举报