総まとめ(アンドロイド地図アプリの開発 最終回)

長い間かかった地図アプリの開発ですが、基本的なところは完成しました。
alasixosaka.hatenablog.com

たぶん、細かい不具合などがあると思いますが、それについては使いながら修正していくという感じになるでしょう。
振り返れば、地図アプリを作ろうと思い立ったのが約1年前。
alasixosaka.hatenablog.com
いやあ、いろいろありました。アンドロイドアプリの開発はまったくやったことなくて、初めに本を買うところから始めて、なんとかゴールにたどり着いたという感じです。
ということで、アプリについてまとめてみたいと思います。ソースコードについては、途中の総括のところで載せていますので、今回はソースコードはなしということで書いていきます。

アプリの概略

はっきり言って、世間の一般的な地図アプリと比べるとクソのような仕様です。自分の必要な機能しか搭載していません。できることは、非常に限定的です。ベースはMapsforgeという地図アプリになります。地図のデータはmap形式というのを使います。使っているのはOpenStreetMapですが、地図形式はOSMでなくmapを使っています。これにも深い意味はないのですが、以前から使っているIpBikeというアプリでもMapsforgeの地図を使っていたのと、日本語でブログを書いている方がおられて、その方の記事を参考に開発を始めたのでそうなってしまったというのが実態です。
OpenStreetMapオープンソースの地図で、誰でも自由に使えるのが特徴です。もちろん日本の地図データも無料でダウンロードできます。
Mapsforgeは地図データとして独特のmap形式を使いますが、基本的にはOpenStreetMapを表示するためのアプリ(というかライブラリといったほうがよい)です。ただし、本家のサイトはとっても不親切で、GitHubにソースがアップされていますが、そこのReadMeを読んだだけでは全く使い方がわかりません(私のようなアプリ開発の初心者には)。
github.com

開発初期には日本語でブログを書いている方の記事を参考にまずは地図を表示させるところから始めました。
blog.mori-soft.com
ここのサイトのお陰でなんとか自分でもOpenStreetMapの地図が表示できるようになりました。ただ、本家のサイトに比べて非常にシンプルなソースコードでやっていることはわかりやすかったのですが、それ以上に複雑なことをしようとするとどうしても本家サイトのコードを読む必要があって、そこから進むのに苦労しました。何とかやっていくうちに仕組みが少しずつ分かってきたので欲しい機能を追加していくことができました。
しかし、プログラマーの皆さんって凄いですね。あれだけの情報で自分用のプログラムが書けるのですから。

次はアプリの機能の紹介です。

メイン画面

f:id:alasixOsaka:20200405183648j:plain
アプリを立ち上げたときに最小に表示される画面
まずアプリを立ち上げるとメイン画面が表示されます。まあ、メイン画面というかメニュー画面ですが。普通なら地図がぱっと表示されるところですが、このアプリではメニューが現れます。こういう仕様にしたのは、地図の画面ではできるだけボタン類の表示を減らして最低限にし、地図の部分を多く表示したかったからです。地図画面からはGoogleのコマンドバーの戻るでメイン画面に戻ってきます。

MAP FILE SELECT

一番上のボタンは地図ファイルの選択です。デフォルトはベルリンの地図になっています。あまり意味はなのですが、Mapsforgeのサンプルプログラムがベルリンの地図を表示するようになっているのでそのまま使っているのと、日本の地図は日本で一つのファイルになっていてサイズが1GBを越える巨大なサイズになっているので、あまり大きなファイルをデフォルトにするのもどうかと思ってそのままにしてあります。
ベルリンの地図はなくても大きな問題になりませんが、そのままだと地図が表示されないのとエラーになる(たぶん)ので、何らかの地図ファイルが必要です。ファイルのダウンロードは次のところからできます。
download.mapsforge.org
また、等高線付きの地図は次のサイトからダウンロードができる。(等高線の表示のしかたは下の方を見て下さい)
https://www.openandromaps.org/en
地図ファイルは端末のどこにおいても構わないですが、後で出てくる他のファイルと同じところに置いておく必要があります。私は、SDカードのルートディレクトリに置いています。
MAP FILE SELECTをタップしたら、ファイルマネジャーを選ぶ画面が出るので、OIファイルマネージャーを使って該当の地図ファイルを選択します。OIファイルマネージャーはあらかじめインストールしておく必要があります。別のファイルマネージャーも使えると思いますが、試していません。

GPX FILE SELECT

