Kotlin 04.1 の高度な Android: Android Google マップ

1. 始める前に

Google マップを使用してアプリを作成すると、衛星画像、マップ用の堅牢な UI コントロール、位置追跡、位置マーカーなどの機能をアプリに追加できます。有名な釣り場や登山地の場所など、独自のデータセットの情報を表示することで、標準の Google マップに付加価値を与えることができます。また、トレジャー ハントや拡張現実ゲームなど、プレーヤーが現実世界を探索するゲームを作成することもできます。

このレッスンでは、カスタマイズした地図とユーザーの現在地を表示する「Wander」という Google マップ アプリを作成します。

前提条件

以下に関する知識:

  • 基本的な Android アプリを作成し、Android Studio を使用して実行する方法。
  • 文字列などのリソースを作成および管理する方法。
  • Android Studio を使用してコードをリファクタリングし、変数の名前を変更する方法。
  • ユーザーとして Google マップを使用する方法
  • 実行時の権限を設定する方法。

学習内容

  • Google API Console から API キーを取得してアプリに登録する方法
  • Google マップをアプリに統合する方法
  • さまざまなマップタイプを表示する方法
  • Google マップのスタイルを設定する方法
  • 地図にマーカーを追加する方法
  • ユーザーがスポット(POI)にマーカーを配置できるようにする方法
  • 位置情報追跡を有効にする方法
  • Google マップが埋め込まれた Wander アプリを作成する方法
  • マーカーやスタイル設定など、アプリのカスタム機能を作成する方法
  • アプリで位置情報追跡を有効にする方法

2. アプリの概要

この Codelab では、カスタム スタイルを適用した Google マップを表示する Wander アプリを作成します。Wander アプリでは、マーカーを場所にドロップしたり、オーバーレイを追加したりして、現在地をリアルタイムで確認することができます。

5b12eda7f467bc2f.png

3. タスク: プロジェクトを設定して API キーを取得する

Maps SDK for Android を使用するには、API キーが必要です。API キーを取得するには、プロジェクトを API に登録し、[サービス] ページをご覧ください。API キーは、アプリを作成者にリンクするデジタル証明書に関連付けられています。デジタル証明書の使用とアプリの署名について詳しくは、アプリへの署名をご覧ください。

この Codelab では、デバッグ用証明書に API キーを使用します。デバッグビルドに署名するで説明されているように、デバッグ用証明書は設計上安全ではありません。Maps SDK for Android を使用する公開済みの Android アプリには、2 つ目の API キー(リリース証明書のキー)が必要です。リリース証明書の取得について詳しくは、API キーを取得するをご覧ください。

Android Studio には、便利なテンプレート コードを生成する Google Maps Activity テンプレートが含まれています。テンプレート コードには、API キーを簡単に取得できるようにするリンクを含む google_maps_api.xml ファイルが含まれています。

ステップ 1: マップ テンプレートを使用して Wander プロジェクトを作成する

  1. 新しい Android Studio プロジェクトを作成します。
  2. [Google Maps Activity] テンプレートを選択します。

d6b874bb19ea68cd.png

  1. プロジェクトに Wander という名前を付けます。
  2. 最小 API レベルを API 19 に設定します。言語が Kotlin であることを確認します。
  3. [完了] をクリックします。
  4. アプリのビルドが完了したら、プロジェクトと、Android Studio によって作成される以下のマップ関連ファイルを確認します。

google_maps_api.xml - この構成ファイルを使用して API キーを保持します。このテンプレートは、デバッグ用とリリース用の 2 つの google_maps_api.xml ファイルを生成します。デバッグ用証明書の API キーのファイルは src/debug/res/values にあります。リリース証明書の API キーのファイルは src/release/res/values にあります。この Codelab では、デバッグ用証明書のみを使用します。

activity_maps.xml - このレイアウト ファイルには、画面全体に表示される単一のフラグメントが含まれています。SupportMapFragment クラスは Fragment クラスのサブクラスです。SupportMapFragment は、アプリに地図を配置する最も簡単な方法です。これは地図のビューのラッパーで、必要なライフサイクルのニーズを自動的に処理します。

