高度な Android 09.1: Google マップ

1. ようこそ

この Codelab は、Google Developers トレーニング チームが開発した高度な Android 開発トレーニング コースの一部です。Codelab を順番に進めると、このコースを最大限に活用できます。

コースの詳細については、上級 Android デベロッパー向けコースの概要をご覧ください。

はじめに

Google マップを使用してアプリを構築すると、航空写真、堅牢な UI コントロール、位置情報追跡、位置マーカーなどの機能をアプリに追加できます。有名な釣り場や登山エリアの場所など、独自のデータセットの情報を表示することで、標準の Google マップに価値を追加できます。ポケモン GO のように、現実世界と結びついたゲームを作成することもできます。

この実習では、Wander という名前の Google マップアプリを作成します。

前提となる知識

以下について把握しておく必要があります。

  • Google マップの基本機能。
  • 実行時の権限。
  • Android Studio でアプリを作成、ビルド、実行する。
  • build.gradle ファイルに外部ライブラリを含める。

学習内容

  • アプリに Google マップを統合します。
  • さまざまな地図の種類を表示します。
  • Google マップのスタイルを設定します。
  • 地図にマーカーを追加します。
  • ユーザーがスポット(POI)にマーカーを配置できるようにします。
  • 位置情報の追跡を有効にします。
  • Google ストリートビューを有効にします。

演習内容

  • Google API Console から API キーを取得し、アプリに登録します。
  • Google マップが埋め込まれた Wander アプリを作成します。
  • マーカー、スタイル設定、位置情報追跡などのカスタム機能をアプリに追加します。
  • アプリで位置情報の追跡とストリートビューを有効にします。

2. アプリの概要

この実習では、スタイル設定された Google マップである Wander アプリを作成します。Wander アプリでは、場所にマーカーをドロップしたり、現在地をリアルタイムで確認したり、ストリートビューのパノラマを表示したりできます。

スタイル付き Google マップ

Android アプリの Google ストリートビュー

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

Google Maps API(Places API など)には API キーが必要です。API キーを取得するには、Google API Console でプロジェクトを登録します。API キーは、アプリをその作成者に関連付けるデジタル証明書に関連付けられています。デジタル証明書の使用とアプリへの署名について詳しくは、アプリへの署名をご覧ください。

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

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

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

  1. 新しい Android Studio プロジェクトを作成します。
  2. 新しいアプリの名前を「Wander」にします。[アクティビティを追加] ページが表示されるまで、デフォルト値をそのまま使用します。
  3. [Google Maps Activity] テンプレートを選択します。
  4. [Activity Name] と [Layout Name] はデフォルトのままにします。
  5. [タイトル] を「Wander」に変更し、[完了] をクリックします。

Android Studio では、地図に関連する追加ファイルがいくつか作成されます。

google_maps_api**.xml**

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

activity_maps.xml

このレイアウト ファイルには、画面全体を埋める単一のフラグメントが含まれています。SupportMapFragment クラスは Fragment クラスのサブクラスです。SupportMapFragment は、追加の属性を持つ任意の ViewGroup<fragment> タグを使用して、レイアウト ファイルに含めることができます。

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

MapsActivity.java

MapsActivity.java ファイルは SupportMapFragment クラスをインスタンス化し、クラスの getMapAsync() メソッドを使用して Google マップを準備します。SupportMapFragment を含むアクティビティは、OnMapReadyCallback インターフェースとそのインターフェースの onMapReady() メソッドを実装する必要があります。getMapAsync() メソッドは、マップが読み込まれたことを示す GoogleMap オブジェクトを返します。

1.2 API キーを取得する

  1. google_maps_api.xml ファイルのデバッグ バージョンを開きます。

