跳转到内容

Idle Detection API:检测用户与屏幕的空闲状态

发布于 更新于

一句话: Idle Detection API 的 IdleDetector 接口让页面能够查询用户在给定阈值内是 否与屏幕或设备发生过交互,以及屏幕当前是否锁定,并在任一状态发生变化时触发 change 事件。

根据 MDN,启动 IdleDetector 需要 idle-detection 权限,且 IdleDetector.requestPermission() 需要瞬态用户激活——必须在用户手势(例如点击处理器) 内部调用:

startButton.addEventListener('click', async () => {
const permission = await IdleDetector.requestPermission();
if (permission !== 'granted') {
console.error('Idle detection permission denied.');
return;
}
await startIdleDetector();
});

start() 接收一个以毫秒为单位的 threshold 及一个可选的 AbortSignal。根据 WICG 规范,当 threshold 低于 60,000ms(60 秒)时,start() 会以 TypeError 拒绝—— 没有办法要求更细粒度的报告:

async function startIdleDetector() {
const controller = new AbortController();
const idleDetector = new IdleDetector();
idleDetector.addEventListener('change', () => {
console.log(`User: ${idleDetector.userState}, Screen: ${idleDetector.screenState}`);
});
await idleDetector.start({
threshold: 60_000,
signal: controller.signal,
});
}

userState 报告 "active" 或 "idle";screenState 报告 "locked" 或 "unlocked"。 根据 MDN,两者在调用 start() 之前都返回 null,start() 会为它们赋予初始值。

根据 MDN 的兼容性数据,IdleDetector 仅在基于 Chromium 的浏览器中提供(自 Chrome 94 版起),且需要安全上下文。Firefox 和 Safari 均未实现它。

async function watchIdleState(onChange) {
if (!('IdleDetector' in window)) {
// 不受支持:这里没有这个 API 所暴露的操作系统级空闲/锁定状态可报告,
// 因此直接报告 unknown,而不是去猜测。
onChange({ userState: 'unknown', screenState: 'unknown' });
return;
}
const permission = await IdleDetector.requestPermission();
if (permission !== 'granted') {
onChange({ userState: 'unknown', screenState: 'unknown' });
return;
}
const idleDetector = new IdleDetector();
idleDetector.addEventListener('change', () => {
onChange({ userState: idleDetector.userState, screenState: idleDetector.screenState });
});
await idleDetector.start({ threshold: 60_000 });
}
  • 在引用该类之前先用 'IdleDetector' in window 做特性检测——它在 Firefox 和 Safari 中并不存在。
  • 在用户手势内部调用 IdleDetector.requestPermission();没有瞬态用户激活的调用 按规范会失败。
  • 不要把 threshold 设置为低于 60,000ms——start() 会以 TypeError 拒绝, 而不仅仅是报告得更慢。
  • 在调用 start() 之前,将 userState 和 screenState 视为 null;不要在 构造之后立即同步读取它们。
  • 为目前尚未实现该 API 的 Firefox 和 Safari 提供可用的回退体验,而不是静默降级。