用屏幕唤醒锁定API防止睡眠

188 阅读6分钟

作者:Jaime Farnan-2021年3月12日

困倦的屏幕

哦,等等。这不会发生......并不是因为你在周二晚上对YouTube太好,而是因为你的手机浏览器足够聪明,在视频播放时保持清醒。撇开视频不谈,当我们在构建促进最小的用户互动的网络应用时,我们可以做什么,我们需要用户的设备保持清醒?一个解决方案是使用David Walsh的wakelock shim。然而,就这篇博文的意图和目的而言,我想给大家介绍一下未来可能出现的情况:屏幕唤醒锁API

当我为自己建立一个运动计时器时,我发现了这个宝石。这是一个完美的解决方案,因为当我在做物理治疗的背部拉伸时,我最不需要的就是我的屏幕计时和扰乱我的节奏。从MDN上看,*"屏幕唤醒锁定API提供了一种方法,可以防止设备在应用程序需要继续运行时调暗或锁定屏幕"。*这里有一些其他相关的说明。

  • 截至目前,屏幕唤醒锁定API是实验性的,打算成为W3C建议。
  • 它目前适用于Chrome、Edge、Opera、WebView Android、Chrome Android和Opera Android。
  • 需要Https。
  • 页面可见性是必需的(例如,导航到一个不同的标签 "释放 "锁)。

让我们开始工作吧!

在这篇文章中,我们不打算建立整个定时器;我们只是专注于WakeLock。

对于一个定时器应用,我们只关心当定时器处于活动状态时如何防止设备睡觉。让我们创建一个名为wakeLock 的新变量,并将其设置为null 。此外,由于这个规范是实验性的,让我们开辟一个try/catch 块,这样不支持的浏览器可以优雅地失败,而不会搞乱我们的收益整个程序。

let wakeLock = null
 
try {
  // WakeLock acquisition will go here
} catch (err) {
  console.log(`${err.name}, ${err.message}`)
}

在支持的网络浏览器中,我们通过调用基于承诺的navigator.wakeLock.request() 方法获得WakeLock,该方法在全局window 对象上可用。一旦承诺得到解决,我们就获得了对WakeLockSentinel 对象的访问权,我们的设备就被设定为保持清醒。让我们把我们的try/catch 块包裹在一个async 函数中,这样我们就可以await 访问WakeLockSentinel 。我们的代码现在应该是这样的。

let wakeLock = null
 
const acquireLock = async () => {
  try {
    wakeLock = await navigator.wakeLock.request('screen')
  } catch (err) {
    console.log(`${err.name}, ${err.message}`)
  }
}

也许事情在将来会发生变化,但现在,wakeLock的request 方法只需要一个参数:请求的type 。也只有一个type"screen" ,它被作为一个字符串传入。如果我们调用我们的acquireLock() 函数和console.log 我们的wakeLock 变量,我们将看到其released 状态被设置为false

WakeLockSentinel {onrelease: null, released: false, type: "screen"}
  onrelease: null
  released: false
  type: "screen"
  __proto__: WakeLockSentinel

完美!这正是我们想要的。这正是我们想要的。在一个虚假的释放状态下,我们的屏幕将保持清醒......只要我们不浏览(例如通过改变浏览器标签)或执行一个会 "释放 "锁的动作,例如调用WakeLock的release 方法(很快会有更多的内容)。

题外话:只是我,还是当你听到WakeLockSentinel ,你也会想到《X战警》系列动画片中的哨兵?

X-Men Sentinel hiding in plain sight

如果我自己说的话,哨兵是个无可挑剔的藏身之处。

一旦我们的运动计时器开始,我们就会调用我们的acquireLock 函数。当我们的时间用完时,我们需要释放锁......嗯......我们不需要......我们可以用我们用户的电池来代替!但我们要友好地对待。

Newman laughing

但让我们友好一点。记住,我们的WakeLock的released 状态目前是false 。为了扭转它并允许我们的设备再次睡眠,WakeLockSentinel 对象有一个release 方法。它返回一个承诺,当解析时,将释放的状态设置为true 。有时我喜欢用我的承诺来改变事情,所以我将在这里使用.then() 语法,但也可以随意使用async/await

const releaseLock = () => {
  if (wakeLock) {
    wakeLock.release().then(() => {
      wakeLock = null
    })
  }
}

所以我们已经考虑到了启动和停止我们的定时器。但是,如果 "岩石 "德维恩-约翰逊在我们正在锻炼的时候打电话来怎么办?很明显,我们要接这个电话......意味着我们刚刚离开了我们的运动计时器。哦,不!我不知道什么更糟糕:是我们释放了我们的WakeLock,还是意识到是 "卵石 "德维恩-约翰逊在打电话--历史上最糟糕的名人冒名顶替。

能见度状态

同时,回到现实中,我们的运动计时器仍在运行,但我们的屏幕不会再永远保持清醒。我们需要一种方法来重新获取我们的WakeLock,当用户离开后再导航回我们的应用程序。我们可以通过Page Visibility API来判断用户是否在我们的页面上活动。让我们打开我们的控制台,输入:document.visibilityState 。它应该输出一个字符串,"visible"

为了看看当用户放弃对这个标签的可见性时发生了什么,把你的控制台拆成自己的窗口。如果你使用的是Chrome浏览器,你可以通过点击面板右上方的三个垂直点,然后选择双矩形图标来做到这一点。每个浏览器都有点不同,但它们的行为应该相对类似。

打开一个新的浏览器标签,回到为另一个页面记录信息的控制台。如果我们现在输入document.visibilityState ,它应该返回字符串:"hidden" 。很好!这正是我们需要的。这正是我们需要的。让我们首先创建一个函数来处理visibilityState的变化。

const handleVisibilityChange = () => (
  document.visibilityState === 'hidden' ? releaseLock() : acquireLock()
)

当这个函数被调用时,我们要检查该页面是否可见。如果不是,我们将释放我们的锁。如果它是可见的,我们将重新获得它。现在我们只需要在用户离开和/或反弹到我们的页面时调用这个函数。是时候给我们的事件监听器接线了。

document.addEventListener('visibilitychange', handleVisibilityChange)

很好。现在我们可以压榨收益,与 "岩石 "对话,并且不用担心我们的设备在不恰当的时候超时而锁住屏幕了。

要想进一步阅读,请查看规范关注GitHub repo以保持对该功能的更新,或者阅读《哈利-波特》或其他什么......我没有说明你应该进一步阅读什么。你做你的,谢谢你的光临

分类: 技术

标签: javascript,学习