このファイルには長い URL を含むコメントが含まれています。URL のパラメータには、アプリに関する具体的な情報が含まれます。

  1. URL をコピーしてブラウザに貼り付けます。
  2. プロンプトに沿って、Google API Console でプロジェクトを作成します。指定された URL のパラメータにより、API Console は Google Maps Android API を自動的に有効にします。
  3. API キーを作成し、[キーを制限] をクリックして、キーの使用を Android アプリに制限します。生成された API キーは AIza で始まります。
  4. google_maps_api.xml ファイルで、YOUR_KEY_HERE と書かれている google_maps_key 文字列に鍵を貼り付けます。
  5. アプリを実行します。アクティビティに地図が埋め込まれ、オーストラリアのシドニーにマーカーが設定されています。(シドニーのマーカーはテンプレートの一部であり、後で変更します)。

4. タスク 2. 地図のタイプとマーカーを追加する

Google マップには、標準、地図 + 写真、航空写真、地形、「なし」の 5 種類の地図タイプがあります。このタスクでは、ユーザーが地図の種類を変更できるオプション メニューを含むアプリバーを追加します。地図の開始位置を自宅の位置に移動します。次に、地図上の単一の場所を示し、ラベルを含めることができるマーカーのサポートを追加します。

2.1 地図の種類を追加する

ユーザーが求める地図の種類は、ユーザーが必要とする情報の種類によって異なります。車内でナビゲーションに地図を使用する際は、道路名がはっきりと表示されると便利です。ハイキングでは、山頂に到達するまでにどれだけ登る必要があるかを知りたいでしょう。このステップでは、ユーザーが地図の種類を変更できるオプション メニューを含むアプリバーを追加します。

  1. 新しいメニュー XML ファイルを作成するには、res ディレクトリを右クリックして、[New] > [Android Resource File] を選択します。
  2. ダイアログで、ファイル名を map_options とします。リソースタイプとして [メニュー] を選択します。[OK] をクリックします。
  3. 新しいファイル内のコードを次のコードに置き換えて、地図オプションを作成します。「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. title 属性の文字列リソースを作成します。
  2. MapsActivity ファイルで、クラスを FragmentActivity クラスを拡張するのではなく、AppCompatActivity クラスを拡張するように変更します。AppCompatActivity を使用するとアプリバーが表示され、メニューも表示されます。
  3. MapsActivity で、onCreateOptionsMenu() メソッドをオーバーライドし、map_options ファイルをインフレートします。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.map_options, menu);
   return true;
}
  1. 地図のタイプを変更するには、GoogleMap オブジェクトの setMapType() メソッドを使用し、地図のタイプ定数のいずれかを渡します。

onOptionsItemSelected() メソッドをオーバーライドします。ユーザーがメニュー オプションのいずれかを選択したときに地図の種類を変更するには、次のコードを貼り付けます。

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       // Change the map type based on the user's selection.
       switch (item.getItemId()) {
           case R.id.normal_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
               return true;
           case R.id.hybrid_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
               return true;
           case R.id.satellite_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
               return true;
           case R.id.terrain_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
               return true;
           default:
               return super.onOptionsItemSelected(item);
       }
    }
  1. アプリを実行します。アプリバーのメニューを使用して、地図のタイプを変更します。地図の外観がどのように変化するかを確認します。

2.2 デフォルトの地図の位置を移動する

デフォルトでは、onMapReady() コールバックには、Google マップが作成されたオーストラリアのシドニーにマーカーを配置するコードが含まれています。デフォルトのコールバックでは、地図をアニメーションでシドニーにパンします。このステップでは、マーカーを配置せずに地図を自宅の位置にパンし、指定したレベルまでズームします。

  1. onMapReady() メソッドで、シドニーにマーカーを配置してカメラを移動するコードを削除します。
  2. ブラウザで www.google.com/maps にアクセスし、自宅を探します。
  3. 場所を右クリックして、[この場所について] を選択します。

画面の下部に、緯度と経度などの位置情報を含む小さなウィンドウが表示されます。

  1. home という名前の新しい LatLng オブジェクトを作成します。LatLng オブジェクトで、ブラウザの Google マップで確認した座標を使用します。
  2. zoom という float 変数を作成し、変数を目的の初期ズームレベルに設定します。次のリストは、各ズームレベルで表示されるおおよその詳細度を示しています。
  • 1: 世界
  • 5: 大陸
  • 10: 都市
  • 15: 通り
  • 20: 建物
  1. CameraUpdateFactory.newLatLngZoom() を使用して CameraUpdate オブジェクトを作成し、LatLng オブジェクトと zoom 変数を渡します。新しい CameraUpdate オブジェクトを渡して、GoogleMap オブジェクトで moveCamera() を呼び出し、カメラをパンしてズームします。
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(home, zoom));
  1. アプリを実行します。地図が自宅に移動し、希望のレベルにズームインします。