任意の ViewGroup<fragment> タグを使用し、追加の name 属性を使用することで、レイアウト ファイルに SupportMapFragment を含めることができます。

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java - MapsActivity.java ファイルは onCreate() メソッドで SupportMapFragment をインスタンス化し、getMapAsync(): 地図システムとビューを自動的に初期化します。SupportMapFragment を含むアクティビティでは、OnMapReadyCallback インターフェースとそのインターフェースの onMapReady() メソッドを実装する必要があります。onMapReady() メソッドは、地図が読み込まれたときに呼び出されます。

ステップ 2: API キーを取得する

  1. google_maps_api.xml ファイルのデバッグ バージョンを開きます。
  2. ファイル内で、URL が長いコメントを探します。URL のパラメータには、アプリに関する具体的な情報が含まれます。
  3. URL をコピーしてブラウザに貼り付けます。
  4. 画面の指示に沿って、API と[サービス] ページをご覧ください。指定した URL のパラメータから、Maps SDK for Android がページで自動的に有効になります。
  5. [Create an API Key] をクリックします。
  6. 次のページで [API キー] セクションに移動し、作成したキーをクリックします。
  7. [キーを制限] をクリックし、[Maps SDK for Android] を選択して、キーの使用を Android アプリに制限します。
  8. 生成された API キーをコピーします。先頭は「AIza"
  9. google_maps_api.xml ファイルで、google_maps_key 文字列の YOUR_KEY_HERE にキーを貼り付けます。
  10. アプリを実行します。アクティビティに、オーストラリアのシドニーにマーカーが配置された埋め込み地図が表示されます。(シドニーのマーカーはテンプレートの一部であり、後で変更できます)。

34dc9dd877c90996.png

ステップ 3: mMap の名前を変更する

MapsActivity には、GoogleMap 型の mMap という非公開の lateinit var があります。Kotlin の命名規則に従うには、mMap の名前を map に変更します。

  1. MapsActivitymMap を右クリックし、[リファクタリング] をクリックします。名前を変更...

e713ccb3384450c6.png

  1. 変数名を map に変更します。

onMapReady() 関数内の mMap へのすべての参照も map に変更されています。

4. タスク: マップタイプを追加する

Google マップには、標準、地図 + 写真、航空写真、地形図、「なし」の地図タイプがあります。(地図がまったく使用されていない場合)。

法線マップ

航空写真地図

地図+写真

地形図

地図の種類によって、提供される情報が異なります。たとえば、車内でのナビゲーションに地図を使用する場合、通りの名前が表示されると便利です。標準のオプションを使用すると便利です。ハイキングをしているときは、地形マップが、頂上に到達するまでにあとどれくらい登ればよいかを判断するのに役立ちます。

このタスクの内容:

  1. ユーザーが地図タイプを変更できるオプション メニューを備えたアプリバーを追加します。
  2. 地図の開始位置を自分の自宅の位置に移動します。
  3. 地図上の単一の場所を示し、ラベルを含めることができるマーカーのサポートを追加します。

地図タイプの [追加] メニュー

このステップでは、ユーザーがマップタイプを変更できるオプション メニュー付きのアプリバーを追加します。

  1. 新しいメニュー XML ファイルを作成するには、res ディレクトリを右クリックして [New] を選択します。Android リソース ファイル:
  2. ダイアログで、ファイルに map_options という名前を付けます。
  3. リソースタイプに [Menu] を選択します。
  4. [OK] をクリックします。
  5. [コード] タブで、新しいファイルのコードを次のコードに置き換えて、マップのメニュー オプションを作成します。「なし」「none」であるため、マップタイプは省略されます。地図がまったくなくなります。このステップではエラーが発生しますが、これは次のステップで解決します。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/normal_map"
       android:title="@string/normal_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/hybrid_map"
       android:title="@string/hybrid_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/satellite_map"
       android:title="@string/satellite_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/terrain_map"
       android:title="@string/terrain_map"
       app:showAsAction="never" />
