Android 09.1 進階功能:Google 地圖

1. 歡迎

這個程式碼研究室是 Google Developers 訓練團隊開發的進階 Android 開發訓練課程的一部分。只要依序完成程式碼研究室的課程,就能充分發揮本課程的價值。

如需本課程的完整資訊,請參閱進階 Android 開發總覽

簡介

您可以運用 Google 地圖建構應用程式,在應用程式中加入多項功能,例如衛星圖像、完善的 UI 控制項、位置追蹤和位置標記等。您可以將自有資料集的資訊 (例如知名釣魚或攀岩區的位置),讓標準 Google 地圖更有價值。您也可以建立與現實世界連結的遊戲,例如《Pokémon Go》。

在本練習中,您會建立名為 Wander 的 Google 地圖應用程式。

必備知識

您必須已經熟悉下列項目:

  • Google 地圖的基本功能。
  • 執行階段權限。
  • 在 Android Studio 中建立、建構及執行應用程式。
  • build.gradle 檔案中加入外部程式庫。

課程內容

  • 將 Google 地圖整合到您的應用程式中。
  • 顯示不同的地圖類型。
  • 設定 Google 地圖的樣式。
  • 在地圖中加入標記。
  • 允許使用者在搜尋點 (POI) 上放置標記。
  • 啟用位置追蹤功能。
  • 啟用 Google 街景服務。

學習內容

  • 到 Google API 控制台取得 API 金鑰,並向應用程式註冊該金鑰。
  • 建立內嵌 Google 地圖的 Wander 應用程式。
  • 在應用程式中加入自訂功能,例如標記、樣式和位置追蹤。
  • 在應用程式中啟用位置追蹤和街景服務。

2. 應用程式總覽

在本練習中,您會建立 Wander 應用程式,也就是樣式化 Google 地圖。Wander 應用程式能讓您將標記拖放至地點、即時查看自己的位置,以及查看街景服務全景。

樣式化 Google 地圖

Android 應用程式中的 Google 街景服務

3. 工作 1:設定專案並取得 API 金鑰

Google Maps API 與 Places API 一樣,需要 API 金鑰。如要取得 API 金鑰,請在 Google API 控制台中註冊專案。API 金鑰會連結至連結應用程式與作者的數位憑證。如要進一步瞭解如何使用數位憑證及簽署應用程式,請參閱「簽署應用程式」。

在本練習中,您將使用 API 金鑰做為偵錯憑證。按照「簽署偵錯版本」中的說明,偵錯憑證並不安全。已發布並使用 Google Maps API 的 Android 應用程式需要第二個 API 金鑰:發布憑證的金鑰。如要進一步瞭解如何取得發布憑證,請參閱「取得 API 金鑰」一文。

Android Studio 提供 Google 地圖活動範本,可產生實用的範本程式碼。範本程式碼包含 google_maps_api.xml 檔案,其中的連結可讓您輕鬆取得 API 金鑰。

1.1 使用地圖範本建立 Wander 專案

  1. 建立新的 Android Studio 專案。
  2. 將新應用程式命名為「Wander」。接受預設值,直到您前往「新增活動」頁面為止。
  3. 選取「Google Maps Activity」(Google 地圖活動) 範本。
  4. 保留預設的「Activity Name」(活動名稱) 和「Layout Name」(版面配置名稱) 預設值。
  5. 將「Title」變更為「Wander」然後按一下「Finish」

Android Studio 會建立幾個與地圖相關的其他檔案:

google_maps_api**.xml**

您可以使用這個設定檔保存 API 金鑰。範本會產生兩個 google_maps_api.xml 檔案:一個用於偵錯,另一個用於發布版本。偵錯憑證的 API 金鑰檔案位於 src/debug/res/values。發布憑證的 API 金鑰檔案位於 src/release/res/values。在本練習中,我們只會使用偵錯憑證。

activity_maps.xml

