flutterで画面ごとではなく、任意のタイミングで端末の自動スリープを抑制する方法
やりたいこと
特定の画面ごとに自動スリープを抑制するのではなく、
例えば動画が再生できる画面において、
動画再生中にのみ自動スリープを抑制、動画再生されていない時は自動スリープをさせたい
利用するpackage
端末の画面スリープを抑制できるpackageです本稿におけるwakelockについての知識は以下のみでOKです
// 端末の自動スリープ抑制をONにする
Wakelock.enable();
// 端末の自動スリープ抑制をOFFにする
Wakelock.disable();
ミニマムな実装
動画再生中にwakelockをenable, 非再生中にはwakelockをdisableにしたい場合の
ミニマムな実装方法としては、以下のようになるとは思います
※https://pub.dev/packages/video_playerを使用してます。
class MyVideoPlayer {
late VideoPlayerController _controller;
bool _isPlaying = false;
Future<void> init(String url) async {
_controller = VideoPlayerController.network(url);
await _controller.initialize();
_controller.addListenter(() {
_playerStatusListener();
_wakelockListener();
},
);
}
_playerStatusListener() {
_isPlaying = _contoller.value.isPlaying;
}
_wakelockListener() {
_isPlaying ? Wakelock.enable() : Wakelock.disable();
}
}
ミニマムな実装ではちょっと物足りない
上記のミニマムな実装で事足りるアプリもあると思いますが、対応しきれないケースもあります
例えば、
60秒の動画と、10秒の音声ファイルが二つ同時に再生される画面において、
動画の再生中と音声ファイルの再生中はwakelock
をenable
にしたい。
のようなケースを考えたとき、上記のミニマムな実装ではカバーしきれません。
60秒の動画を全て再生し切るよりも先に10秒の音声ファイルの再生が終了してしまい、
(音声ファイル非再生時のwakelock.disable()
がcallされる)
動画再生中にも関わらず、端末の自動スリープが有効になってしまいます。
もう少し柔軟性のある実装
上記ケースに対応するため、
複数機能から異なるタイミングで操作されても問題ないような、
Wakelock
をラップしたclassを実装をしてみます
class MyWakelock {
// インスタンスが一つしか存在しないことを保証したいのでSingletonとして実装
static final MyWakelock _instance = MyWakelock._();
MyWakelock._();
factory MyWakelock() {
return _instance;
}
int _count = 0;
void enableRequest() {
_count++;
if (_count > 0) Wakelock.enable();
}
void disableRequest() {
_count--;
assert(_count >= 0, "_count is negative value.($_count) As expected?");
if (_count <= 0) Wakelock.disable();
}
}
考え方としてはGCの参照カウンタと同じで、
enableRequest
がcallされるとcount
をincrementし、disableRequest
がcallされるとcount
をdecrement、
count
が1以上の時にWakelock
をenable、0以下の時にWakelock
をdisableにします
そして、
Wakelock
を操作をしたい機能からは直接Wakelock.enable()
, Wakelock.disable()
をcallするのではなく、
enable/disable
にしたい、という申請をこのclassへ行い、
実際にenable/disable
にするかはまるっと任せてるようにします
すると、
60秒の動画と15秒の音声ファイルを同時に再生し (countは2)、
15秒の音声ファイルの再生が先に終了 (count--) したとしても、
画面スリープの抑制はonのままにしておくことができます。(countは1)
その後動画の再生が終了すると、画面スリープの抑制はoffになります。 (count--でcountが0になる)
期待通りの動作です。
今回は以上になります
誰かの参考になれば幸いです
また、もっとスマートな実装方法があればご教授いただけるとさらに幸いです!
※初めて記事を書いてみたらすっかり深夜になってしまったため、のちほど実際に動くコードベースのリンクを追加しておきます。
Author And Source
この問題について(flutterで画面ごとではなく、任意のタイミングで端末の自動スリープを抑制する方法), 我々は、より多くの情報をここで見つけました https://zenn.dev/tady/articles/6324968cd24a4b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol