JavaScript
WakeLockAPI

今からでも間に合う! JavaScriptのWake Lock APIの使い方

近頃、PWAに代表されるような、ブラウザアプリのモバイル端末への進出が進んでいることは皆さんご存知かと思います。とはいえ、ネイティブアプリに比べると、ブラウザ上で動くJavaScriptにできることは限られています。現在、それを補うために、JavaScriptから使用することができる様々なAPIが次々と策定されています。この記事で紹介するWake Lock APIもその1つです。

Wake Lockという言葉は、ネイティブアプリ開発をしている方なら知っている言葉かもしれません。これは、要するにほっといても画面が勝手に消えない機能です。

スマートフォンのような端末は、一定時間触らないでいると画面が消えてアプリ等の動作も止まるのが普通です。しかし例えば動画を再生するアプリなどは、触らないからといって勝手に消えてもらっては困ります。ですから、この自動画面オフを制御する機能が必要となるのです。そして、このような制御をJavaScriptから行えるのがWake Lock APIなのです。

Wake Lock APIの使用法

では、さっそくWake Lock APIの使用法を解説していきます。まず、WakeLockオブジェクトというものを取得する必要があります。そのために使うのがnavigator.getWakeLockメソッドです。このメソッドの返り値はPromiseであり、成功すればこのPromiseはWakeLockオブジェクトに解決されます。

WakeLockの取得
// スクリーンのWakeLockを取得
navigator.getWakeLock('screen').then(wakelock => {
  // WakeLockの取得に成功した
})
.catch(err => {
 // 失敗
  console.error(err);
});

WakeLockが設定で許可されていないなどの場合はWakeLockの取得に失敗することになります。

そして、実際に画面のWakeLockを有効にするにはWakeLockオブジェクトのcreateRequestメソッドを呼び出します。

リクエストの取得
// スクリーンのWakeLockを取得
navigator.getWakeLock('screen').then(wakelock => {
  // リクエストを取得
  const request = wakelock.createRequest();
});

createRequestによりリクエストを取得した時点でスクリーンのWakeLockが有効化され、勝手に画面が消えなくなります。

これを解除するためには、取得したリクエストのcancelメソッドを呼び出します。例えば、1分後に解除する単純なコードは次のようになります。

リクエストの解除
// スクリーンのWakeLockを取得
navigator.getWakeLock('screen').then(wakelock => {
  // リクエストを取得
  const request = wakelock.createRequest();

  setTimeout(()=> {
    // リクエストを解除
    request.cancel();
  }, 60000);
});

なお、createReqesutを複数回呼び出すことで複数個のリクエストを得ることも可能です。この場合、全てのリクエストが解除されるまでWakeLockは有効になります。この仕様は、複数のライブラリが独立にWakeLockを取得しても大丈夫なのでありがたいですね。

2種類のWakeLock

上のサンプルでは、getWakeLock'screen'という文字列を渡していることに気づいたかと思います。これはWakeLockの種類を表す引数であり、'screen''system'の2種類があります。

'screen'というのが今まで説明したような、自動的な画面オフを防ぐWakeLockです。

もうひとつ'system'というのがあり、これはCPUが省電力モードに移行してプログラムが止まるのを防ぐWakeLockです。実装にもよりますが、このWakeLockを取得しておくことで、場合によってはモバイル端末がロックされている状態でもプログラムを実行し続けることが可能です1

WakeLockオブジェクトのその他の機能

WakeLockオブジェクトには、現在WakeLockが有効かどうかを調べたり、有効/無効の状態が変化したときにイベントで知らせてもらえる機能もあります。

navigator.getWakeLock('screen').then(wakelock => {
  // activeプロパティ(真偽値)で現在の状態を取得
  if (wakelock.active) {
    console.log('なんかWakeLockが有効です');
  }
  // onactivechange イベントハンドラで状態の変化を検知
  wakelock.onactivechange = ()=> {
    if (wakelock.active) {
      console.log('有効になりました'); 
    } else {
      console.log('無効になりました');
    }
  };
  // WakeLockはEventTargetなのでaddEventListenerも使用可
  wakelock.addEventListener('activechange', ()=> { /* 省略 */ });
});

このactiveプロパティの情報はグローバルな状態であることに注意してください。すなわち、自分ではなく他の文書がWakeLockを取得した場合でもtrueとなります。実際に自分の文書がリクエストを取得しているかどうかは別問題なので、別途管理する必要があります2

WakeLockの有効範囲

'screen' WakeLockリクエストは、それを取得したページが表示されている間のみ有効です。つまり、'screen' WakeLockリクエストを取得しているページがあっても、そのページを閲覧していない場合(別のタブが開かれている場合など)は普通に画面が消えます。

また、WakeLockリクエストを取得している場合でも、例えばバッテリーが少ないなどの事情により、WakeLockが無効化されることがあります。JavaScript程度ではOSには逆らえないということですね。

なお、このような外的要因でWakeLockが無効化された場合も、ちゃんと前述のactiveプロパティはfalseになります。

また、Wake Lock APIはsecure contextでしか使えません。大雑把に言えば、HTTPSで配信されているページでないと使えないということです。

Wake Lock APIの仕様はこれだけです。シンプルで結構分かりやすいですね。

※ Wake Lock APIはまだW3C勧告ではないため、将来的に内容の変更があるかもしれません。ご注意ください。

対応ブラウザ

対応ブラウザはまだありません。Chrome Platform Status

よかったですね、間に合いました。

※ 記事執筆時点(2018年10月12日)の情報です。


  • ただ、Chrome(Chromium)ではつい最近実装されたようです(257511 - Implement WakeLock API)。そのうちChromeで利用可能になるかもしれません。

  • また、Firefox OSでは古いバージョンのAPIがサポートされているようです(MDN)。

  • よく分かりませんが、EdgeではWinRT APIというものにアクセスすることで同じことができるそうです。それを用いたEdge用のPolyfillがあるようです

  • Wake Lock APIを使わずに似たようなことをするNoSleep.jsというライブラリがあります。これは、ページ上で見えない動画を再生し続けることで画面が消えるのを防いでいるようです。


  1. 仕様書の“Manually switching off the screen MUST NOT affect the applicability of the system wake lock.”という文を根拠としていますが、実際問題として本当にそんなことが許可されるのかはよく分かりません。  

  2. 実際、仕様書では無関係な(オリジン境界をまたいだ)文書間で通信が行える可能性が指摘されています。モールス信号で通信するライブラリとかが発生したら面白いですね。OSからしたらいい迷惑ですが。