まだ、Android の Activity と Service の違いを100%理解しているわけではないが、徐々に理解が深まっている。 レンダリングは複数のスレッドで実行している。メインスレッドとレンダリングスレッドとのデータ交換や共有は簡単であるが、 Service は別のプロセスと考えた方が良さそうだ。簡単にデータ交換や共有ができない。
地図アプリでは、位置情報取得は Service として実装している。 地図アプリの主体は Activity であり、操作している時間はごく短い。一方、位置情報取得 Service は通常は一日中稼働している。 就寝時など動かす必要はないが、止めてしまうと動かし始めるタイミングが難しいため、現在は24時間稼働としている。
ただし、自宅にいると推測される時間帯では、位置情報取得間隔を長くし、精度を抑えて、電池の消耗が少なくなるようにしている。
電池の消耗が大きいのは、デバッグやスマホ画面を見る時間が長いときである。位置情報取得自体はそれほど電池を消耗しない。
位置情報は Broadcast機能を使って、Service から Activity に送っている。 Service では、位置情報を Locationインスタンスとして入手する。ログファイルへの書き込みは Service で行っている。
Activity には Broadcast を送る。プロセス間通信のようなものであるから、送るデータはシリアライズが必要である。
位置情報所得Service は地図アプリActivity が起動する。独立に動くにせよ、その配下である。 このようなケースでは Locationインスタンスを Broadcast で送受信するテストも1年ほど前に行った。
ただ、全く独立した別アプリではうまく行かなかったように記憶している。 最初は地図アプリと位置情報取得アプリは独立させていたため、位置情報は Locationインスタンスではなく、 位置情報を CSV形式の文字列情報として Broadcast していた。この方が汎用的で問題は少ないが、Service では文字列化、 Activity では文字列のパースがいるため、パフォーマンス上は効率が悪いと言える。
位置情報は極座標である。地図に表示するには、座標変換が必要となる。 この座標変換時間のことを考えれば、文字列を数値に戻す時間はそれほど問題にすべきでないかも知れない。
当面、位置情報は文字列として Broadcast で送り、余裕がでたときに Locationインスタンスで送る方法を試したい。
地図アプリMapには移動ルートの表示のために、その日、1日分の位置情報履歴をメモリ上に持つ。 ファイル上は精々200~300KBであるため、メモリ使用量は問題ではない。
スクロールや zoom の変更ごとに、1日分の位置情報について座標変換を行うため、現状では、 この時間が一番大きい。
しかし、今のところ、これが地図アプリのパフォーマンスに悪影響を与えている様子はない。 Broadcastする座標は極座標から世界XY平面座標に変換して置けは、表示時の変換処理は高速になる。 必要が生じたときはそれを考える。
遠出とか旅行時のGPS軌跡の表示だけを対象とした場合には、データ量は少ないので、全データをメモリに読込むことも可能である。 しかし、散歩などを含めると膨大となるため、スマホの場合、全データをメモリに読込むのは難しい。 専用アプリを設けるまでの事はしたくない。
インデックスデータだけをメモリに読込む方式が無難であろう。Windowsタブレットの履歴とスマホの履歴は分離しておくが、 インデックスファイルは一つでいいだろう。スマホの履歴は増えていくので、インデックスファイルにも追記していく必要がある。
インデックスファイル(CSV形式)では、境界ボックス、ファイルパス、日付等を管理する。
インデックスファイルは地図アプリで作成する。最初は、Androidエミュレータで作成して、 その結果をスマホにコピーする。後の日々のインデックスファイルの追記はスマホで実行する。
アプリ起動時にインデックスファイルを読み込み、メモリ上で最後のレコードの境界ボックスは位置情報取得時に更新する。 (可能ならば)日付が変わったとき、または、定期的に、ファイルに書き込む。
ファイル形式は何度か変更している。この際、元のファイルはそのまま残し、表示用データを作り直すのがいいかもしれない。 レコードは適宜間引きを行うことにより、ファイルサイズは小さくできる。 ファイル名に日付および境界ボックスの値を含めればインデックスファイルは要らない。
最近のデータは 3.55MB/91=39KB/日である。一方、Windows時代では 186MB/1153=161KB/日である。 過去のデータは冗長性が高いため、大幅に間引くことが可能である。 テキストファイル(CSV形式)でも全体で 50MB以下にできる可能性があり、メモリに読み込み場合には、 30MB以下にできるであろう。したがって、アプリ起動時にバックグラウンドで表示用の全履歴データをメモリに読込むことも 可能である。ただし、ファイル数が大きいため、読み込みに要する電池使用量が気になる。
6時間弱の内、4時間ほど外出したが、全体の消費量は 22%となった。内訳は地図アプリMap 7%、画面 5%、 スギサポwalk(万歩計アプリ)3%、Google Play開発者サービス 2%、モバイルネットワークスタンバイ 1%、アイドル 1%、 sunlight-booster 1%、Wi-Fi 1%、com.qti.phone 1%、温度制御1%、com.sonymobile.pocketmode2 1%、 com.sonymobile.intelligent.iengine 1%、AesEntitlementClientService 1%、acu 1%となった。
画面は、地図アプリや万歩計アプリを見た時間が多い。Map 7%の内訳は位置情報取得が大半と思われるが、 万歩計アプリと同様に StepCounter の読み込み時間も多少かかっているであろう。 全体の約1/3が位置情報取得時間と推測される。巨大ではないが、自宅にいて移動のない時間も同じように電池を消耗するのは 問題である。やはり、この間は位置情報精度を落とすか、位置情報取得をやめるべきであろう。
これまでは、位置情報精度を落としていた。特に自宅で就寝中は位置情報取得は不要なため、 位置情報取得を完全にストップさせることを考える。
24時間稼働のServiceでは、位置情報取得と合わせて、StepCounterの値を取得する。自宅にいるとき、例えば1分ごとにチェックして、2~3分間変化がなければ、位置情報取得をストップする。
位置情報取得をストップしているとき、StepCounterの一定以上の変動を検出すると、位置情報取得を開始する。 自宅内での移動であれば、いずれ、また、位置情報取得は止まる。自宅外に出た場合は、再び帰宅するまで、位置情報取得を続ける。
先月までは自宅でWiMAX(Wi-Fi)が動いていたため、GPSでなくても自宅での位置情報は比較的精度が高かった。 恐らく、住所から位置情報が検出されるのであろう。
WiMAXの契約を解除して、モバイルWi-Fiに切り替えたため、位置情報は主に基地局から検出されるようになり、 精度が悪くなった。
試しに、常時、GPSで位置情報を取得してみる。ただし、自宅では、20秒間隔とする。
スマホは画面表示およびAndroid Studioの実機デバッグでは電池消費が大きい。 GPSの消費も大きいと言われるが、 10~20秒間隔であれば、バッテリ消費がそれほど大きくないかもしれない。その場合は、24時間GPS取得を行ってもよい。
バッテリー消費が大きいようであれば、別の対策を考える。例えば、位置情報だけでなく、万歩計(StepCounter)のデータも活用して、自宅にいるかどうかを判断する。
StepCounterは車などによる移動は検出できないが、一定時間内にある歩数以上歩いた場合に、位置情報取得をオンにする。 位置情報が何度か連続して、自宅と判断されたときは、位置情報取得をオフにする。そのほか、手動(メニュー)で 位置情報取得をオン・オフできるようにしておく。
1, 2か月後に格安SIMによるホームルータを導入した。自宅では、Wi-Fi接続としたので、GPSを使わず、 精度の高い位置情報が得られるようになったので、位置情報取得に関する電池使用量が僅少になった。