高度な Android 09.1: Google マップ

1. ようこそ

この Codelab は、Google Developers トレーニング チームが開発した高度な Android 開発トレーニング コースの一部です。このコースを最大限に活用するには、Codelab に順番に取り組んでください。

コースの詳細については、高度な Android 開発の概要をご覧ください。

はじめに

Google マップを使用してアプリを作成すると、衛星画像、堅牢な UI コントロール、位置追跡、位置マーカーなどの機能をアプリに追加できます。有名な釣り場や登山場の場所など、独自のデータセットの情報を表示することで、標準の Google マップに付加価値を与えることができます。Pokemon 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 キーを取得する

Places API と同様に、Google Maps 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」という名前を付けます。[Add an Activity] ページが表示されるまで、デフォルト値を受け入れます。
  3. [Google Maps Activity] テンプレートを選択します。
  4. [Activity Name] と [Layout Name] はデフォルトのままにします。
  5. [タイトル] を「Wander」に変更します。[Finish] をクリックします。

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

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

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 でプロンプトに従い、プロジェクトを作成します。API Console では、指定された URL のパラメータから、Google Maps Android API が自動的に有効になることが認識されます。
  3. API キーを作成し、[キーを制限] をクリックして、キーの使用を Android アプリに制限します。生成された API キーは「AIza」で始まる必要があります。
  4. google_maps_api.xml ファイルで、google_maps_key 文字列の YOUR_KEY_HERE にキーを貼り付けます。
  5. アプリを実行します。アクティビティに埋め込み地図があり、マーカーがオーストラリアのシドニーに設定されています。(シドニーのマーカーはテンプレートの一部で、後で変更できます)。

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

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

2.1 マップタイプを追加する

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

  1. 新しいメニュー XML ファイルを作成するには、res ディレクトリを右クリックして、[New] >Android リソース ファイル
  2. ダイアログで、ファイルに map_options という名前を付けます。リソースタイプに [Menu] を選択します。[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 変数を渡します。GoogleMap オブジェクトで moveCamera() を呼び出し、新しい CameraUpdate オブジェクトを渡すことで、カメラのパンとズームを行います。
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」に設定します。snippet フィールドを addMarker() メソッド内の位置座標に設定します。
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 スポット リスナーを追加する

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

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

スポットのマーカー

  1. MapsActivity で、final GoogleMap を引数として受け取り、void を返す setPoiClick() というメソッドスタブを作成します。
private void setPoiClick(final GoogleMap map) {}
  1. setPoiClick() メソッドで、渡された GoogleMapOnPoiClickListener を設定します。
map.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
   @Override
   public void onPoiClick(PointOfInterest poi) {
   }
});
  1. onPoiClick() メソッドで、スポットの位置にマーカーを配置します。タイトルをスポットの名前に設定します。結果を 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. アプリを実行し、公園などのスポットを見つけます。スポットをタップすると、そのスポットにマーカーが配置され、情報ウィンドウにそのスポットの名前が表示されます。

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() メソッドにスタイル設定を追加していないため、スポット マーカーは引き続き赤色です。

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

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

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

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

  1. この Android 画像をダウンロードして、res/drawable フォルダに保存します。
  2. onMapReady() で、カメラをホーム ポジションに移動する呼び出しの後に、GroundOverlayOptions オブジェクトを作成します。オブジェクトを homeOverlay という変数に代入します。
GroundOverlayOptions homeOverlay = new GroundOverlayOptions();
  1. BitmapDescriptorFactory.fromResource() メソッドを使用して、上記の画像から BitmapDescriptor オブジェクトを作成します。オブジェクトを 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 ストリートビューを使用して、場所に関する追加情報を提供できます。Google ストリートビューは、特定の場所のナビゲーション可能なパノラマ写真です。

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

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

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

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

  1. AndroidManifest.xml ファイルで、FINE_LOCATION 権限がすでに存在することを確認します。Google マップ テンプレートを選択したときに、Android Studio がこの権限を挿入しました。
  2. アプリで位置情報追跡を有効にするには、引数を取らず、何も返さない enableMyLocation() というメソッドを MapsActivity に作成します。
  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 マップには、指定された経路をナビゲートするためのコントロールを備えたストリートビューがあります。これは場所のパノラマビューです。ストリートビューは全世界の対象ではありません

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

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

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

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

実行時にフラグメントが変更された場合は、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. XML 内に静的 SupportMapFragment がなくなったため、MapsActivityonCreate() で、ID で 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. MapsActivity で、GoogleMap を引数として受け取り、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. SupportStreetViewPanoramaFragment の新しいインスタンスを作成し、作成した options オブジェクトを渡します。
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 本社の本社であるマウンテン ビューなど、ストリートビューを提供する都市にズームインし、公園などのスポットを探します。スポットをタップすると、マーカーを配置して情報ウィンドウを表示できます。情報ウィンドウをタップして、マーカーの位置のストリートビュー モードを開始します。[戻る] ボタンを押して地図フラグメントに戻ります。

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

7. 解答コード

Wander の解答コード。

8. コーディングの課題

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

9. まとめ

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

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

  • 標準: 通常の道路地図道路、一部の人間が建てた対象物、川などの重要な自然対象物を表示します。道路や対象物のラベルも表示されます。
  • 地図+写真: 衛星写真データと道路地図を追加しました。道路や対象物のラベルも表示されます。
  • 航空写真: 写真データ。道路および地物のラベルは表示されません。
  • 地形: 地形データ。色、等高線とラベル、透視投影による影も表示されます。一部の道路とラベルも表示されます。
  • なし**:** 地図がありません。

Google マップについて:

  • マーカーは、特定の地理的位置を示すインジケーターです。
  • マーカーがタップされると、マーカーのデフォルトの動作として、場所に関する情報を含む情報ウィンドウが表示されます。
  • スポット(地図上の場所)は対応するアイコンとともに基本地図にデフォルトで表示されます。公園、学校、政府機関などもスポットに該当します。
  • また、マップタイプが 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 Maps Activity テンプレートを使用して、アプリの起動時に Google マップを読み込む新しいアプリを作成します。
  2. Google マップが読み込まれたら、学校や自宅など、ユーザーにとって意味のある場所にカメラを移動します。
  3. 2 つのマーカーを地図に追加します。1 つは学校、もう 1 つは自宅など、わかりやすい場所に配置します。
  4. デフォルトの色を変更したり、デフォルトのマーカー アイコンをカスタム画像に置き換えたりして、マーカー アイコンをカスタマイズします。

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

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

問題 1

地図が読み込まれてアプリで使用できるようになると呼び出されるメソッドは、次のうちどれですか。

問題 2

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

  • MapViewMapFragment
  • MapFragmentMapActivity
  • MapViewMapActivity
  • MapFragment のみ

問題 3

Google Maps Android API ではどのような種類の地図が提供されますか?

  • 標準、ハイブリッド、地形図、衛星画像、ロードマップ
  • 標準、ハイブリッド、地形、衛星、「なし」
  • ハイブリッド、地形、衛星、ロードマップ、「なし」
  • 標準、地形、衛星、イメージマップ、「なし」

問題 4

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

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

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

採点者のガイダンス

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

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

12. 次の Codelab

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