2.3 地図マーカーを追加する

Google マップでは、Marker クラスを使用して作成したマーカーを使用して、場所を特定できます。デフォルトのマーカーは、標準の Google マップ アイコン(Google マップのマーカー)を使用します。

マーカーを拡張して、情報ウィンドウにコンテキスト情報を表示できます。

このステップでは、ユーザーが地図上の場所を長押ししたときにマーカーを追加します。次に、マーカーがタップされたときにマーカーの座標を表示する InfoWindow を追加します。

ドロップしたピンの情報ウィンドウ

  1. MapsActivitysetMapLongClick() というメソッド スタブを作成します。このメソッドは final GoogleMap を引数として受け取り、void を返します。
private void setMapLongClick(final GoogleMap map) {}
  1. GoogleMap オブジェクトの setOnMapLongClickListener() メソッドを使用して、ユーザーがタッチして長押しした場所にマーカーを配置します。onMapLongClick() メソッドをオーバーライドする OnMapLongClickListener の新しいインスタンスを渡します。受信引数は、ユーザーが押した位置の座標を含む LatLng オブジェクトです。
private void setMapLongClick(final GoogleMap map) {
   map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
       @Override
       public void onMapLongClick(LatLng latLng) {
       }
   });
}
  1. onMapLongClick() 内で、addMarker() メソッドを呼び出します。位置が渡された LatLng に設定された新しい MarkerOptions オブジェクトを渡します。
map.addMarker(new MarkerOptions().position(latLng));
  1. onMapReady() メソッドの最後に setMapLongClick() を呼び出します。mMap を渡します。
  2. アプリを実行します。地図を長押しして、その場所にマーカーを配置します。
  3. マーカーをタップすると、画面の中央に表示されます。

画面の左下にナビゲーション ボタンが表示され、ユーザーは Google マップアプリを使用してマークされた位置に移動できます。

マーカーに情報ウィンドウを追加するには:

  1. MarkerOptions オブジェクトで、title フィールドと snippet フィールドを設定します。
  2. onMapLongClick() で、title フィールドを「Dropped Pin」に設定します。addMarker() メソッド内で snippet フィールドを位置情報の座標に設定します。
map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
   @Override
   public void onMapLongClick(LatLng latLng) {
       String snippet = String.format(Locale.getDefault(),
               "Lat: %1$.5f, Long: %2$.5f",
               latLng.latitude,
               latLng.longitude);

       map.addMarker(new MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet));
   }
});
  1. アプリを実行します。地図を長押しして、位置マーカーをドロップします。マーカーをタップして情報ウィンドウを表示します。

2.4 POI リスナーを追加する

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

このステップでは、地図に GoogleMap.OnPoiClickListener を追加します。このクリック リスナーは、長押しを待つのではなく、すぐに地図上にマーカーを配置します。クリック リスナーは、POI 名を含む情報ウィンドウも表示します。

スポット マーカー

  1. MapsActivitysetPoiClick() というメソッド スタブを作成します。このメソッドは final GoogleMap を引数として受け取り、void を返します。
private void setPoiClick(final GoogleMap map) {}
  1. setPoiClick() メソッドで、渡された GoogleMapOnPoiClickListener を設定します。
map.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
   @Override
   public void onPoiClick(PointOfInterest poi) {
   }
});
  1. onPoiClick() メソッドで、POI の場所にマーカーを配置します。タイトルを POI の名前に設定します。結果を poiMarker という変数に保存します。