這個版面配置檔案含有一個填滿整個螢幕的單一片段。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 檔案的偵錯版本。

檔案含有含有長網址的註解。網址的參數包含應用程式的特定資訊。

  1. 複製網址並貼到瀏覽器中。
  2. 按照提示在 Google API 控制台建立專案。由於提供網址中的參數,API 控制台知道要自動啟用 Google Maps Android API。
  3. 建立 API 金鑰並點選「Restrict Key」,限制金鑰只能用於 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. 將新檔案中的程式碼替換為下列程式碼,建立地圖選項。「無」「無」會省略地圖類型導致缺少任何地圖
<?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 檔案中,將類別變更為擴充 AppCompatActivity 類別,而非擴充 FragmentActivity 類別。使用 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. 建立名為 zoomfloat 變數,並將變數設為所需的初始縮放等級。以下清單可讓您瞭解各縮放等級所顯示的詳細程度:
  • 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. MapsActivity 中建立名為 setMapLongClick() 的方法虛設常式,並將 final GoogleMap 做為引數並傳回 void
private void setMapLongClick(final GoogleMap map) {}
  1. 使用 GoogleMap 物件的 setOnMapLongClickListener() 方法,在使用者輕觸和保留的位置放置標記。傳入新的 OnMapLongClickListener 例項,該例項會覆寫 onMapLongClick() 方法。傳入的引數是一個 LatLng 物件,其中包含使用者按下的位置座標:
private void setMapLongClick(final GoogleMap map) {
   map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
       @Override
       public void onMapLongClick(LatLng latLng) {
       }
   });
}
  1. onMapLongClick() 中呼叫 addMarker() 方法。傳入新的 MarkerOptions 物件,並將位置設為傳入的 LatLng
map.addMarker(new MarkerOptions().position(latLng));
  1. onMapReady() 方法的結尾呼叫 setMapLongClick()。傳入 mMap
  2. 執行應用程式。按住地圖即可在地圖上放置標記。
  3. 輕觸可將標記置於畫面中央的標記。

導覽按鈕位於螢幕左下角,方便使用者透過 Google 地圖應用程式導航到標示的位置。

如何為標記新增資訊視窗:

  1. MarkerOptions 物件中,設定 title 欄位和 snippet 欄位。
  2. onMapLongClick() 中,將 title 欄位設為「已放置圖釘」。將 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 新增搜尋點事件監聽器

根據預設,搜尋點 (POI) 與對應的圖示會一併顯示在地圖上。搜尋點包括公園、學校、政府大樓等。當地圖類型設為 normal 時,商家搜尋點也會顯示在地圖上。商家搜尋點代表商家,例如商店、餐廳和飯店。

在這個步驟中,您將在地圖中加入 GoogleMap.OnPoiClickListener。這個點擊事件監聽器能立即在地圖上放置標記,不需等待輕觸可保存狀態點擊事件監聽器也會顯示包含搜尋點名稱的資訊視窗。

搜尋點標記

  1. MapsActivity 中建立名為 setPoiClick() 的方法虛設常式,並將 final GoogleMap 做為引數,然後傳回 void
