WebHID API:用 navigator.hid 访问设备
发布于
一句话: WebHID 让网页可以通过权限提示请求访问一个人机接口设备 (HID,Human Interface Device)——“a type of device that takes input from or provides output to humans”(一种接受人类输入或向人类提供输出的设备),它使用最初为 USB 设计、此后也被实现在 其他传输方式(包括蓝牙)之上的 HID 协议。MDN 将其标记为**实验性(experimental)**且 非 Baseline,“because it does not work in some of the most widely-used browsers”(因为它 在一些广泛使用的浏览器中无法工作)。
安全上下文与用户激活
Section titled “安全上下文与用户激活”navigator.hid 仅在安全上下文中暴露:规范中为其添加该属性的 Navigator 与
WorkerNavigator 局部接口都标注了 [SecureContext]。调用 requestDevice() 还需要
用户激活(transient activation)——如果“the relevant global object of this does not
have transient activation”(this 的相关全局对象没有用户激活),规范会以 SecurityError
DOMException 拒绝返回的 Promise;如果调用方不是 window 上下文,则以 NotSupportedError
拒绝。
请求并复用设备
Section titled “请求并复用设备”const devices = await navigator.hid.requestDevice({ filters: [] });requestDevice() 会显示一个列出候选设备的权限提示(空的 filters 数组匹配所有设备);用户
选择一个设备并点击 Connect。设备一旦被授权,getDevices() 就可以再次获取它,而无需再次弹出
提示:
const devices = await navigator.hid.getDevices();devices.forEach((device) => { console.log(`HID: ${device.productName}`);});这两个方法的访问还受到一个名为 "hid" 的 Permissions Policy 特性的限制:如果调用文档不被
“allowed to use”(允许使用)该特性,规范会以 SecurityError 拒绝。
connect 与 disconnect 事件
Section titled “connect 与 disconnect 事件”navigator.hid.addEventListener("disconnect", (event) => { console.log(`HID disconnected: ${event.device.productName}`);});当一个先前已获授权的设备被接入或移除时,HID 接口会触发相应的 connect 与 disconnect
事件,每个事件都携带一个带有 device 属性的 HIDConnectionEvent。
打开设备并交换报告
Section titled “打开设备并交换报告”HIDDevice.open() 在设备状态不是 "closed" 时会以 InvalidStateError 拒绝;否则它会请求
操作系统打开该设备,成功打开后 resolve(失败则以 NetworkError 拒绝)。close() 会以
AbortError 拒绝所有挂起的报告 Promise,关闭操作系统句柄,并将设备状态重置为 "closed"。
sendReport()、sendFeatureReport() 与 receiveFeatureReport() 在设备状态不是
"opened" 时都会以 InvalidStateError 拒绝;当报告 ID 与设备接口是否使用报告 ID 不匹配时,
会以 TypeError 拒绝。
被阻止的报告
Section titled “被阻止的报告”规范定义了“blocked report”(被阻止的报告)这一概念:sendReport()、
sendFeatureReport() 与 receiveFeatureReport() 都会检查目标报告是否被阻止,如果是,则以
NotAllowedError 拒绝;被阻止的输入报告则根本不会触发 inputreport 事件。规范还分别描述了
基于设备与基于用途(usage)的阻止方式——例如按厂商/产品 ID 阻止,或通过检查设备集合上分配的
HID usage 值来阻止(规范以键盘作为基于用途阻止的示例)。
在 Worker 中的可用性
Section titled “在 Worker 中的可用性”MDN 指出该特性在 Web Worker 中可用,“except for Shared Web Workers”(共享 Worker 除外)——
WorkerNavigator.hid 在专用 Worker 中暴露该特性,与主线程上的 Navigator.hid 相对应。
特性检测与回退
Section titled “特性检测与回退”async function connectHidDevice() { if (!("hid" in navigator)) { // 此环境不支持 WebHID —— 回退到手动配对界面 // 或其他传输方式,而不是调用 navigator.hid。 return null; } const [device] = await navigator.hid.requestDevice({ filters: [] }); return device ?? null;}- 在调用任何 WebHID 方法之前先检测
navigator.hid——根据 MDN,它是实验性且非 Baseline 的特性,在部分浏览器中不存在是预期情况。 - 通过 HTTPS 提供页面;
navigator.hid仅在安全上下文中暴露。 - 只在具有用户激活(用户手势)的情况下调用
requestDevice(),否则会以SecurityError拒绝。 - 在后续访问时调用
getDevices(),以复用先前已授权的设备而无需新的提示。 - 在调用
sendReport()、sendFeatureReport()或receiveFeatureReport()之前,检查HIDDevice.opened/状态——在未打开的设备上调用都会以InvalidStateError拒绝。 - 不要仅因设备已打开就认为报告一定会成功:规范允许已打开设备上的“blocked report”
(被阻止的报告)以
NotAllowedError被拒绝。 - 记住一台物理设备可能对应多个
HIDDevice对象。