public void onPoiClick(PointOfInterest poi) {
   Marker poiMarker = mMap.addMarker(new MarkerOptions()
       .position(poi.latLng)
       .title(poi.name);
}
  1. poiMarkershowInfoWindow() を呼び出すと、情報ウィンドウがすぐに表示されます。
poiMarker.showInfoWindow();
  1. onMapReady() の最後に setPoiClick() を呼び出します。mMap を渡します。
  2. アプリを実行し、公園などのスポットを探します。POI をタップすると、その場所にマーカーが配置され、情報ウィンドウに POI の名前が表示されます。

5. タスク 3. 地図のスタイルを設定する

Google マップはさまざまな方法でカスタマイズでき、地図に独自のルック アンド フィールを与えることができます。

他のフラグメントをカスタマイズする場合と同様に、使用可能な XML 属性を使用して MapFragment オブジェクトをカスタマイズできます。ただし、このステップでは、GoogleMap オブジェクトのメソッドを使用して、MapFragmentコンテンツの見た目と操作感をカスタマイズします。オンラインのスタイル設定ウィザードを使用して、地図にスタイルを追加し、マーカーをカスタマイズします。また、地図に合わせて拡大 / 回転する GroundOverlay を自宅の位置に追加します。

3.1 地図にスタイルを追加する

地図のカスタマイズされたスタイルを作成するには、地図内のフィーチャーの表示方法を指定する JSON ファイルを生成します。この JSON ファイルを手動で作成する必要はありません。Google は、地図のスタイルを視覚的に設定した後に JSON を生成する スタイル ウィザードを提供しています。この実習では、マップを「夜間モード」用にスタイル設定します。つまり、夜間に使用するために、マップに暗い色と低いコントラストを使用します。

  1. ブラウザで https://mapstyle.withgoogle.com/ に移動します。
  2. [スタイルを作成] を選択します。
  3. [] テーマを選択します。
  4. メニューの下部にある [その他のオプション] をクリックします。
  5. [設備や機能の種類] リストの下部にある [水域 > 塗りつぶし] を選択します。水の色を濃い青色(#160064 など)に変更します。
  6. [完了] をクリックします。表示されたポップアップ ウィンドウから JSON コードをコピーします。
  7. Android Studio で、res ディレクトリに raw という名前のリソース ディレクトリを作成します。res/rawmap_style.json というファイルを作成します。
  8. JSON コードを新しいリソース ファイルに貼り付けます。
  9. JSON スタイルを地図に設定するには、GoogleMap オブジェクトで setMapStyle() を呼び出します。JSON ファイルを読み込む MapStyleOptions オブジェクトを渡します。setMapStyle() メソッドは、スタイルの設定が成功したかどうかを示すブール値を返します。ファイルを読み込めない場合、メソッドは Resources.NotFoundException をスローします。

次のコードを onMapReady() メソッドにコピーして、地図のスタイルを設定します。ログステートメント用に TAG 文字列を作成する必要がある場合があります。

     try {
        // Customize the styling of the base map using a JSON object defined
        // in a raw resource file.
        boolean success = googleMap.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
                   this, R.raw.map_style));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
     } catch (Resources.NotFoundException e) {
        Log.e(TAG, "Can't find style. Error: ", e);
     }
  1. アプリを実行します。地図が normal モードのときに、新しいスタイル設定が表示されるはずです。

夜間モード スタイルの Google マップ

3.2 マーカーのスタイルを設定する

地図マーカーのスタイルを設定して、地図をさらにカスタマイズできます。このステップでは、デフォルトの赤いマーカーをナイトモードの配色に合わせて変更します。

  1. onMapLongClick() メソッドで、次のコード行を MarkerOptions() コンストラクタに追加して、デフォルトのマーカーを使用しつつ、色を青に変更します。
.icon(BitmapDescriptorFactory.defaultMarker
       (BitmapDescriptorFactory.HUE_BLUE))
  1. アプリを実行します。配置したマーカーが青色で表示されるようになり、アプリの夜間モードのテーマとより一致するようになりました。

onPoiClick() メソッドにスタイルを追加していないため、POI マーカーはまだ赤色です。

3.3 オーバーレイを追加する

