
今年 5 月の Google I/O では、Android 開発用の言語として Kotlin が正式サポートされることが発表されましたね。みなさんはもう Kotlin で開発にトライしてみましたか?
私は、ArcGIS Runtime SDK for Android という Android 端末で地図などの GIS 機能を扱うための開発者製品を担当しているので、これを機に Kotlin の世界に足を踏み入れてみました!いままで Android で使っていたライブラリなどもそのまま Kotlin で使用できるとのことで、今回は ArcGIS Runtime SDK for Android でも、Kotlin による開発を実現できるのかやってみました!
※ Kotlin は、Android Studio で開発可能ですが、ArcGIS Runtime SDK for Android の開発言語としては非サポートです。
作った地図アプリ
今回作成したのは背景地図を表示して、任意にタップした場所の緯度経度を表示するという簡単な地図アプリです。
全体のコードは ESRIジャパンGitHub にて公開しています。

Kotlin コード
ここからはコードを解説してきたいと思います。上記の画像と同じようなアプリを Android (java) で作成する場合は、callout というプロジェクトのコードを参考にしてください。
アプリは次の 3 つの要素で構成します。
- 地図を表示する
- タップイベントを実装する
- タップした地図上の緯度経度を表示する
それでは、この要素をそれぞれどのようにコーディングするのか見ていきましょう!
地図を表示する
背景地図を表示するコードは、Android (java) とさほど変わりません。Kotlin は言語特有の体裁的な部分を省き本質的な部分のみ実装できるということを、他のブログ記事などでよく目にしますが、これだけのコードでは書き方や実行行数の変化は感じられませんでした。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// MapView の作成
mMapView = findViewById(R.id.mapView) as MapView
// 背景地図の表示
val map = ArcGISMap(Basemap.Type.TOPOGRAPHIC, 35.3312442,139.6202471, 😎
mMapView!!.map = map
・・・
タップイベントを実装する
Kotlin を実装するにあたって、いいな!と思ったところは、リスナーやコールバックの処理が本質の部分だけで短くシンプルに記述できるというところでした。
これを実現しているのは SAM(Single Abstract Method)変換というもので、私の理解では引数の abstract のクラスがもつメソッドがひとつだけだった場合、呼び出されるメソッドは決まっているので、呼び出すコードを省くことができるというものです。しかし、実際にArcGIS Runtime SDK for Android でタップイベントを実装すると次のようになりました。
// タップイベントを実装する
mMapView!!.setOnTouchListener(object : DefaultMapViewOnTouchListener(this, mMapView) {
override fun onSingleTapConfirmed(motionEvent: MotionEvent?): Boolean {
// TODO タップしたときの処理:取得したポイントを吹き出しで表示する処理を書く
・・・
return true
}
} );
実は、次のような処理の書き方を想像していたので、Android (java) で実装するのと代わり映えしない印象です。
mMapView!!.setOnTouchListener { v, event -> 処理の内容 }
もちろん、setOnTouchListener の引数になっている abstract の View.OnTouchListener クラスは、onTouch() メソッドをひとつだけ持っているので、上記のコードでは onTouch() が呼ばれた時の処理として '処理の内容' の処理が実行されます。
これが Kotlin においての SAM 変換実装です。
SAM 変換については、Qiitaの記事の「Kotlinでリスナーやコールバックをスッキリと書く【関数リテラルとSAM変換】」がわかりやすかったです。
しかし地図アプリには、ただ単にタップしたときのイベントの他に、ダブルタップやドラッグして地図を操作したいときがあります。
このイベントを簡単に取得できるようになっているのが DefaultMapViewOnTouchListener です。このリスナーは地図を操作する基本の動作を保ったまま、様々なタップイベントを実装できます。
上記のコードでは、onSingleTapConfirmed というメソッドを実装しています。このメソッドは、シングル タップがあったときに呼び出されるメソッドですが、同時にダブル タップではないことを保証してくれるメソッドです。View.OnTouchListener.onTouch() メソッドを使用するよりも地図に対する操作を確実にとらえることができます。
タップした地図上の緯度経度を表示する
画面をタップしたイベントから X、Y の座標を取得して緯度経度に変換します。
ArcGIS Runtime SDK for Android では、いわゆる「吹き出し」のコントロールは callout というクラスで実現します。
吹き出しに表示するテキストを作成しているところでは、実は Android (java) のコードも混在していますが、これでも動作します。
// タップしたときの処理:取得したポイントを吹き出しで表示する処理
val screenPoint = android.graphics.Point(Math.round(motionEvent!!.getX()),Math.round((motionEvent!!.getY())))
val arcgisPoint = mMapView!!.screenToLocation(screenPoint)
// WGS84へ変換
val arcgis84p = GeometryEngine.project(arcgisPoint, SpatialReferences.getWgs84()) as Point
// 表示するテキストを作成する
val calloutTextview = TextView(applicationContext)
calloutTextview.setText("Lat:" + String.format("%.4f", arcgis84p.getY()) + "/Lon:" + String.format("%.4f", arcgis84p.getX()))
calloutTextview.setTextColor(Color.BLACK)
// 表示オブジェクトに設定
val callout = mMapView!!.callout
callout.location = arcgisPoint
callout.content = calloutTextview
callout.show()
Kotlin の魅力
Kotlin では、Android (java) のコードを Kotlin のプロジェクトへペーストすれば、Android Studio が自動的に変換してくれます。
または、クラス内に Kotlin のコードと Android(Java)のコードが混在していても動作します。この 2 つが今回実装していてすごく驚いたところです。
Kotlin の SAM 変換は一見ステキな処理に見えるのですが、使い方や考え方、継承しているクラスなどをちゃんと捉えないとハマる場所かなという所感です。
今回は触れませんでしたが、今後も Kotlin の文法にそった実装や Android では存在しなかったプロパティの機能を使ってスマート実装な地図アプリを開発してみたいと思います!今回はここまで。楽しい Kotlin ライフを~
関連リンク集
ArcGIS 関連ページ
・ArcGIS for Developers
・ArcGIS for Developers 開発リソース集
・ArcGIS Online
・ArcGIS Open Data