v154 · webhid on android

Asking for one

A filter, a gesture, and a chooser only the user can answer. Everything up to the chooser is code you write, and it is where the mistakes are — so this page builds the call, makes it for real, and records what came back.

Build a filter


    
Choose a filter and press a button.

What happened


    

The second button is the interesting one. It makes the identical call from a timer rather than from your click, which removes the transient user activation — and the rejection you get names the reason, which is more than most gesture-gated APIs manage.

What a filter can say

The four filter fields, and what each one narrows
fieldexamplewhat it matches

An empty filters array does not mean "no devices" — it means no constraint, so the chooser offers everything the browser is willing to show. That is rarely what you want: a chooser full of every HID device on the machine asks the user to make a decision they cannot make well.

And then

const [device] = await navigator.hid.requestDevice({ filters });
if (!device) return;               // the user closed the chooser — not an error

await device.open();
device.addEventListener("inputreport", ({ data, reportId }) => {
  // data is a DataView over the report body, without the report id byte
});

// Give the permission back when you are finished with it.
await device.forget();

The empty result is the case worth handling first: a user who closes the chooser has said no, and it arrives as an empty array rather than a rejection. Code that destructures without checking treats a considered refusal as a crash.

see also