Google マップをカスタマイズする方法の 1 つは、地図の上に描画することです。この手法は、人気の釣り場など、特定の種類の場所をハイライト表示する場合に便利です。次の 3 種類のオーバーレイがサポートされています。

  • シェイプ: 地図にポリラインポリゴンを追加できます。
  • TileOverlay オブジェクト: タイル オーバーレイは、基本地図タイルの上に重ねて追加される画像のセットを定義します。タイル オーバーレイは、大きい画像をマップに追加する場合に役立ちます。一般的なタイル オーバーレイは、広い地理的領域を対象としています。
  • GroundOverlay オブジェクト: 地面オーバーレイは、地図に固定されている画像です。マーカーとは異なり、地面オーバーレイは画面ではなく地表面に平行に配置されます。地図を回転、傾斜、ズームすると、画像の向きが変わります。地面オーバーレイは、地図上の 1 か所に 1 枚の画像を固定したい場合に便利です。

このステップでは、Android の形をしたグラウンド オーバーレイを自宅の場所に配置します。

  1. この Android イメージをダウンロードして、res/drawable フォルダに保存します。
  2. onMapReady() で、カメラをホーム ポジションに移動する呼び出しの後、GroundOverlayOptions オブジェクトを作成します。オブジェクトを homeOverlay という変数に割り当てます。
GroundOverlayOptions homeOverlay = new GroundOverlayOptions();
  1. 上記の画像から BitmapDescriptor オブジェクトを作成するには、BitmapDescriptorFactory.fromResource() メソッドを使用します。オブジェクトを GroundOverlayOptions オブジェクトの image() メソッドに渡します。
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.android));
  1. position() メソッドを呼び出して、GroundOverlayOptions オブジェクトの position プロパティを設定します。home LatLng オブジェクトと、目的のオーバーレイの幅(メートル単位)を表す float を渡します。この例では、幅 100 m が適切です。
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
     .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
       .position(home, 100);
  1. GoogleMap オブジェクトで addGroundOverlay() を呼び出します。GroundOverlayOptions オブジェクトを渡します。
mMap.addGroundOverlay(homeOverlay);
  1. アプリを実行します。自宅の位置を拡大すると、Android の画像がオーバーレイとして表示されます。

6. タスク 4. 位置情報の追跡とストリートビューを有効にする

ユーザーは現在地を確認するために Google マップをよく使用します。Location Services API を使用してデバイスの位置情報を取得できます。Location データをさらに使用せずに地図上にデバイスの位置情報を表示するには、位置情報データレイヤを使用します。

位置情報レイヤでは、地図の右上に [現在地] ボタンが追加されます。ユーザーがボタンをタップすると、地図の中心がデバイスの位置に移動します。現在地は、デバイスが静止している場合は青い点で示され、デバイスが移動している場合は青い山形で示されます。

位置情報の追跡機能が組み込まれたスタイル設定済みの Google マップ

Google ストリートビュー(特定の場所のナビゲーション可能なパノラマ写真)を使用して、場所に関する追加情報を提供できます。

このタスクでは、位置情報レイヤとストリートビューを有効にして、ユーザーが POI マーカーの情報ウィンドウをタップしたときに地図がストリートビュー モードに切り替わるようにします。

4.1 位置情報の追跡を有効にする

Google マップで位置情報の追跡を有効にするには、1 行のコードが必要です。ただし、ユーザーが位置情報の権限を付与していることを確認する必要があります(ランタイム権限モデルを使用)。

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

  1. AndroidManifest.xml ファイルで、FINE_LOCATION 権限がすでに存在することを確認します。Android Studio で Google マップ テンプレートを選択すると、この権限が挿入されます。
  2. アプリで位置情報のトラッキングを有効にするには、MapsActivity に、引数を受け取らず何も返さない enableMyLocation() というメソッドを作成します。
  3. enableMyLocation() メソッドを定義します。ACCESS_FINE_LOCATION 権限を確認します。権限が付与されている場合は、位置情報レイヤを有効にします。それ以外の場合は、権限をリクエストします。
