跳转到内容

HID 键鼠自动化控制指南

更新: 2026/3/2 字数: 0 字 时长: 0 分钟

基于物理级硬件的 零权限 / 强隔离 / 高一致性 自动化方案

HID(Human Interface Device)键鼠自动化 是一种纯硬件层输入模拟方案。 它通过 ESP32 / 专用 HID 硬件,在 USB / OTG / 蓝牙协议层模拟标准键盘、鼠标、触控设备,对手机或其他终端进行操作控制。

👉 从操作系统视角看,这些行为与真实外设输入完全一致

核心优势

零权限运行

HID 键鼠控制基于外置硬件输入实现,不依赖任何系统级能力或高权限接口,包括但不限于:

  • 无障碍 / 辅助功能
  • ADB 调试通道 / 开发人员选项
  • Root 或系统修改能力

无需授权、不占用系统权限,插入即生效。

强环境隔离性

HID 方案的操作路径完全位于系统输入链路最前端

  • 输入事件来源为 外部物理设备
  • 行为由系统输入子系统统一接收
  • 不通过应用层 API、不注入进程、不修改系统状态
  • 不产生额外的调用痕迹或运行特征

从系统与应用的角度看, 👉 这些操作等价于真实用户使用键盘、鼠标或触控设备完成的输入行为。

全功能覆盖,适配多种业务形态

支持完整的输入与控制能力,包括:

  • 按键与组合键模拟
  • 文本输入与粘贴
  • 精准触控与多点手势
  • 滑动、缩放、长按等交互
  • 屏幕截图与视觉联动

同时兼容 BLE 蓝牙 / OTG / USB 多种连接方式,满足不同部署环境。

高稳定性 & 低时延表现

指标HID 硬件方案传统软件方案
输入延迟5–50ms50–200ms
连续运行稳定性≈99.9%依赖系统状态
系统适配Android 7.0+强依赖版本与厂商
长时间运行❌ 易受系统影响

HID 工作原理

HID 不是“模拟点击” 而是 作为输入设备参与系统工作

系统处理流程如下:

text
[ESP32 / HID 硬件]

[USB / OTG / BLE 协议]

[系统输入子系统]

[应用接收标准输入事件]

👉 对应用而言,输入来源不可区分,行为一致。

支持的连接方式

连接方式特点适用场景
BLE 蓝牙无线、部署灵活移动设备、远程或分布式环境
OTG / USB极低延迟、稳定固定工位、高频交互场景

硬件支持列表

硬件类型支持型号说明
ESP32 开发板ESP32-C3 / S2 / S3成本低,支持单一连接模式
多模二合一蓝牙 + OTG支持模式切换与供电控制
多模三合一蓝牙 + OTG + USB全模式覆盖,即插即用

核心 API 模块说明

$hid —— ESP32 通用控制模块

统一封装 ESP32 OTG / 蓝牙 HID 能力,自动识别当前连接方式,提供一致的调用接口,适用于大多数场景。

$hid.esp32ble —— 蓝牙专用模块

针对 ESP32 BLE HID 优化,支持指定设备地址、蓝牙连接管理,适合无线部署环境。

$hid.esp32otg —— OTG 专用模块

专注 ESP32 OTG 有线 HID 输入,具备更低时延与更高输入一致性,适合高频或精细操作。

$hid.multi —— 多模硬件模块

适配二合一 / 三合一 HID 设备,支持在连接状态下切换工作模式,适合规模化或长期部署。

$hid.http —— HTTP 控制模块

通过本地 HTTP 服务调用 HID 能力,便于跨进程、跨语言或远程系统集成。

HID 设备状态监听

用于监听 HID 设备的状态变化,包括设备插入、拔出、权限请求、权限结果、连接和断开等事件。

支持以下事件类型:

  • device_attached OTG HID 设备插入时触发

  • device_detached OTG HID 设备拔出时触发

  • permission_request 请求 USB 或 OTG 管理权限时触发

  • permission_result 用户确认或拒绝权限请求后触发

  • connected HID 设备连接时触发

  • disconnected HID 设备断开连接时触发

基础监听示例

