能力 · API
Screen Wake Lock API
发布于
navigator.wakeLock.request("screen") 请求操作系统在文档保持可见期间不要调暗或锁定屏幕,并以一个 WakeLockSentinel 兑现;这把锁由你主动释放,页面一旦被隐藏浏览器也会替你释放。它适合菜谱页、演示文稿、实时追踪界面这类场景;对后台任务毫无作用,因为隐藏的文档既持有不了也申请不到锁。
Chrome 84、Edge 84、Firefox 126 与 macOS 上的 Safari 16.4 无附加条件地实现了该 API。iOS 上的 Safari 16.4 至 18.3 在 browser-compat-data 中记为 partial:在独立运行的主屏幕 Web App 中锁不起作用(WebKit bug 254545),该条目把 iOS 18.4 列为首个完整支持的版本。
navigator.wakeLock.request()navigator.wakeLock.request(type)
sentinel.release()request() 返回 Promise<WakeLockSentinel>。sentinel 上的 release() 返回 Promise<undefined>,锁消失时(无论由谁释放)在 sentinel 上触发 release 事件。两个接口都带 [SecureContext] 且只暴露在 Window 上:在 localhost 以外的 http:// 源上 navigator.wakeLock 为 undefined,worker 中则完全没有唤醒锁。
request() 接受一个可选参数;它兑现的 sentinel 暴露三个成员和一个事件。
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
type |
WakeLockType(枚举) |
否,默认 "screen" |
规范定义的唯一取值是 "screen"。曾讨论过 "system" 类型(熄屏但让 CPU 保持运行),后来被放弃;传入它违反 WebIDL 枚举约束。 |
WakeLockSentinel 成员 |
类型 | 说明 |
|---|---|---|
released |
boolean(只读) |
持有锁期间为 false;release() 兑现后或浏览器释放后为 true。Chrome 87 加入该属性(Chrome 84 至 86 的 sentinel 没有它)。 |
type |
WakeLockType(只读) |
回显请求的类型,即 "screen"。 |
release() |
Promise<undefined> |
把这个 sentinel 从文档的活动锁列表中移除;同类型再无其他 sentinel 时释放平台锁。 |
release 事件 |
Event |
每个 sentinel 被释放时触发一次,包括浏览器在页面隐藏、文档卸载或系统干预时执行的释放。 |
多个 sentinel 可以同时存活;最后一个释放时平台锁才释放。document.visibilityState 变为 "hidden" 时浏览器会释放全部 sentinel,页面重新可见时不会自动恢复。
request() 以 DOMException 或 TypeError 拒绝。规范定义的每一种拒绝都使用同一个名称。
| 异常 | 条件 |
|---|---|
NotAllowedError |
文档不是 fully active;或 screen-wake-lock Permissions Policy 拒绝了该文档(默认允许列表为 'self');或浏览器拒绝为该文档提供此类型的锁;或调用时、或权限检查结束时 document.visibilityState 为 "hidden";或 screen-wake-lock 权限的结果为 "denied"。 |
TypeError |
type 不是 WakeLockType 枚举的成员(WebIDL 转换在算法开始前就失败)。 |
电量低或处于省电模式是规范允许浏览器拒绝锁的理由(第 12 节 Security considerations),在 Chromium 中这种拒绝表现为 NotAllowedError。更底层的操作系统失败则被刻意隐藏:规范注明被系统拒绝的锁与成功获取的锁不可区分,因此 Promise 照样兑现,released 保持 false。release() 不会拒绝;对已释放的 sentinel 调用它会立即兑现。
两个示例都先检测 navigator.wakeLock,缺失时(Firefox 126 之前、Safari 16.4 之前、去掉了该权限的 Android WebView 构建)执行回退分支。
健身计时期间保持屏幕常亮,切换标签页后重新获取
Section titled “健身计时期间保持屏幕常亮,切换标签页后重新获取”页面一旦隐藏锁就会丢失,所以 visibilitychange 监听器在页面回到前台且训练仍在进行时重新申请。API 不存在时,应用显示一行提示,而不是任由屏幕悄悄熄灭。
let sentinel = null;let workoutRunning = false;
async function keepScreenOn() { if (!('wakeLock' in navigator)) { document.querySelector('#hint').textContent = '请在系统设置中调长屏幕超时时间;此浏览器没有唤醒锁。'; return; } try { sentinel = await navigator.wakeLock.request('screen'); sentinel.addEventListener('release', () => { sentinel = null; }); } catch (err) { console.warn(`${err.name}: ${err.message}`); }}
document.querySelector('#start').addEventListener('click', async () => { workoutRunning = true; await keepScreenOn();});
document.querySelector('#stop').addEventListener('click', async () => { workoutRunning = false; await sentinel?.release();});
document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible' && workoutRunning && !sentinel) { keepScreenOn(); }});浏览器已经释放锁之后调用 sentinel?.release() 是安全的:release 监听器已把 sentinel 置为 null,可选链会跳过这次调用。
让复选框跟随真实的锁状态
Section titled “让复选框跟随真实的锁状态”声称“屏幕正保持常亮”的控件必须跟随 sentinel 而不是跟随点击,因为浏览器可能在用户没碰复选框的情况下释放锁。在 release 处理函数里读取 released 能让两者保持一致。
const box = document.querySelector('#keep-awake');let sentinel = null;
box.disabled = !('wakeLock' in navigator);
box.addEventListener('change', async () => { if (box.checked) { try { sentinel = await navigator.wakeLock.request('screen'); sentinel.addEventListener('release', () => { box.checked = !sentinel.released; // 浏览器放手后变为 false }); } catch (err) { box.checked = false; // 被拒绝:页面隐藏、策略拒绝或权限被拒 } } else { await sentinel?.release(); }});navigator.wakeLock 缺失时直接禁用复选框,用户一开始就知道这里没有该选项,而不是第一次切换时才失败。
- Media Session API,播放界面同时需要锁屏控件时的搭档
- Idle Detection API,用于响应用户离开,而不是阻止屏幕锁定
- iOS 与 Safari 上的 PWA,主屏幕 Web App 的例外情况记录在那里
- Screen Wake Lock API: request() method(w3.org)
- Screen Wake Lock API: Security considerations(w3.org)
- WebKit bug 254545: Screen Wake Lock in Home Screen web apps(webkit.org)
- Stay awake with the Screen Wake Lock API(developer.chrome.com)
规范
| 规范 | 状态 |
|---|---|
| Screen Wake Lock(屏幕常亮锁) | W3C |
| Screen Wake Lock API: request() method | W3C |
| Screen Wake Lock API: release() method | W3C |
- 图例
- 支持
- 部分支持
- 需开启标志
- 不支持
- 未知
| 浏览器 / 平台 | 支持 | 版本 | 置信度 | 来源 | 备注 |
|---|---|---|---|---|---|
| Chrome (Desktop) | 支持 | 84 | 高 | 来源 | — |
| Chrome (Android) | 支持 | 84 | 高 | 来源 | 1 |
| Edge (Desktop) | 支持 | 84 | 高 | 来源 | 2 |
| Firefox (Desktop) | 支持 | 126 | 高 | 来源 | — |
| Firefox (Android) | 支持 | 126 | 高 | 来源 | 3 |
| Safari (macOS) | 支持 | 16.4 | 高 | 来源 | — |
| Safari (iOS) | 部分支持 | 16.4 → 18.4 | 高 | 来源 | 4 |
| Samsung Internet | 支持 | 14.0 | 高 | 来源 | 5 |
| WebView (Android) | 支持 | 84 | 高 | 来源 | 6 |
| Opera | 支持 | 73 | 低 | 来源 | — |
- 由 browser-compat-data 镜像自 Chrome 的数据推导。
- 由 browser-compat-data 镜像自 Chrome 的数据推导。
- 由 browser-compat-data 镜像自 Firefox 的数据推导。
- 在 standalone 模式的主屏幕 Web 应用中不可用。见 bug 254545(https://webkit.org/b/254545#c32)。
- 由 browser-compat-data 镜像自 Chrome Android 的数据推导。
- 由 browser-compat-data 镜像自 Chrome Android 的数据推导。