</menu>
  1. エラーを解決するために、strings.xmltitle 属性のリソースを追加します。
<resources>
   ...
   <string name="normal_map">Normal Map</string>
   <string name="hybrid_map">Hybrid Map</string>
   <string name="satellite_map">Satellite Map</string>
   <string name="terrain_map">Terrain Map</string>
   <string name="lat_long_snippet">Lat: %1$.5f, Long: %2$.5f</string>
   <string name="dropped_pin">Dropped Pin</string>
   <string name="poi">poi</string>
</resources>
  1. MapsActivity で、onCreateOptionsMenu() メソッドをオーバーライドし、map_options リソース ファイルからメニューをインフレートします。
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   val inflater = menuInflater
   inflater.inflate(R.menu.map_options, menu)
   return true
}
  1. MapsActivity.kt で、onOptionsItemSelected() メソッドをオーバーライドします。マップタイプの定数を使用して、ユーザーの選択を反映するようにマップタイプを変更します。
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
   // Change the map type based on the user's selection.
   R.id.normal_map -> {
       map.mapType = GoogleMap.MAP_TYPE_NORMAL
       true
   }
   R.id.hybrid_map -> {
       map.mapType = GoogleMap.MAP_TYPE_HYBRID
       true
   }
   R.id.satellite_map -> {
       map.mapType = GoogleMap.MAP_TYPE_SATELLITE
       true
   }
   R.id.terrain_map -> {
       map.mapType = GoogleMap.MAP_TYPE_TERRAIN
       true
   }
   else -> super.onOptionsItemSelected(item)
}
  1. アプリを実行します。
  2. 地図タイプを変更するには 428da163b831115b.png をクリックします。モードによって地図の外観がどのように変わるかに注目してください。

6fa42970d87f5dc7.png

5. 操作: マーカーを追加する

デフォルトでは、onMapReady() コールバックには、Google マップが作成されたオーストラリアのシドニーにマーカーを配置するコードが含まれています。また、デフォルトのコールバックにより、シドニーまでパンするよう地図がアニメーション化されます。

このタスクでは、地図のカメラを自宅に移動し、指定したレベルにズームして、そこにマーカーを配置します。

ステップ 1: 自宅にズームしてマーカーを追加する

  1. MapsActivity.kt ファイルで、onMapReady() メソッドを見つけます。シドニーにマーカーを配置してカメラを移動するコードを削除します。メソッドは次のようになります。
override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

}
  1. 自宅の緯度と経度は、こちらの手順で確認できます。
  2. 緯度の値と経度の値を作成し、浮動小数点値を入力します。
val latitude = 37.422160
val longitude = -122.084270
  1. homeLatLng という新しい LatLng オブジェクトを作成します。homeLatLng オブジェクトで、作成した値を渡します。
val homeLatLng = LatLng(latitude, longitude)
  1. 地図上でのズームイン率を指定する val を作成します。ズームレベル 15f を使用します。
val zoomLevel = 15f

ズームレベルによって、地図上でのズームインの度合いがコントロールされます。以下のリストは、各ズームレベルで表示される詳細レベルを示しています。

  • 1: 世界
  • 5: 大陸/大陸
  • 10: 都市
  • 15: 通り
  • 20: 建物
  1. map オブジェクトで moveCamera() 関数を呼び出してカメラを homeLatLng に移動し、CameraUpdateFactory.newLatLngZoom() を使用して CameraUpdate オブジェクトを渡します。homeLatLng オブジェクトと zoomLevel を渡します。
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
  1. マップの homeLatLng にマーカーを追加します。
map.addMarker(MarkerOptions().position(homeLatLng))

完成したメソッドは次のようになります。