このボタンをタップするとGPXファイルを選択する画面になります。拡張子がGPXのファイルだけを選択できるようにしてあります。下位フォルダにはフォルダ名をタップすればたどっていけますが、上位フォルダには行けない(と思い)ます。デフォルトは地図ファイルの置いてあるディレクトリになるので同じディレクトリに置いておくのが無難です。GPXファイルはGaeminConnectやカシミール3D、ridewithGPSなどで作成したルートを利用できます。あらがじめ自分が行きたいルートを決めておいて、アプリに取り込んで表示させるためのものです。アプリ上では青色の線で表示されます。後で書きますが、高低図を表示させるためには高度の情報が必要ですので、例えばカシミール3Dで無料の地図である地理院地図を使ったりすると標高データが含まれていませんので、高低図が表示できないことになります。
GPXファイルのデフォルトはnull.gpxというファイル名になっています。null.GPXは中身が何もない空のファイルです、ただすっからかんだとファイルを開くときにエラーになるので何でもよいので最低一文字は入れておく必要があります。メモ帳なので適当にファイルを作って後で拡張子をGPXとすれば出来上がりです。GPXファイルは一度選択するとそのファイルのデータをいつまでも表示し続ける仕様になっているので、ルートを消去したい時には選択画面でnull.GPXを選択するととで消去することができます。

f:id:alasixOsaka:20190907113200p:plain
GPXファイルのルートを青く表示する。

POI FILE SELECT

これもGPX FILE SELECTと同じです。タップすると選択画面が現れて、拡張子がPOIのファイルを選択するようになります。POIファイルはPoint Of Interestの略で、地図上にアイコンを表示するのに使っています。自分の場合は、交差点を左右に曲がるポイントに矢印マークを表示するのに使っています(自分で好きなアイコンを追加することができますが今は矢印のみです)。自転車で走っていると曲がるポイントを行き過ぎてしまうということがよくあるので、この機能は絶対に必要と思っています。GarminのEdge800などのサイコンには矢印とか様々なアイコンを表示する機能があるのですが、残念ながら画面が小さくて老眼になってからは見づらくて使っていません。その後スマホをサイコン代わりに使えるIpBikeというアプリをメインに使っていましたが、IpBikeにはアイコンを表示する機能がないので残念に思っていました。POIファイルはカシミール3Dでアイコンを表示したいところにウェイポイント作成していってGPXファイルとして出力し、拡張子をPOIに変更することで使っています。

f:id:alasixOsaka:20200302163139j:plain
POIファイルで矢印を表示
POIも表示を消すためにはnull.POIというファイルを用意しておいて、これを選択することで消去するようにしています。

MAP VIEW

MAP VIEWをタップすると地図が表示されます。このボタンはその下のラジオボタンと連動していて、地図表示の形式をラジオボタンの選択で切り替えるようになっています。
ラジオボタンの内、上の行は、地図の回転と現在地の表示のOn/Offを切り替えます。Onにすると地磁気センサーと加速度センサーを使って端末の向きを割り出して、端末の向きに応じて地図を回転させます。と同時にGPSから得られた現在地点を地図の中心にしてそのポイントに水色の丸を表示します。

f:id:alasixOsaka:20190929094938p:plain
現在地点の表示
Offにすると地磁気センサーと加速度センサーはオフになり、地図の表示も北が上の表示になります。また、現在地点を表す水色の丸も表示されなくなります。
ラジオボタンの下の行は高低図表示のOn/Offを切り替えます。Onにすると高低図を表示し、Offにすると表示しません。高低図は坂を上っているときにあとどのくらい登りが続くのかわかるので絶対欲しい機能の一つでした。また、上の行の回転のOn/Offによって表示が変わり、Onの場合、高低図にも現在地点が水色の丸で表示されます。また、高低図の横軸のフルスケールは10㎞となり、現在地点に応じて横方向にスクロールします。
f:id:alasixOsaka:20200429121059j:plain
高低図にも現在地を表示
Offにすると現在地点の表示はなくなり、高低図の横軸スケールはルートの全体となり、全体像を見ることができます。
f:id:alasixOsaka:20200412173322j:plain
高低図の全体像を表示
ちなみに、高低図の縦軸はそのルートの最高点にオートスケールされます。ただし、最高点が500m以下の場合は拡大されすぎて見にくいので縦軸のフルスケールは500mになります。同様の理由で、横軸もコース全体の長さが10㎞以下ならフルスケールは10㎞になります。

SELECT THEME

これは地図の表示形式を定義したテーマファイルを読み込むためのボタンで、何も選択しないとデフォルトのテーマが選択されます。デフォルトテーマでは、たとえ等高線のデータ含まれている地図ファイルを選択しても等高線が表示されません。等高線を表示させるためにはそれに応じたテーマファイルを読み込む必要があります。
先に紹介したOpenAndroMapのサイトにテーマをダウンロードするリンクがあります。図の赤丸の部分をクリックするとElevate.ZIPというファイルがダウンロードされるのでそれを適当なフォルダに解凍し、その中にあるElevate.XMLというファイルを端末の地図ファイルと同じディレクトリにコピーします。