js
var receiverHID = new JavaAdapter(android.content.BroadcastReceiver, {
  onReceive: function (context, intent) {
    threads.start(function () {
      try {
        console.log("监听到消息");
        // 单 ACTION 广播
        if (intent.getAction() === "hid.action.EVENT") {
          // 获取事件类型
          var event = intent.getStringExtra("event");

          // 获取设备(UsbDevice / UsbAccessory / BluetoothDevice)
          var device = intent.getParcelableExtra("device");
          console.log(device);
          // 根据事件类型处理
          switch (event) {
            case "device_attached":
              console.log("设备插入");

              break;

            case "device_detached":
              console.log("设备拔出");
              break;

            case "permission_request":
              console.log("请求OTG/USB管理权限");
              break;

            case "permission_result":
              var granted = intent.getBooleanExtra("granted", false);
              console.log("用户处理权限结果: " + granted);
              break;

            case "connected":
              console.log("设备 HID 已连接");
              break;

            case "disconnected":
              console.log("设备 HID 已断开");

              break;
          }
        }
      } catch (error) {
        /* 处理异常的代码块 */
        console.error(error);
      }
    });
  },
});

var filterHID = new android.content.IntentFilter("hid.action.EVENT");

if (android.os.Build.VERSION.SDK_INT >= 33) {
  context.registerReceiver(receiverHID, filterHID, android.content.Context.RECEIVER_EXPORTED);
} else {
  context.registerReceiver(receiverHID, filterHID);
}



// 脚本退出时注销广播接收器
events.on("exit", function () {
  try {
    if (receiverHID) {
      context.unregisterReceiver(receiverHID);
    }
  } catch (error) {
    /* 处理异常的代码块 */
    console.error(error);
  }
});

$hid.esp32otg.init();

$hid.esp32otg.connect();

// 在此处编写你的业务逻辑

// 用于测试 HID 广播监听,防止脚本执行完毕后退出,保持脚本常驻运行,确保 HID 事件监听持续有效
setInterval(() => {}, 1000);

自动授权与界面辅助处理

在 HID 设备连接或权限请求过程中,系统可能会显示权限确认界面。

通过临时启用无障碍服务,可以自动完成权限确认或其他界面操作,实现 HID 设备的自动授权与异常恢复。

无障碍服务仅在需要时启用,完成操作后可自动关闭,不影响系统正常使用。

适用场景:

  • USB / OTG HID 自动授权
  • HID 重连恢复
  • 系统权限确认自动处理

无障碍服务的启用与关闭方法请参考:

js

/**
 * 启用无障碍服务
 */
function enableAccessibilityService() {
  const SERVICE_PATH = ":" + context.getPackageName() + "/com.google.android.accessibility.selecttospeak.SelectToSpeakService";

  var Settings = android.provider.Settings;
  let enabledServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);

  // 移除重复服务,防止写入冲突
  enabledServices = enabledServices ? enabledServices.replace(new RegExp(SERVICE_PATH, "gi"), "") : "";

  // 清空并写入服务,确保生效
  Settings.Secure.putString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
  Settings.Secure.putString(
    context.getContentResolver(),
    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
    enabledServices + SERVICE_PATH
  );
}

/**
 * 检查应用是否拥有指定权限
 * @param {string} permission 权限名称
 * @returns {boolean} 是否已授权
 */
function checkPermission(permission) {
  var pm = context.getPackageManager();
  return android.content.pm.PackageManager.PERMISSION_GRANTED == pm.checkPermission(permission, context.getPackageName());
}

/**
 * HID 设备连接后的自动处理逻辑
 *
 * 功能说明:
 * 1. 检查并启用无障碍服务(支持 WRITE_SECURE_SETTINGS 自动开启)
 * 2. 自动处理 USB/HID 权限授权弹窗(点击“确定”)
 * 3. 授权完成后自动关闭无障碍服务,避免长期占用
 *
 * 使用场景:
 * - ESP32 HID
 * - OTG HID 键鼠
 * - USB HID 自动授权
 *
 */
