2019/05/28 追記: 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を取得
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)にはフラグ付きの実装が入っていますが、まだ完成には程遠い試験実装程度の状態のようです。
-
また、Firefox OSでは古いバージョンのAPIがサポートされているようです(MDN)。
-
よく分かりませんが、EdgeではWinRT APIというものにアクセスすることで同じことができるそうです。それを用いたEdge用のPolyfillがあるようです。
-
Wake Lock APIを使わずに似たようなことをするNoSleep.jsというライブラリがあります。これは、ページ上で見えない動画を再生し続けることで画面が消えるのを防いでいるようです。