[Android] Doze mode で AlarmManager の繰り返しアラームを実装するには

AlarmManagerで繰り返しのアラーム機能を実装したいのですが、バックグラウンド実行制限があります。本来の機能として定期的なバックグラウンド処理のためにはちょっと工夫が必要です。
 
1x1.trans - [Android] Doze mode で AlarmManager の繰り返しアラームを実装するには


Android Studio 3.5.3
API 29

 




setExactAndAllowWhileIdle

 

Dozeモードはバッテリーの寿命を延ばすための省電力機能ですが、その制限事項として、標準AlarmMangerはメンテナンス時間枠まで保留になります。定期的なアラームは制限されるわけですが、

アラームのスケジュール設定をサポートするため、Android 6.0(API レベル 23)では、setAndAllowWhileIdle() と setExactAndAllowWhileIdle() という 2 つの新しい AlarmManager メソッドが導入されています。 このメソッドを使用すると、端末が Doze モードになっていてもアラームが発生するように設定できます。

Reference: Doze と App Standby 用に最適化する | Android Developers
ということで、このsetExactAndAllowWhileIdleを実装してみます。ただし、これも9分に1回までのようです。
 

 

繰り返し、Repeating

 

AlarmManagerにはsetRepeating()というのがありますが inexact つまりばらつきがある繰り返しになってしまいます。xxxAndAllowWhileIdleにsetRepeatingというのもありません。

ある程度精度があるアラームが必要な場合はsetExact… を使うことになりますが、Serviceで可能です。
Serviceが開始したところで次のサービスをAlarmManagerで呼び出すというやり方で実現できます。
TestService.java

 

startForegroundService()

 

ただ、Serviceはバックグラウンド制限のため今までのようには使えません。

Android 8.0 では、追加機能があります。システムは、バックグラウンド アプリによるバッグラウンド サービスの作成を許可しません。 そのため、Android 8.0 では、フォアグラウンドで新しいサービスを作成する Context.startForegroundService() メソッドが新たに導入されています。

Reference: バックグラウンド実行制限 | Android Developers
BackgroundではなくForegroundだと”言い張る”ということですか、はい。
このあたりはこちらで試しています。
 

service 00 100x100 - [Android] Doze mode で AlarmManager の繰り返しアラームを実装するには
Servce はバックグラウンドで作業をさせたい場合に使います。システムは直ぐにスリープに入れてしまいます。それでも裏で色々やりたい場合に有...

 
このForegroundServiceを使うためにはNotificationを使う必要があるため、通知エリアにはアイコンが表示され通知ドロワーにはアプリ名、そして通知音が鳴る(対策無しだと)ということになります。

 

サンプルコード

 

Doze中でも繰り返しができるように、15分に1回、作業は短く内部ストレージのファイルに時間を書き込むという形で作って見ました。
 
MainActivity.java

 
Serviceを実行するクラスを新しく作成します。
TestService.java

 
Manifest.xml

 
ファイル書込み読出し用のクラスです。
InternalFileReadWrite.java

 
レイアウトです。

 
strings.xml

 

結果

 setExactAndAllowWhileIdle:15分間隔

これで一晩寝かせてみました。上のコードの通り15分間隔で時間を記録するアプリをstartさせて、アプリを終了。マルチタスクメニューからも削除。
 
1x1.trans - [Android] Doze mode で AlarmManager の繰り返しアラームを実装するには


 
夜7時頃から12時間です、ほぼ15分間隔で実行されていました、途中で多少ずれているのは不明です。完璧ではないということでしょうか。
 
setExactAndAllowWhileIdle:1分間隔
ついでに1分間隔でのテストもやってみました。
15分間隔のアラームを1分間隔に変更

 
1x1.trans - [Android] Doze mode で AlarmManager の繰り返しアラームを実装するには


 
最初は1分間隔ですがあるところで9分にさせられています。またあるところで1分間隔になったりしていますがこれは端末を持って移動していた時間帯です。深いDozeから浅いDoze、あるいはStand byになったのでしょうか。
 
setExact:1分間隔
正確なアラーム間隔ですが、Doze 中にどうなるかです
 

 
1x1.trans - [Android] Doze mode で AlarmManager の繰り返しアラームを実装するには


 
最初の1時間は1分間隔ですが、その後間隔が伸びて約2時間、4時間、6時間間隔となっていました。Dozeの影響でしょうか
 
関連ページ:

 

References:
サービス | Android Developers
バックグラウンド実行制限 | Android Developers
Service | Android Developers

シェアする

  • このエントリーをはてなブックマークに追加

フォローする