1

我正在为 Scratch3 编写一个基于 WebUSB 的扩展。在扩展构造函数中,我需要建立 WebUSB 连接。理想情况下,我想使用 navigator.usb.getDevices() 检查可用/配对的设备,如果失败,我想要求用户使用 navigator.usb.requestDevice() 选择设备。

问题是 navigator.usb.requestDevice() 需要从用户手势中调用。在大多数情况下,scratch3 扩展构造函数是从用户操作中调用的,因此我可以很好地使用 navigator.usb.requestDevice()。

但是 navigator.usb.getDevices() 返回一个 Promise 并从那里调用 navigator.usb.requestDevice() 失败,并显示“必须处理用户手势以显示权限请求”。

所以以下工作(但每次都会打开一个请求对话框):

navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] })
        .then(selectedDevice => {
            // ...
        })

但是由于缺少“用户手势”而导致以下失败:

navigator.usb.getDevices().then(devices => {
    if(devices.length == 0) {
        navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] })
            .then(selectedDevice => {
                // ...
        })
    }
})

我想避免弄乱 Scratch 3 核心,因此不想添加另一个 UI 元素。

在第一个片段中仅使用 navigator.usb.requestDevice() 有两个主要缺点:

  1. 它一直打开请求对话框,尽管它只需要一次
  2. 有时稍后可能会从非交互式情况调用构造函数,并且 navigator.usb.requestDevice() 会完全失败,而 navigator.usb.getDevices() 会成功

有没有办法使第二个代码片段的方法起作用?

4

2 回答 2

0

从 Chrome 72 开始,此问题已通过用户激活 v2功能修复。

于 2019-04-10T14:20:36.433 回答
0

我不熟悉 Scratch 3,但是是否可以getDevices()在您的扩展程序初始化时调用并推迟提供用户可以单击以触发的按钮,requestDevice()直到代码知道它是否已经有权访问设备?

提供了getDevices()方法onconnectondisconnect事件处理程序,以便页面可以使用任何可用设备使其界面保持最新。

于 2019-03-15T21:33:35.087 回答