private void setPoiClick(final GoogleMap map) {}
  1. setPoiClick() 方法中,在傳入的 GoogleMap 上設定 OnPoiClickListener
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. poiMarker 呼叫 showInfoWindow(),立即顯示資訊視窗。
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. 選取「Create a Style」(建立樣式)
  3. 選取「夜晚」主題。
  4. 按一下選單底部的「更多選項」
  5. 在「地圖項目類型」地圖項目類型下方,選取「水域」「水域」填滿。將水域顏色變更為深藍色 (例如 #160064)。
  6. 按一下「完成」。從結果彈出式視窗中複製 JSON 程式碼。
  7. 在 Android Studio 中,在 res 目錄中建立名為 raw 的資源目錄。在 res/raw 中建立名為 map_style.json 的檔案。
  8. 將 JSON 程式碼貼到新的資源檔案中。
  9. 如要將 JSON 樣式設為地圖,請呼叫 GoogleMap 物件上的 setMapStyle()。傳入 MapStyleOptions 物件,此物件會載入 JSON 檔案。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 地圖的方法之一,就是在地圖上方繪製地圖。如果想要標記特定類型的地點 (例如熱門釣魚地點),這項技巧就非常實用。系統支援三種疊加層類型:

  • 形狀:您可以在地圖中加入折線多邊形圓形
  • TileOverlay 物件:圖塊疊加層會定義一組圖像,疊加在基本地圖圖塊上方。當您想在地圖上加入大量圖像時,圖塊疊加層就非常實用。典型的地圖方塊疊加層涵蓋大範圍地理區域。
  • GroundOverlay 物件:區域疊加層是指固定於地圖上的圖片。不同於標記,區域疊加層的方向看到的都是地球表面,而不是螢幕。旋轉、傾斜或縮放地圖會變更圖片的方向。想修正地圖上某個區域的單一圖片時,區域疊加層就非常實用

在這個步驟中,您將在住家位置新增 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 公尺的效果良好:
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 資料,您可以使用位置資料層

位置資料層會在地圖右上方新增「我的位置」按鈕,使用者輕觸按鈕時,地圖會以裝置的位置為中心。如果裝置未移動,位置會顯示為藍點;如果裝置正在移動,則會顯示為藍色的 V 形圖案。

樣式化 Google 地圖,提供位置追蹤功能

您可以透過 Google 街景服務,也就是特定地點的可瀏覽全景相片,提供該地點的相關資訊。

在這項工作中,您要啟用位置資料層和街景服務,這樣當使用者輕觸搜尋點標記的資訊視窗時,地圖就會進入街景服務模式。

4.1 啟用位置追蹤功能

在 Google 地圖中啟用位置追蹤功能只需要一行程式碼。不過,您必須確認使用者已授予位置存取權 (使用執行階段權限模型)。

在這個步驟中,您將要求位置存取權,並啟用位置追蹤功能。

  1. AndroidManifest.xml 檔案中,確認 FINE_LOCATION 權限已存在。您選取 Google 地圖範本時,Android Studio 已插入這項權限。
  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 地圖提供街景服務,讓您透過指定路徑瀏覽地點的全景檢視。街景服務並非全球涵蓋範圍

在這個步驟中,您可以啟用街景服務全景,在使用者輕觸搜尋點的資訊視窗時啟用。您必須完成兩項操作:

  1. 指出搜尋點標記與其他標記的差異,因為您希望應用程式的功能「只」適用於搜尋點標記。如此一來,您就可以在使用者輕觸搜尋點資訊視窗時開始街景服務,而無法在使用者輕觸任何其他類型的標記時開始街景服務。

Marker 類別包含可讓您附加資料的 setTag() 方法。(資料可以是來自 Object 的任何資料)。您必須在使用者點按搜尋點時建立的標記上設定標記。

  1. 當使用者在 OnInfoWindowClickListener 中輕觸已標記的資訊視窗時,請將 MapFragment 替換成 StreetViewPanoramaFragment。(下方程式碼使用 SupportMapFragmentSupportStreetViewPanoramaFragment 支援 API 12 以下版本的 Android)。

如有任何片段在執行階段變更,您必須在內含的 Activity 類別中新增片段,而不是在 XML 中以靜態方式變更。

標記搜尋點標記

  1. onPoiClick() 回呼中,呼叫 poiMarker 上的 setTag()。傳入任何字串:
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. MapsActivity 中建立名為 setInfoWindowClickToPanorama() 的方法虛設常式,並將 GoogleMap 做為引數並傳回 void
private void setInfoWindowClickToPanorama(GoogleMap map) {}
  1. OnInfoWindowClickListener 設為 GoogleMap
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 控制台取得 API 金鑰。
  • 在 Android Studio 中使用 Google Maps Activity 範本產生 Activity,而且在應用程式的版面配置中,SupportMapFragment這個範本也會將 ACCESS_FINE_PERMISSION 新增至應用程式資訊清單,並在活動中實作 OnMapReadyCallback,並覆寫必要的 onMapReady() 方法。

如要在執行階段變更 GoogleMap 的地圖類型,請使用 GoogleMap.setMapType() 方法。Google 地圖可以是下列其中一種地圖類型:

  • 一般:一般道路地圖。顯示道路、部分人造設施,以及河流等重要自然景觀。Road and feature labels are also visible.
  • 混合地圖:已新增道路地圖的衛星相片資料。Road and feature labels are also visible.
  • 衛星:相片資料。不顯示道路和地圖項目標籤。
  • 地形:地形資料。該地圖包含的顏色,輪廓線和標籤,和透視陰影。也顯示部分道路和地圖項目標籤。
  • ****:沒有地圖。

關於 Google 地圖:

  • 標記是特定地理位置的指標。
  • 輕按標記時,標記的預設行為是顯示包含位置相關資訊的資訊視窗。
  • 根據預設,搜尋點與對應的圖示會一併顯示在基本地圖上。搜尋點包括公園、學校、政府大樓等。
  • 此外,如果地圖類型為 normal,預設會顯示商家搜尋點 (商店、餐廳、飯店等)。
  • 您可以使用 OnPoiClickListener 拍攝搜尋點的點擊次數。
  • 您可以使用樣式精靈變更 Google 地圖上幾乎所有元素的視覺外觀。樣式精靈會產生 JSON 檔案,讓您使用 setMapStyle() 方法傳遞至 Google 地圖。
  • 您可以自訂標記,像是變更預設顏色,或是將預設標記圖示換成自訂圖片。

其他重要資訊:

  • 使用區域疊加層將圖片修正為某個地理位置。
  • 使用 GroundOverlayOptions 物件指定圖片、圖片尺寸 (以公尺為單位) 和圖片位置。將此物件傳遞至 GoogleMap.addGroundOverlay() 方法,即可將疊加層設為地圖。
  • 如果您的應用程式具備 ACCESS_FINE_LOCATION 權限,即可使用 mMap.setMyLocationEnabled(true) 方法啟用位置追蹤功能。
  • 「Google 街景服務」可讓您在指定道路的涵蓋區域進行 360 度全景檢視。
  • 使用 StreetViewPanoramaFragment.newInstance() 方法建立新的街景服務片段。
  • 如要為檢視畫面指定選項,請使用 StreetViewPanoramaOptions 物件。將物件傳入 newInstance() 方法。

10. 瞭解詳情

相關概念說明文件請參閱「9.1: Google Maps API」。

Android 開發人員說明文件:

參考說明文件:

11. 作業

本節列出的作業可由課程講師指派給學習本程式碼研究室的學員。講師可自由採取以下行動:

  • 視需要指派作業。
  • 告知學員如何繳交作業。
  • 為作業評分。

講師可以視需求使用全部或部分建議內容,也可以自由指派任何其他合適的作業。

如果您是自行學習本程式碼研究室,不妨利用這些作業驗收學習成果。

建構並執行應用程式

  1. 使用 Google 地圖活動範本建立新的應用程式,在應用程式啟動時載入 Google 地圖。
  2. 載入 Google 地圖後,請將攝影機移至你的學校位置、住家位置,或是其他可以你知道的位置。
  3. 在地圖上新增兩個標記,一個是學校地點,另一個是住家或其他有意義的地點。
  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) 回呼方法中執行。
  • 標記會顯示在學生的學校位置和其他地點 (例如學生的住家)。
  • 這兩種標記可供自訂。例如,標記會使用預設紅色以外的顏色,或使用自訂圖示。

12. 下一個程式碼研究室

如要查看進階 Android 開發訓練課程中的所有程式碼研究室,請造訪進階 Android 開發程式碼研究室到達網頁