Sensor APIs - 向 Web 平台公开一致性的设备传感器接口
Sensor API(传感器 API)是根据通用设计构建的一组接口,以一致的方式向 Web 平台公开设备传感器。
传感器 API 的概念和用法
尽管通用的传感器 API 规范定义了一个 Sensor
接口,但作为 Web 开发人员,您不会使用到它。相反,您将使用它的一个子类来检索特定类型的传感器数据。例如,Gyroscope
接口返回设备在读取时沿所有三个轴的加速度。
传感器可能与物理设备传感器完全对应,也可能不完全对应。例如,Gyroscope
接口与物理设备接口完全对应。AbsoluteOrientationSensor
接口则提供从两个或多个设备传感器通过算法聚合的信息。这些传感器类型分别称为低级和高级。后一种类型的传感器也称为融合传感器(或者,虚拟或合成传感器)。
特征检测
传感器接口只是底层设备传感器的代理。因此,传感器的特征检测比其他 API 更复杂。传感器 API 的存在并不能告诉您该 API 是否连接到真正的硬件传感器、该传感器是否工作、它是否仍然连接,甚至用户是否已授予对它的访问权限。使所有这些信息一致可用会对性能和电池寿命造成很大影响。
因此,传感器 API 的功能检测必须包括对 API 本身的检测和防御性编程策略 (见下文)。
下面的实例显示了三种检测传感器 API 的方法。此外,您还可以将对象实例化放在一个 try...catch
块中。请注意,不应该通过 Navigator
接口进行检测。
if (typeof Gyroscope === "function") {
// ...
}
if ("ProximitySensor" in window) {
// ...
}
if (window.AmbientLightSensor) {
// ...
}
防御性编程
如特征检测中所述,检查特定传感器 API 不足以进行特征检测。 还必须确认实际传感器的存在。 这就是需要防御性编程的地方。 防御性编程需要三种策略。
- 检查实例化传感器对象时引发的错误。
- 侦听在使用过程中抛出的错误。
- 优雅地处理错误,从而增强而不是降低用户体验。
下面的代码实例说明了这些原则。try...catch
块捕获传感器实例化期间引发的错误。它侦听 error
事件以捕获在使用过程中引发的错误。只有在需要请求权限以及设备不支持传感器类型时,才会向用户显示内容。
Note: 如果功能策略阻止使用该功能,则原因是您的代码与服务器上设置的策略不一致。该情况不会向用户显示出来。有关实现说明,请参阅
Feature-Policy
。
let accelerometer = null;
try {
accelerometer = new Accelerometer({ referenceFrame: 'device' });
accelerometer.addEventListener('error', event => {
// 处理运行时错误。
if (event.error.name === 'NotAllowedError') {
// 处理用于请求权限的代码。
} else if (event.error.name === 'NotReadableError' ) {
console.log('无法连接到传感器。');
}
});
accelerometer.addEventListener('reading', () => reloadOnShake(accelerometer));
accelerometer.start();
} catch (error) {
// 处理构造错误。
if (error.name === 'SecurityError') {
// 请参阅上面有关功能策略的说明。
console.log('初始化传感器被功能策略阻止。');
} else if (error.name === 'ReferenceError') {
console.log('用户代理不支持传感器。');
} else {
throw error;
}
}
权限和功能策略
除非用户向特定类型的传感器授予许可,否则不能获取传感器数据。请使用 Permissions API 进行操作。下面显示了一个简短的实例,该实例在尝试使用传感器之前请求许可。
navigator.permissions.query({ name: 'accelerometer' })
.then(result => {
if (result.state === 'denied') {
console.log('使用加速度传感器的许可被拒绝。');
return;
}
// 使用传感器。
});
另一种方法是尝试使用传感器并侦听 SecurityError
。
const sensor = new AbsoluteOrientationSensor();
sensor.start();
sensor.addEventListener('error', error => {
if (event.error.name === 'SecurityError')
console.log("没有使用 AbsoluteOrientationSensor 的权限。);
});
下表描述了每种传感器类型、权限 API 所需的名称、<iframe>
元素的 allow
属性和 Feature-Policy
指令。
传感器 | 权限 / 功能策略名称 |
---|---|
AbsoluteOrientationSensor |
'accelerometer' ,'gyroscope' 和 'magnetometer' |
Accelerometer |
'accelerometer' |
AmbientLightSensor |
'ambient-light-sensor' |
GravitySensor |
'accelerometer' |
Gyroscope |
'gyroscope' |
LinearAccelerationSensor |
'accelerometer' |
Magnetometer |
'magnetometer' |
RelativeOrientationSensor |
'accelerometer' 和 'gyroscope' |
读数
传感器读数是通过所有传感器类型继承的 READING
事件回调来接收的。读取频率由您决定,通过将一个选项传递给传感器的构造函数来实现。该选项是一个指定每秒读数的数字。可以使用整数或小数,后者用于频率小于一秒的频率。实际读取频率取决于设备硬件,因此可能小于请求的读取频率。
下面的实例使用 Magneteter
传感器说明了这一点。
let magSensor = new Magnetometer({frequency: 60});
magSensor.addEventListener('reading', e => {
console.log("沿 X 轴方向的磁场:" + magSensor.x);
console.log("沿 Y 轴方向的磁场:" + magSensor.y);
console.log("沿 Z 轴方向的磁场:" + magSensor.z);
})
magSensor.addEventListener('error', event => {
console.log(event.error.name, event.error.message);
})
magSensor.start();
接口
AbsoluteOrientationSensor
安全上下文
描述设备相对于地球参考坐标系的物理方向。
Accelerometer
安全上下文
提供沿所有三个轴应用于设备的加速度。
AmbientLightSensor
安全上下文
返回宿主设备周围环境光的当前灯光级别或照度。
GravitySensor
安全上下文
提供沿所有三个轴应用于设备的重力。
Gyroscope
安全上下文
提供设备沿所有三个轴的角速度。
LinearAccelerationSensor
安全上下文
提供沿所有三个轴应用于设备的加速度,不包含重力的影响。
Magnetometer
安全上下文
提供有关由设备的主磁力计传感器检测到的磁场的信息。
OrientationSensor
安全上下文
AbsolteOrientationSensor
的基类。此接口不能直接使用,它提供了属性和方法用于继承。
RelativeOrientationSensor
安全上下文
描述设备的物理方向,不包含地球的参考坐标系。
Sensor
安全上下文
所有其他传感器接口的基类。此接口不能直接使用。相反,它提供用于继承它的接口访问的属性、事件处理程序和方法。
SensorErrorEvent
安全上下文
提供有关由 Sensor
或相关接口引发的错误的信息。
规范
规范 |
---|
Generic Sensor API |
Accelerometer |
Ambient Light Sensor |
Gyroscope |
Magnetometer |
Orientation Sensor |
桌面浏览器兼容性
特性 | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
基础支持 | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
activated | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
hasReading | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
onactivate | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
onerror | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
onreading | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
start | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
stop | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
timestamp | 67 | 79 | 不支持 | 不支持 | 54 | 不支持 |
移动浏览器兼容性
特性 | Android | Chrome for Android | Edge mobile | Firefox for Android | IE mobile | Opera Android | iOS Safari |
---|---|---|---|---|---|---|---|
基础支持 | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
activated | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
hasReading | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
onactivate | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
onerror | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
onreading | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
start | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
stop | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |
timestamp | 67 | 67 | 未知 | 不支持 | 未知 | 48 | 不支持 |