f:id:alasixOsaka:20200502145812j:plain
赤丸の部分をクリックするとテーマファイルがダウンロードされる
アプリの選択画面でLocusをタップするとこのElevate.XMLをテーマとして使用する設定になり等高線が表示されます。実はこのファイルはLocusMapというアプリで等高線を表示させるためのものですが、LocusMapはmap形式に対応しているので、Mapsforgeでも使用することができました。

バックグランドでの動作

アプリでMapViewをタップすると地図が表示されますが、どのオプションを選んでいてもバックグランドでの動作が可能なモードに入ります。バックグランドでアプリが動作中は左上のバーにコンパスのアイコンが表示されます。MapViewからホームボタンでホーム画面に戻ってもアプリ自体は動作を続けており、アイコンも表示されたままになります。スリープモードに入ってもアプリは動作し続けるので消費電力は大きくなります。これは、GPSでの位置を見失わないための処理で、バックグランド動作をしないと、スリープから復帰したときに端末が現在地を見失っており、GPSを掴むのにものすごく時間がかかるため、仕方なくバックグランドで動作するようにしました。バックグランド動作を止めるためには、地図画面でコマンドバーの戻るボタンをタップしてメイン画面に戻れば止まります。と同時にアイコンも消去されます。このアイコンはAndroid8では強制的に消去することはできませんが、Andorid7以前では上のバーをスワイプして通知画面を拡大して、通知を消去すれば消えてしまいます。ただ、通知が消えているだけでバックグランド動作は継続していますので注意が必要です。
冒頭の部分で書き忘れましたが、このアプリはGPSが動作していることが前提として作成されています。アプリ自身ではGPSのOn/OffをコントロールしていないのであらかじめGPSをオンにしておく必要があります。また、GPSはバックグランド動作にかかわらずオンの状態になるので(端末の設定画面から強制的にオフにすれば別ですが)、それなりに電力を消費します。

軌跡の表示

赤色でいままで通ったところの軌跡を表示します。これは、当初の構想にはなかった機能ですが、現在地点の表示が単なる丸印で方向がわからないので、これから行く方向と今まで通ってきた方向がすぐわかるように、軌跡を表示するようにしました。軌跡もバックグランドでも動作していますので、スリープに入っても軌跡は途切れることなく表示されます。また、軌跡はメイン画面に戻れば消去されます。そこから再びMapViewをタップして地図画面に戻った場合、そこから軌跡を描き始めます。

f:id:alasixOsaka:20200430142311j:plain
赤色で軌跡を表示。バックグランドでも描き続ける。

これからのこと

アプリはできましたが、バグが残っていることは十分に予想されます。バグとりは実際に使ってみないとわからない部分も多いので使っている中で改良していくという作業になりますが、コロナの影響で色々なところに行けないので気長にやるしかなさそうです。
ログ機能は搭載していません。GarminGPSウォッチをいつも使っているのでGPSのログはそっちで取るので必要性を感じていないからです。軌跡を描いているのでそのタイミングでファイルに書き込みを行っていけばログファイルを作ることができますが、そうするとどこでログをストップするかを考えて実装する必要が出てきます。現状では軌跡を消去するのにメイン画面に戻る方法を使っているのですが、そうでなくてログを止める別のボタンをメイン画面に追加するとかの方法も考えられます。ただ、そうするとバックグラウンド動作もそこでストップするといった処理が必要になり、結構ややこしいことになってしまいます。なのであまりやる気がありません。
また、等高線付きの地図ですが、ダウンロードできるmap形式の地図は等高線間隔が20mのものしかなく、10m間隔のものが使いたければ自分で作るしかなさそうです。自転車の場合はいいですが、登山やトレランなどにこのアプリを使おうと思ったら細かい地形を読むためには等高線間隔は10mくらいの方が読みやすいのでやる価値はあると思いますが手間との相談ですね。
Gamin用の地図をOpenStreetMapをベースに作っている人がいるのでそのやり方を参考にすればできそうですが、結構手間がかかるので気が向いたらやってみようかと思っています。ちなみにオリエンテーリングでは等高線間隔は標準で5m間隔です。これくらいでないと細かい地形が読みきれません。まあ、地図の縮尺も1:10000とかがメインなのでそうしないと等高線がスカスカになってしまいますけど。
その辺はやってみてうまくいったらまたブログに書いてみたいと思います。