override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

   //These coordinates represent the latitude and longitude of the Googleplex.
   val latitude = 37.422160
   val longitude = -122.084270
   val zoomLevel = 15f

   val homeLatLng = LatLng(latitude, longitude)
   map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
   map.addMarker(MarkerOptions().position(homeLatLng))
}
  1. アプリを実行します。自宅まで地図が表示され、希望のレベルにズームインして、自宅にマーカーが配置されます。

fc939024778ee76.png

ステップ 2: ユーザーが長押しクリックでマーカーを追加できるようにする

このステップでは、ユーザーが地図上の場所を長押ししたときにマーカーを追加します。

  1. GoogleMap を引数として受け取る setMapLongClick() というメソッドスタブを MapsActivity に作成します。
  2. 地図オブジェクトに setOnMapLongClickListener リスナーをアタッチします。
private fun setMapLongClick(map:GoogleMap) {
   map.setOnMapLongClickListener { }
}
  1. setOnMapLongClickListener() で、addMarker() メソッドを呼び出します。渡された LatLng に位置を設定して、新しい MarkerOptions オブジェクトを渡します。
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. onMapReady() メソッドの最後で、map を指定して setMapLongClick() を呼び出します。
override fun onMapReady(googleMap: GoogleMap) {
   ...
  
   setMapLongClick(map)
}
  1. アプリを実行します。
  2. 地図を長押しして、場所にマーカーを配置します。
  3. マーカーをタップします。画面の中央にマーカーが表示されます。

4ff8d1c1db3bca9e.png

ステップ 3: マーカーの情報ウィンドウを追加する

このステップでは、マーカーがタップされたときにマーカーの座標を表示する InfoWindow を追加します。

  1. setMapLongClick()setOnMapLongClickListener() で、snippetval を作成します。スニペットとは、タイトルの後に表示される追加のテキストです。スニペットには、マーカーの緯度と経度が表示されます。
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       // A snippet is additional text that's displayed after the title.
       val snippet = String.format(
           Locale.getDefault(),
           "Lat: %1$.5f, Long: %2$.5f",
           latLng.latitude,
           latLng.longitude
       )
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. addMarker() で、R.string.dropped_pin 文字列リソースを使用して、マーカーの title を「ドロップしたピン」に設定します。
  2. マーカーの snippetsnippet に設定します。

完成した関数は次のようになります。

private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       // A Snippet is Additional text that's displayed below the title.
       val snippet = String.format(
           Locale.getDefault(),
           "Lat: %1$.5f, Long: %2$.5f",
           latLng.latitude,
           latLng.longitude
       )
       map.addMarker(
           MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet)
              
       )
   }
}
  1. アプリを実行します。
  2. 地図を長押しして、位置マーカーをドロップします。
  3. マーカーをタップすると情報ウィンドウが表示されます。

63f210e6e47dfa29.png

ステップ 4: スポット リスナーを追加する

スポット(地図上の場所)は対応するアイコンとともに地図上にデフォルトで表示されます。公園、学校、政府機関などもスポットに該当します。地図タイプが normal に設定されている場合は、ビジネス スポットも地図に表示されます。ビジネス スポットは、店舗、レストラン、ホテルなどを表します。

このステップでは、地図に GoogleMap.OnPoiClickListener を追加します。このクリック リスナーは、ユーザーがスポットをクリックするとすぐに地図上にマーカーを配置します。クリック リスナーには、スポット名を含む情報ウィンドウも表示されます。

  1. GoogleMap を引数として受け取る setPoiClick() というメソッドスタブを MapsActivity に作成します。
  2. setPoiClick() メソッドで、渡された GoogleMapOnPoiClickListener を設定します。
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->

   }
}
  1. setOnPoiClickListener() で、マーカーの val poiMarker を作成します。
  2. map.addMarker() を使用し、MarkerOptionstitle をスポットの名前に設定して、マーカーを設定します。
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
   }
}
  1. setOnPoiClickListener() 関数の poiMarker に対して showInfoWindow() を呼び出して、すぐに情報ウィンドウを表示します。
poiMarker.showInfoWindow()

