トップAndroid Java > GPSログを取り続ける方法

GPSログを取り続ける方法

前ページ

はじめに

現在は外出時には位置情報を取り続けているため、バッテリ消費の大半を占めるのは位置情報取得となる。 バッテリ消費は自宅では大体が 0.5〜1.0%/時であるが、自宅外で位置情報取得(GPS主体)を1〜3秒間隔で取り続けた場合、約3%/時となる。

夏は外出時間が短いため、全体に占める割合は小さいが、このままではやがて大きな割合を占めるようになる。 まずは 2%以下/時 に抑えることを目指したい。

この2か月近くは、バッテリ使用量の削減に取り組んだ。 モバイルネットワークスタンバイの使用量が大きい原因をあれこれ探ったが、位置情報取得が関係していることが分かった。

いくつかの改善点があるが、急ぐのではなく、十分に日時をかけて少しずつ改善したい。


[2023.12.10] 最近、自作地図アプリで位置情報取得が止まってしまうことが多くなった。 多分、OSがバッテリ使用を抑制するために、位置情報取得サービスを止めてしまうのであろう。

位置情報取得失敗が何度か続いた場合、位置情報取得をやめてしまうのかも知れない。

位置情報取得が継続して行われていることを監視して、位置情報取得が止まっていると判断したときは、 位置情報取得サービスを一旦強制終了して、再開するなど、何らかの措置により、実質的に位置情報取得が続くようにしたい。

ログ取得間隔

スマホの位置情報はバッテリ使用量節減のため、Windowsタブレットに比べて精度が低いため、 短い間隔で取得する意味がない。これまで、徒歩は3秒間隔、車両は1秒間隔としていたが、 徒歩(IntervalWalk)は5秒間隔、車両(IntervalViecle)は2秒間隔に変更する。これにより、外出時のバッテリ使用量は若干減少するであろう。

さらに、休憩中、食事中など動きが極めて少ない時(IntervalSlow)は 10秒間隔とした。 もっと大きくしたいところであるが、そうすると、動き始めが迅速にキャッチできない。


IntervalWalkからIntervalSlowのみで、IntervalViecleでは無視する。 StepCounterでも IntervalSlowから IntervalWalk に変更するが、 静止状態から電車、バス、車に乗った場合、StepCounterでは検出できないケースが多い。 加速度センサを使えば、移動を検出できるが、当面は最大10秒間の遅れを許容する。 IntervalSlow をもっと大きくするには、加速度センサの情報も使う必要がある。

位置情報取得権限設定

位置情報へのアクセスは「常に許可」とする。「アプリの使用中のみ許可」 この場合、Serviceが動いていても、Activityが休止すると、位置情報取得がストップする。

ServiceからActivityへの位置情報のbroadcast

Serviceは24時間稼働であり、位置情報を取り続けて、それを broadcast している。 Activity が休止中のデータはOSが蓄えているようで、アクティブになったとき、 まとめて受け取るようである。

現行プログラムでは、ログファイルへの書き込みは Service で行っている。 その日のログは Activity のメモリにあるので、通常は読み込む必要はないが、 MapX を強制停止して再起動した場合にはその日のログを読み込む必要がある。 Serviceでの書き込みとActivityの読み込みがぶつからないようにする必要がある。 現在は、Serviceではデータをメモリに蓄えて、5分間隔でファイルに書き込んでいるため、 この書き込みと読み込みがぶつかる可能性は極めて低い。万一ぶつかった場合、 地図アプリの再起動をやり直せばよいので、必ずしも排他制御は要らない。

Activityがスリープ中のログは捨てられると思い、Serviceでログを書き込むようにしたが、 スリープ中のログは OS がバッファリングしており、アクティブになったとき、 まとめて受け取るのであれば、Activityでログをファイルに書き込むように変更すれば、 再起動時にファイルの読み込みと書き込みがぶつかることはない。

しかし、スリープ中にシャットダウンした場合、残りのログがファイルに書き込まれない。 やはりログ書き込みは Service で行うべきのようだ。

ログ記録

現在はログをメモリ上に蓄えて、ログの書き込み回数を減らしている(5分間隔で書き込む)。 強制停止するときには、たまっている分を書き込む必要があるが、この処理が漏れている。

BufferedWriterを使えば、自前でバッファリングしなくても済むであろう。 ただし、 時々 Flush したり、強制終了で Flush することは必要である。

ログ書き込みのオーバヘッドは少し増えるかも知れないが、プログラムを簡単にしたい。 具体的には、 Intent.ACTION_TIME_TICK、Intent.ACTION_SHUTDOWN で Flushタイミングを得る。

24時間稼働であり、午前0時に新ファイルに変わる。 日付の変更に的確に対応したい。 Intent.ACTION_TIME_TICKで日付の変更を検出するのがいいだろう。 日付が変わったら、現在のログファイルを flush/close して、新しい日付に対応するファイルを生成する。

システムログとGPSログは同じように日付別とするので、なるべくプログラムを共通化したい。

2.プログラム修正記録

2023.7.24 GPS軌跡の表示がおかしい【解決】

2、3日前に、バッテリ使用量を調べるために、1日あまり、MapX を止めていた。 昨日、再開したが、GPS軌跡が途切れ途切れになる。念のため、Mapを動かしてみたが、異常はない。

この間、MapXのプログラムを少し修正したかも知れない。

位置情報へのアクセスは「常に許可」とする。これを「アプリの使用中のみ許可」に変えていた。 この場合、Serviceが動いていても、Activityが休止すると、位置情報取得がストップする。

A.リファレンス

[1] 電池の最適化をオフにする方法
[2] デバイスの起動状態を維持する
[3] [Android] バックグラウンドでGPSログを取り続けるには
[4] 常駐するサービスの作成
[5] AndroidアプリでForeground Serviceを使って、画面スリープ状態でも位置情報を定期取得する
[6] [Android] Service の使い方
[7] ウェイクロック: Android* アプリケーションでスリープしない問題の検出
[8] 直近の位置情報を取得する
[9] open-gpstracker
[10] ブロードキャストレシーバの実装によるアクティビティとサービスの通信
[11] バックグラウンドでの位置情報へのアクセス
[12] 現在地の更新情報をリクエストする
[13] android / location-samples
[14] LocationUpdatesForegroundService
[15] location-samples/LocationUpdatesPendingIntent/
[16] AndroidアプリでForeground Serviceを使って、画面スリープ状態でも位置情報を定期取得する[kt]
[17] Androidでよく書く基本的な記述集(その1)
[18] SERVICEを使う(1) LOCALSERVICEによる常駐型アプリ