private void enableMyLocation() {
   if (ContextCompat.checkSelfPermission(this,
           Manifest.permission.ACCESS_FINE_LOCATION)
           == PackageManager.PERMISSION_GRANTED) {
       mMap.setMyLocationEnabled(true);
   } else {
       ActivityCompat.requestPermissions(this, new String[]
                       {Manifest.permission.ACCESS_FINE_LOCATION},
               REQUEST_LOCATION_PERMISSION);
   }
}
  1. onMapReady() コールバックから enableMyLocation() を呼び出して、位置情報レイヤを有効にします。
  2. onRequestPermissionsResult() メソッドをオーバーライドします。権限が付与されている場合は、enableMyLocation() を呼び出します。
@Override
public void onRequestPermissionsResult(int requestCode,
       @NonNull String[] permissions,
       @NonNull int[] grantResults) {
   // Check if location permissions are granted and if so enable the
   // location data layer.
   switch (requestCode) {
       case REQUEST_LOCATION_PERMISSION:
           if (grantResults.length > 0
                   && grantResults[0]
                   == PackageManager.PERMISSION_GRANTED) {
               enableMyLocation();
               break;
           }
   }
}
  1. アプリを実行します。右上に [現在地] ボタンが表示され、デバイスの現在地が表示されます。

4.2 ストリートビューを有効にする

Google マップでは、ストリートビューという、指定された経路に沿って移動するためのコントロールを備えた場所のパノラマビューが提供されています。ストリートビューは世界中で利用できるわけではありません

この手順では、ユーザーが POI の情報ウィンドウをタップしたときにアクティブになるストリートビュー パノラマを有効にします。次の 2 つを行う必要があります。

  1. アプリの機能がスポット マーカーでのみ動作するように、スポット マーカーを他のマーカーと区別します。このようにすると、ユーザーがスポットの情報ウィンドウをタップしたときにストリートビューを開始できますが、他のタイプのマーカーをタップしたときには開始されません。

Marker クラスには、データを添付できる setTag() メソッドが含まれています。(データは Object から拡張されたものであれば何でもかまいません)。ユーザーがスポットをクリックしたときに作成されるマーカーにタグを設定します。

  1. ユーザーが OnInfoWindowClickListener でタグ付けされた情報ウィンドウをタップした場合は、MapFragmentStreetViewPanoramaFragment に置き換えます。(以下のコードでは、API 12 より前の Android バージョンをサポートするために SupportMapFragmentSupportStreetViewPanoramaFragment を使用しています)。

実行時にフラグメントが変更される場合は、XML で静的にではなく、包含する Activity クラスに追加する必要があります。

スポットのマーカーにタグを付ける

  1. onPoiClick() コールバックで、poiMarkersetTag() を呼び出します。任意の文字列を渡します。
poiMarker.setTag("poi");

静的な SupportMapFragment を実行時のインスタンスに置き換える

  1. activity_maps.xml を開き、要素をフラグメントのコンテナとして機能するフレーム レイアウトに変更します。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/fragment_container"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />
  1. MapsActivityonCreate() で、ID で SupportMapFragment を検索するコードを削除します。XML に静的な SupportMapFragment がなくなったためです。代わりに、SupportMapFragment.newInstance() を呼び出して SupportMapFragment の新しいランタイム インスタンスを作成します。
SupportMapFragment mapFragment = SupportMapFragment.newInstance();
  1. FragmentManager を使用してフラグメント トランザクションでフラグメントを FrameLayout に追加します。
getSupportFragmentManager().beginTransaction()
       .add(R.id.fragment_container, mapFragment).commit();
  1. 地図の非同期読み込みをトリガーするコード行はそのままにします。
mapFragment.getMapAsync(this);

OnInfoWindowClickListener を設定してマーカータグを確認する

  1. MapsActivityGoogleMap を引数として受け取り、void を返す setInfoWindowClickToPanorama() というメソッド スタブを作成します。
private void setInfoWindowClickToPanorama(GoogleMap map) {}
  1. OnInfoWindowClickListenerGoogleMap に設定します。
map.setOnInfoWindowClickListener(
       new GoogleMap.OnInfoWindowClickListener() {
           @Override
           public void onInfoWindowClick(Marker marker) {
           }
       });
  1. onInfoWindowClick() メソッドで、マーカーに onPoiClick() メソッドで設定した文字列タグが含まれているかどうかを確認します。