setPoiClick() 関数の最終的なコードは次のようになります。

private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
       poiMarker.showInfoWindow()
   }
}
  1. onMapReady() の最後で setPoiClick() を呼び出し、map を渡します。
override fun onMapReady(googleMap: GoogleMap) {
   ...

   setPoiClick(map)
}
  1. アプリを実行し、公園やコーヒー ショップなどのスポットを見つけます。
  2. スポットをタップしてマーカーを配置し、情報ウィンドウにスポットの名前を表示します。

f4b0972c75d5fa5f.png

6. タスク: 地図のスタイルを設定する

Google マップはさまざまな方法でカスタマイズでき、独自のデザインにすることができます。

利用可能な XML 属性を使用して、他のフラグメントと同様に MapFragment オブジェクトをカスタマイズできます。ただしこのステップでは、GoogleMap オブジェクトのメソッドを使用して、MapFragmentコンテンツのデザインをカスタマイズします。

地図のスタイルをカスタマイズするには、地図上の対象物の表示方法を指定する JSON ファイルを生成します。この JSON ファイルを手動で作成する必要はありません。Google が提供する Maps Platform Styling Wizard を使用すると、地図を視覚的にスタイル設定した後、自動的に JSON を生成できます。このタスクでは、レトロなテーマを使用して地図のスタイルを設定します。つまり、地図にヴィンテージ カラーを使用し、色付きの道路を追加します。

ステップ 1: 地図のスタイルを作成する

  1. ブラウザで https://mapstyle.withgoogle.com/ にアクセスします。
  2. [スタイルの作成] を選択します。
  3. [レトロ] を選択します。

208b3d3aeab0d9b6.png

  1. [その他のオプション] をクリックします。

4a35faaf9535ee82.png

  1. [道路] を選択 >塗りつぶし
  2. 道路の色を任意の色(ピンクなど)に変更します。

92c3293749293a4c.png

  1. [完了] をクリックします。

f1bfe8585eb69480.png

  1. 表示されるダイアログから JSON コードをコピーし、必要に応じて次のステップで使用するために書式なしテキストのメモに入れておきます。

3c32168b299d6420.png

ステップ 2: 地図にスタイルを追加する

  1. Android Studio の res ディレクトリにリソース ディレクトリを作成し、raw という名前を付けます。JSON コードなどの raw ディレクトリ リソースを使用する。
  2. res/rawmap_style.json というファイルを作成します。
  3. 保存した JSON コードを新しいリソース ファイルに貼り付けます。
  4. MapsActivity で、onCreate() メソッドの上に TAG クラス変数を作成します。これはロギングの目的に使用されます。
private val TAG = MapsActivity::class.java.simpleName
  1. また、MapsActivity で、GoogleMap を受け取る setMapStyle() 関数を作成します。
  2. setMapStyle()try{} ブロックを追加します。
  3. try{} ブロックで、スタイル設定を成功させるための val success を作成します。(次の catch ブロックを追加します)。
  4. try{} ブロックで、JSON スタイルを地図に設定し、GoogleMap オブジェクトで setMapStyle() を呼び出します。JSON ファイルを読み込む MapStyleOptions オブジェクトを渡します。
  5. 結果を success に代入します。setMapStyle() メソッドは、スタイル ファイルの解析とスタイルの設定の成功ステータスを示すブール値を返します。
private fun setMapStyle(map: GoogleMap) {
   try {
       // Customize the styling of the base map using a JSON object defined
       // in a raw resource file.
       val success = map.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
               this,
               R.raw.map_style
           )
       )
   }
}
  1. success が false である if ステートメントを追加します。スタイル設定に失敗した場合は、解析が失敗したログを出力します。
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   }
}
  1. スタイル ファイルがない場合に対処するために、catch{} ブロックを追加します。catch ブロックで、ファイルを読み込めない場合は Resources.NotFoundException をスローします。
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}

完成したメソッドは次のコード スニペットのようになります。