function handleHidConnected() {
  console.log("HID 设备已连接,开始执行自动授权流程: ");

  // =========================
  // 第一步:检查无障碍自动开启权限
  // =========================

  if (checkPermission("android.permission.WRITE_SECURE_SETTINGS")) {
    console.log("已获得 WRITE_SECURE_SETTINGS 权限,正在自动启用无障碍服务");

    enableAccessibilityService();
  } else {
    console.warn(
      "\n⚠️ 未授予 WRITE_SECURE_SETTINGS 权限,无法自动开启无障碍服务" +
        "\n请使用 ADB 授权或手动开启无障碍服务" +
        "\n授权命令已复制到剪贴板"
    );

    // 复制授权命令
    var cmd = "adb shell pm grant " + context.getPackageName() + " android.permission.WRITE_SECURE_SETTINGS";

    setClip(cmd);

    console.info("已复制 ADB 授权命令");

    // 打开无障碍设置页面
    app.startActivity({
      action: "android.settings.ACCESSIBILITY_SETTINGS",
    });

    console.info("等待用户手动开启无障碍服务...");

    // 阻塞等待无障碍开启
    auto.waitFor();
  }

  // =========================
  // 第二步:检测无障碍状态
  // =========================

  if (auto.service == null) {
    toastLog("❌ 无障碍服务启动失败,无法执行自动授权");

    return;
  }

  console.log("无障碍服务已启用");

  // =========================
  // 第三步:等待 USB 权限弹窗出现
  // =========================

  sleep(2000);

  console.log("正在查找 USB 授权确认按钮...");

  // =========================
  // 第四步:点击“确定”
  // =========================

  var confirmBtn = selector().text("确定").className("android.widget.Button").visibleToUser(true).clickable(true).findOne(2000);

  if (confirmBtn) {
    var result = confirmBtn.click();

    console.log("USB 授权确认点击结果: " + result);
  } else {
    toastLog("⚠️ 未找到 USB 授权确认按钮");

    return;
  }

  // =========================
  // 第五步:自动关闭无障碍服务
  // =========================

  sleep(2000);

  if (auto.service != null) {
    auto.service.disableSelf();

    console.log("无障碍服务已关闭(自动授权流程完成)");
  }
}

// 监听 HID 广播
var receiverHID = new JavaAdapter(android.content.BroadcastReceiver, {
  onReceive: function (context, intent) {
    threads.start(function () {
      try {
        console.log("监听到消息");
        // 单 ACTION 广播
        if (intent.getAction() === "hid.action.EVENT") {
          // 获取事件类型
          var event = intent.getStringExtra("event");

          // 获取设备(UsbDevice / UsbAccessory / BluetoothDevice)
          var device = intent.getParcelableExtra("device");
          console.log(device);
          // 根据事件类型处理
          switch (event) {
            case "device_attached":
              console.log("设备插入");

              break;

            case "device_detached":
              console.log("设备拔出");
              break;

            case "permission_request":
              console.log("请求OTG/USB管理权限");
              break;

            case "permission_result":
              var granted = intent.getBooleanExtra("granted", false);
              console.log("用户处理权限结果: " + granted);
              break;

            case "connected":
              console.log("设备 HID 已连接");
              // 对于 OTG 类型的 HID 设备:
              // 1. 系统会弹出“是否允许应用访问 USB 设备”提示
              // 2. 可通过无障碍服务查找控件并点击“确定”,或点击指定坐标,实现自动授权
              // 3. 等待 "permission_result" 广播后,可延迟 2000ms 再关闭无障碍服务
              // 4. 也可以在点击“确定”后直接关闭无障碍服务
              handleHidConnected(device);

              break;

            case "disconnected":
              console.log("设备 HID 已断开");

              break;
          }
        }
      } catch (error) {
        /* 处理异常的代码块 */
        console.error(error);
      }
    });
  },
});


var filterHID = new android.content.IntentFilter("hid.action.EVENT");

if (android.os.Build.VERSION.SDK_INT >= 33) {
  context.registerReceiver(receiverHID, filterHID, android.content.Context.RECEIVER_EXPORTED);
} else {
  context.registerReceiver(receiverHID, filterHID);
}


// 脚本退出时注销广播接收器
events.on("exit", function () {
  try {
    if (receiverHID) {
      context.unregisterReceiver(receiverHID);
    }
  } catch (error) {
    /* 处理异常的代码块 */
    console.error(error);
  }
});

$hid.esp32otg.init();

$hid.esp32otg.connect();

// 在此处编写你的业务逻辑

// 用于测试 HID 广播监听,防止脚本执行完毕后退出,保持脚本常驻运行,确保 HID 事件监听持续有效
setInterval(() => {}, 1000);

总结

核心价值

  1. 输入层一致性:所有操作等价于真实外设输入
  2. 系统隔离性强:不依赖系统权限或应用接口
  3. 稳定可控:不受系统更新、权限策略变化影响
  4. 组合能力强:可与 YOLO / OCR / 找图找色等视觉方案协同工作

选择建议


如需进一步扩展协议或进行深度定制,请参考开发文档。