if (marker.getTag() == "poi") {}

SupportMapFragment を SupportStreetViewPanoramaFragment に置き換える

  1. マーカーにタグが含まれている場合は、StreetViewPanoramaOptions オブジェクトを使用してストリートビュー パノラマの場所を指定します。オブジェクトの position プロパティを、渡されたマーカーの位置に設定します。
StreetViewPanoramaOptions options =
       new StreetViewPanoramaOptions().position(
               marker.getPosition());
  1. 作成した options オブジェクトを渡して、SupportStreetViewPanoramaFragment の新しいインスタンスを作成します。
SupportStreetViewPanoramaFragment streetViewFragment
       = SupportStreetViewPanoramaFragment
       .newInstance(options);
  1. フラグメント トランザクションを開始します。フラグメント コンテナの内容を新しいフラグメント streetViewFragment に置き換えます。トランザクションをバックスタックに追加して、戻るボタンを押すとアプリが終了するのではなく、SupportMapFragment に戻るようにします。
getSupportFragmentManager().beginTransaction()
       .replace(R.id.fragment_container,
               streetViewFragment)
       .addToBackStack(null).commit();
  1. setPoiClick(). の呼び出し後に onMapReady()setInfoWindowClickToPanorama(mMap) を呼び出す
  2. アプリを実行します。マウンテンビュー(Google 本社の所在地)など、ストリートビューの対象地域の都市にズームし、公園などの POI を見つけます。POI をタップしてマーカーを配置し、情報ウィンドウを表示します。情報ウィンドウをタップすると、マーカーの場所のストリートビュー モードに切り替わります。[戻る] ボタンを押して、マップ フラグメントに戻ります。

Android アプリの Google ストリートビュー

7. 解答コード

Wander ソリューション コード。

8. コーディングの課題

課題: ストリートビューの対象外の場所にある POI の情報ウィンドウをタップすると、黒い画面が表示されます。

9. まとめ

  • Maps API を使用するには、Google API Console から API キーを取得する必要があります。
  • Android Studio で Google Maps Activity テンプレートを使用すると、アプリのレイアウトに 1 つの SupportMapFragment を含む Activity が生成されます。また、テンプレートはアプリ マニフェストに ACCESS_FINE_PERMISSION を追加し、アクティビティに OnMapReadyCallback を実装し、必要な onMapReady() メソッドをオーバーライドします。

実行時に GoogleMap の地図タイプを変更するには、GoogleMap.setMapType() メソッドを使用します。Google マップは、次のいずれかの地図タイプになります。

  • Normal: 通常の道路地図。道路、一部の人工物、河川などの重要な自然物を表示します。道路や対象物のラベルも表示されます。
  • ハイブリッド: 航空写真データに道路地図を加えたもの。道路や対象物のラベルも表示されます。
  • 航空写真: 写真データ。道路および地物のラベルは表示されません。
  • 地形: 地形データ。色、等高線とラベル、透視投影による影も表示されます。一部の道路とラベルも表示されます。
  • なし**:** 地図なし。

Google マップについて:

  • マーカーは、特定の地理的位置を示すインジケーターです。
  • タップすると、マーカーのデフォルトの動作として、その場所に関する情報を含む情報ウィンドウが表示されます。
  • スポット(地図上の場所)は、対応するアイコンとともに基本地図にデフォルトで表示されます。POI には、公園、学校、政府機関などが含まれます。
  • また、地図タイプが normal の場合は、ビジネス スポット(店舗、レストラン、ホテルなど)がデフォルトで地図に表示されます。
  • OnPoiClickListener を使用して、スポットのクリックをキャプチャできます。
  • スタイル設定ウィザードを使用すると、Google マップのほぼすべての要素の視覚的な外観を変更できます。スタイル ウィザードは、setMapStyle() メソッドを使用して Google マップに渡す JSON ファイルを生成します。
  • デフォルトの色を変更したり、デフォルトのマーカー アイコンをカスタム画像に置き換えたりして、マーカーをカスタマイズできます。