private fun setMapStyle(map: GoogleMap) {
   try {
       // Customize the styling of the base map using a JSON object defined
       // in a raw resource file.
       val success = map.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
               this,
               R.raw.map_style
           )
       )

       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}
  1. 最後に、onMapReady() メソッドで setMapStyle() メソッドを呼び出して、GoogleMap オブジェクトを渡します。
override fun onMapReady(googleMap: GoogleMap) {
   ...
   setMapStyle(map)
}
  1. アプリを実行します。
  2. 地図を normal モードに設定すると、レトロなテーマ設定と選択した色の道路で新しいスタイルが表示されます。

b59d6cb81f02a14f.png

ステップ 3: マーカーのスタイルを設定する

地図上のマーカーのスタイルを設定して、地図をさらにカスタマイズできます。このステップでは、デフォルトの赤いマーカーをより洗練されたものに変更します。

  1. onMapLongClick() メソッドで、次のコード行をコンストラクタの MarkerOptions() に追加して、デフォルトのマーカーを使用しますが、色を青に変更します。
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))

onMapLongClickListener() は次のようになります。

map.setOnMapLongClickListener { latLng ->
   // A snippet is additional text that's displayed after the title.
   val snippet = String.format(
       Locale.getDefault(),
       "Lat: %1$.5f, Long: %2$.5f",
       latLng.latitude,
       latLng.longitude
   )
   map.addMarker(
       MarkerOptions()
           .position(latLng)
           .title(getString(R.string.dropped_pin))
           .snippet(snippet)
         .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
   )
}
  1. アプリを実行します。長押しすると表示されるマーカーが青色で表示されるようになります。なお、onPoiClick() メソッドにスタイル設定を追加していないため、スポット マーカーは引き続き赤色です。

b9916bca3c367e3.png

7. タスク: オーバーレイを追加する

Google マップをカスタマイズする一つの方法として、地図上に図形を描画することができます。この手法は、人気の釣り場など、特定の種類の場所を強調する場合に便利です。

  • シェイプ: 地図にポリラインポリゴンを追加できます。
  • GroundOverlay オブジェクト: 地面オーバーレイは、地図に固定された画像です。マーカーとは異なり、地面オーバーレイの向きは、画面ではなく地表面の向きに設定されます。地図を回転、傾斜、ズームすると、画像の向きが変わります。地面オーバーレイは、地図上の 1 つの領域に 1 つの画像を固定したい場合に便利です。

ステップ: 地面オーバーレイを追加する

このタスクでは、自宅の位置に Android の形の地面オーバーレイを追加します。

  1. この Android 画像をダウンロードして、res/drawable フォルダに保存します。(ファイル名が android.png であることを確認してください)。

61fabd56a0841b44.png

  1. onMapReady() で、カメラを家の位置に移動する呼び出しの後に、GroundOverlayOptions オブジェクトを作成します。
  2. オブジェクトに androidOverlay という変数を割り当てます。
val androidOverlay = GroundOverlayOptions()
  1. BitmapDescriptorFactory.fromResource() メソッドを使用して、ダウンロードした画像リソースから BitmapDescriptor オブジェクトを作成します。
  2. 結果の BitmapDescriptor オブジェクトを GroundOverlayOptions オブジェクトの image() メソッドに渡します。
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
  1. 目的のオーバーレイの幅(メートル単位)の float overlaySize を作成します。この例では、幅を 100f にするとうまくいきます。

position() メソッドを呼び出して、GroundOverlayOptions オブジェクトの position プロパティを設定し、homeLatLng オブジェクトと overlaySize を渡します。

val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
   .position(homeLatLng, overlaySize)
  1. GoogleMap オブジェクトで addGroundOverlay() を呼び出し、GroundOverlayOptions オブジェクトを渡します。
map.addGroundOverlay(androidOverlay)
  1. アプリを実行します。
  2. zoomLevel の値を 18f に変更して、Android 画像をオーバーレイとして表示します。

b1b25b0acd6a9807.png

