12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

StudyCoAdvent Calendar 2019

Day 15

Maps SDK for Androidチュートリアル

Last updated at Posted at 2019-12-15

Androidで地図を表示する場合、第一の選択肢となる Maps SDK for Android の使い方についてまとめてみました。

Maps SDK for Androidとは

Google製のマップを表示するAndroid用のSDKです。地図の表示だけならモバイルは無制限に利用できます。iOSやブラウザ用もあります。

準備

API Keyを取得する必要があるので、Maps SDK for Android - Get an API key を参照してAPIキーを作成してください。

  1. GCPコンソールにいく
  2. gcpプロジェクト作成
  3. 認証情報に行き、API key生成
  4. API keyの制限

API keyの制限で、特定のパッケージ名のアプリに限定するためには、証明書に合わせたSHA-1のフィンガープリントを作成する必要があります。

AndroidStudioの新規プロジェクト作成で、「Google Maps Activity」を選択し作成しましょう。選択しなくてできますが、その場合SDKの指定や、Manifestなどの書き換えが必要になります。

google_maps_api.xml というファイルが作成されているので、APIキーを指定します。

google_maps_api.xml
<resources>
  <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">YOUR_KEY_HERE</string>
</resources>

アプリをビルドするとマップが表示されます。「Google Maps Activity」の自動生成だと、シドニーが指定されています。

image.png

地図を表示する

地図を表示する方法を具体的に見ていきましょう。(「Google Maps Activity」の自動生成だとコードはすでに作成されています。)
Mapを表示する際に、 MapFragment を使う方法と、 MapView を使い方法があります。
ここでは前者の方法を見ます。

地図を表示したいactivityのレイアウトに、 以下のFragmentを記載します。
android:name="com.google.android.gms.maps.MapFragment" を指定するとActivityに自動的にAreaMapFragment が適用されます。(ActivityのコードからMapFragmentを追加することもできます)

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.google.android.gms.maps.MapFragment"
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

次に、表示するActivityで OnMapReadyCallback インターフェースを実装します。

MainActivity.kt
class MapsActivity : AppCompatActivity(), OnMapReadyCallback {

    private lateinit var mMap: GoogleMap

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_maps)

        val mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }

    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap
    }
}

supportFragmentManager.findFragmentById(R.id.map) で、xmlに記載したMapFragmentのidを指定します。
getMapAsync() でコールバックがセットされます。

mapの準備ができたら、 onMapReady が呼ばれます。以降、マーカーを設置したり、マップを動かしたりすることができるようになります。

スタイルを変更する

マップの全体のデザインを変更したいときは、簡単に指定することができます。Maps Platform Styling Wizardという、スタイルを作成するツールが用意されているので、容易に自分好みのスタイルを作ることができます。
(しかもiOS、ブラウザでも共通のスタイルを利用することができます)

ツールで地図をカスタマイズすると、jsonが生成されるので、リソースに raw フォルダを作成し追加します。

onMapReady でstyleを先ほどのjsonファイルを指定すると、マップに反映されます。

MainActivity.kt
override fun onMapReady(googleMap: GoogleMap) {

        // style
        val mapOptions = MapStyleOptions.loadRawResourceStyle(this, R.raw.style_map)
        googleMap.setMapStyle(mapOptions)
        
    }
image.png

マーカーを設置する

マーカーの設置は、緯度経度やタイトル、タップしたときの情報などを指定してセットすることができます。

MainActivity.kt
val skytree = LatLng(35.710063, 139.8107)

        val markerOption = MarkerOptions()
            .position(skytree)
            .anchor(0.5f, 0.5f)  // マーカーの位置をずらせます
            .title("skytree marker")  // iconをタップすると表示されます
            .snippet("The tallest tower in Japan.") // iconをタップすると表示されます
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.skytree))
        mMap.addMarker(markerOption)

        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(skytree, 15f))
image.png

円を表示する

円を描画することもできます。

MainActivity.kt
mMap.addCircle(
        CircleOptions()
            .center(skytree)  // 中心の緯度経度
            .radius(500.0)  // 円の半径
            .strokeColor(0x500000FF)  // 境界線の色
            .strokeWidth(5f)  // 境界線の太さ
            .fillColor(0x0F0000FF)  // 円内部の色
    )
image.png

カメラを動かす

パッと切り替える方法と、アニメーションしながら切り替える方法があります。

MainActivity.kt
move_button.setOnClickListener {
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(tokyoTower, 15f))
}

move_to_tokyo_tower.gif

MainActivity.kt
animate_button.setOnClickListener {
    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(tokyoTower, 15f))
}

animate_to_tokyo_tower.gif

マーカーが収まるように表示する

複数のマーカーが地図に収まるように表示したい時があるかと思います。

MainActivity.kt
override fun onMapReady(googleMap: GoogleMap) {
  mMap = googleMap
  mMap.setOnMapLoadedCallback {
    fitMarkersOnScreen()
  }
}

private fun fitMarkersOnScreen() {
    val skytree = LatLng(35.710063, 139.8107)
    val kaminariMon = LatLng(35.710233, 139.797648)
    val asakusaViewHotel = LatLng(35.715151, 139.79829)
    val bounds = LatLngBounds.Builder().also { builder ->
        listOf(skytree, kaminariMon, asakusaViewHotel).forEach {
            mMap.addMarker(MarkerOptions().position(it))
            builder.include(it)
        }
    }.build()
    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 300))
}

newLatLngBounds は、地図がレンダリングされたあとで呼び出さないといけません。 setOnMapLoadedCallback で呼び出すようにしましょう。

image.png

その他

  • mapFragment.getMapAsync(this)onCreate で呼ぶようにしましう。onResumeなどでよぶと、地図が再生成されてしまうので、表示に時間がかかります。

まとめ

Maps SDKを使えば、簡単に地図を表示することがわかったかなとおもいます。良い地図ライフを。

12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?