その他の重要な情報:

  • 地面オーバーレイを使用して、画像を地理的位置に固定します。
  • GroundOverlayOptions オブジェクトを使用して、画像、画像のサイズ(メートル単位)、画像の位置を指定します。このオブジェクトを GoogleMap.addGroundOverlay() メソッドに渡して、オーバーレイを地図に設定します。
  • アプリに ACCESS_FINE_LOCATION 権限が付与されている場合、mMap.setMyLocationEnabled(true) メソッドを使用して位置情報の追跡を有効にできます。
  • Google ストリートビューは、対象地域全体について、指定された道路からの 360 度のパノラマビューを提供します。
  • StreetViewPanoramaFragment.newInstance() メソッドを使用して、新しいストリートビュー フラグメントを作成します。
  • ビューのオプションを指定するには、StreetViewPanoramaOptions オブジェクトを使用します。オブジェクトを newInstance() メソッドに渡します。

10. 関連リンク

関連するコンセプトのドキュメントは、9.1: Google Maps API にあります。

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

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

11. 宿題

このセクションでは、インストラクター主導のコースの一環として、この Codelab に取り組んでいる生徒向けに考えられる宿題をいくつか示します。インストラクターは、以下のようなことを行えます。

  • 必要に応じて宿題を与える
  • 宿題の提出方法を生徒に伝える
  • 宿題を採点する

インストラクターは、これらの提案を必要なだけ使用し、必要に応じて他の宿題も自由に与えることができます。

この Codelab に独力で取り組む場合は、これらの宿題を自由に使用して知識をテストしてください。

アプリをビルドして実行する

  1. Google マップ アクティビティ テンプレートを使用する新しいアプリを作成します。このテンプレートは、アプリの起動時に Google マップを読み込みます。
  2. Google マップが読み込まれたら、カメラを学校や自宅など、自分にとって意味のある場所に移動します。
  3. 地図に 2 つのマーカーを追加します。1 つは学校の場所、もう 1 つは自宅などの意味のある場所です。
  4. デフォルトの色を変更したり、デフォルトのマーカー アイコンをカスタム画像に置き換えたりして、マーカー アイコンをカスタマイズできます。

ヒント: onMapReady (GoogleMap googleMap) のドキュメントをご覧ください。

以下の質問に回答してください

問題 1

マップが読み込まれ、アプリで使用できる状態になったときに呼び出されるメソッドはどれですか?

問題 2

アプリに Google マップを含めるために使用できる Android コンポーネントはどれですか?

  • MapViewMapFragment
  • MapFragmentMapActivity
  • MapViewMapActivity
  • MapFragment のみ

問題 3

Google Maps Android API ではどのような種類の地図を使用できますか?

  • 標準、ハイブリッド、地形、衛星、ロードマップ
  • 標準、地図+写真、地形、航空写真、なし
  • ハイブリッド、地形図、航空写真、ロードマップ、なし
  • Normal、terrain、satellite、imagemap、none

問題 4

スポット(POI)にクリック機能を実装するには、どのインターフェースを実装しますか?

  • GoogleMap.OnPoiListener
  • GoogleMap.OnPoiClickListener
  • GoogleMap.OnPoiClick
  • GoogleMap.OnPoiClicked

採点のためアプリを送信する

採点者のガイダンス

アプリに以下の機能があることを確認します。

  • アプリを起動すると、Google マップが正しく表示され、API キーが正しく生成されたことがわかります。
  • Google マップが読み込まれると、カメラは生徒の自宅または学校の場所に移動します。コードでは、このステップは onMapReady (GoogleMap googleMap) コールバック メソッドで行う必要があります。
  • マーカーは、生徒の学校の場所と、生徒の自宅などの別の場所に表示されます。
  • 2 つのマーカーがカスタマイズされています。たとえば、マーカーがデフォルトの赤色以外の色を使用している場合や、カスタム アイコンを使用している場合などです。

12. 次の Codelab

高度な Android 開発トレーニング コースのすべての Codelab を確認するには、高度な Android 開発の Codelab のランディング ページをご覧ください。