8. タスク: 位置情報追跡を有効にする

ユーザーは多くの場合、現在地を確認するために Google マップを使用します。地図上にデバイスの位置情報を表示するには、位置情報レイヤを使用します。

位置情報レイヤにより、地図に現在地アイコンが追加されます。

f317f84dcb3ac3a1.png

ユーザーがボタンをタップすると、デバイスの現在地が地図の中央に表示されます。デバイスが静止している場合は、位置情報が青い点で表示され、デバイスが移動している場合は青いシェブロンで表示されます。

このタスクでは、位置情報レイヤを有効にします。

ステップ: 位置情報の利用許可をリクエストする

Google マップで位置追跡を有効にするには、コードを 1 行記述する必要があります。ただし、(実行時の権限モデルを使用して)ユーザーが位置情報の利用を許可していることを確認する必要があります。

このステップでは、位置情報の利用許可をリクエストし、位置情報追跡を有効にします。

  1. AndroidManifest.xml ファイルで、FINE_LOCATION 権限がすでに存在することを確認します。Google マップ テンプレートを選択したときに、Android Studio がこの権限を挿入しました。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. MapsActivity で、REQUEST_LOCATION_PERMISSION クラス変数を作成します。
private val REQUEST_LOCATION_PERMISSION = 1
  1. 権限が付与されているかどうかを確認するには、MapsActivityisPermissionGranted() というメソッドを作成します。この方法では、ユーザーが権限を付与したかどうかを確認します。
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. アプリで位置情報追跡を有効にするには、引数を取らず、何も返さない enableMyLocation() というメソッドを MapsActivity に作成します。その中で、ACCESS_FINE_LOCATION 権限を確認します。権限が付与されている場合は、位置情報レイヤを有効にします。それ以外の場合は、権限をリクエストします。
private fun enableMyLocation() {
   if (isPermissionGranted()) {
       map.isMyLocationEnabled = true 
   }
   else {
       ActivityCompat.requestPermissions(
           this,
           arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
           REQUEST_LOCATION_PERMISSION
       )
   }
}
  1. onMapReady() コールバックから enableMyLocation() を呼び出して、位置情報レイヤを有効にします。
override fun onMapReady(googleMap: GoogleMap) {
   ...
   enableMyLocation()
}
  1. onRequestPermissionsResult() メソッドをオーバーライドします。requestCodeREQUEST_LOCATION_PERMISSION と等しいかどうかを確認します。権限がある場合は、権限が付与されていることを意味します。権限が付与されている場合は、grantResults 配列の最初のスロットに PackageManager.PERMISSION_GRANTED が含まれているかどうかも確認します。true の場合は、enableMyLocation() を呼び出します。
override fun onRequestPermissionsResult(
   requestCode: Int,
   permissions: Array<String>,
   grantResults: IntArray) {
   if (requestCode == REQUEST_LOCATION_PERMISSION) {
       if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
           enableMyLocation()
       }
   }
}
  1. アプリを実行します。デバイスの位置情報へのアクセスをリクエストするダイアログが表示されます。権限を許可してください。

da7e23e00ec762c1.png

デバイスの現在地が地図に青い点で表示されます。場所ボタンがあることに注目してください。現在地から離れた場所に地図を移動してこのボタンをクリックすると、デバイスの現在地が地図の中心に戻ります。

5b12eda7f467bc2f.png

9. 解答コード

この Codelab の完成したコードをダウンロードします。

$  git clone https://github.com/googlecodelabs/android-kotlin-geo-maps

または、リポジトリを ZIP ファイルとしてダウンロードし、Android Studio で開くこともできます。

10. まとめ

これで、Android Kotlin アプリに Google マップを追加し、スタイルを設定しました。

11. 関連リンク

Android デベロッパー ドキュメント:

リファレンス ドキュメント:

12. 次の Codelab

このコースの他の Codelab へのリンクについては、Kotlin を使用した高度な Android Codelab のランディング ページをご覧ください。