Kotlin 04.1 版的 Android 進階功能:Android Google 地圖

1. 事前準備

您可以運用 Google 地圖建構應用程式,在應用程式中加入多項功能,例如衛星圖像、完善的地圖 UI 控制項、位置追蹤和位置標記等。您可以顯示自有資料集中的資訊 (例如知名釣魚或攀岩區的位置),讓標準 Google 地圖更實用。您也可以製作遊戲,讓玩家探索現實世界,比如尋寶或是擴增實境遊戲。

在本課程中,您將建立一個名為 Wander 的 Google 地圖應用程式,可顯示自訂地圖並顯示使用者的位置。

必要條件

應瞭解以下項目:

  • 如何建立基本的 Android 應用程式,並透過 Android Studio 執行。
  • 如何建立及管理字串等資源。
  • 如何使用 Android Studio 重構程式碼並重新命名變數。
  • 如何以使用者的身分使用 Google 地圖。
  • 如何設定執行階段權限。

課程內容

  • 如何透過 Google API 控制台取得 API 金鑰,並將金鑰註冊至應用程式
  • 如何在應用程式中整合 Google 地圖
  • 如何顯示不同的地圖類型
  • 如何設定 Google 地圖的樣式
  • 如何在地圖中加入標記
  • 如何讓使用者在搜尋點 (POI) 上放置標記
  • 如何啟用位置追蹤功能
  • 如何建立內嵌 Google 地圖的 Wander 應用程式
  • 如何為應用程式建立自訂功能,例如標記和樣式
  • 如何在應用程式中啟用位置追蹤功能

2. 應用程式總覽

在本程式碼研究室中,您將建立 Wander 應用程式,以顯示採用自訂樣式的 Google 地圖。Wander 應用程式可讓您將標記放置到位置、新增疊加層,並即時查看您的所在位置。

5b12eda7f467bc2f.png

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

Maps SDK for Android 需要 API 金鑰。如要取得 API 金鑰,請在 API 和「服務」頁面。API 金鑰會連結至連結應用程式與作者的數位憑證。如要進一步瞭解如何使用數位憑證及簽署應用程式,請參閱「簽署應用程式」。

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

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

步驟 1:使用地圖範本建立 Wander 專案

  1. 建立新的 Android Studio 專案。
  2. 選取「Google Maps Activity」(Google 地圖活動) 範本。

d6b874bb19ea68cd.png

  1. 將專案命名為 Wander
  2. 將最低 API 級別設為「API 19」。確認語言為 Kotlin
  3. 按一下 [完成]。
  4. 應用程式建構完成後,請查看專案,以及 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 類別的子類別。SupportMapFragment 是在應用程式中放置地圖最簡單的方法。這個函式是地圖檢視畫面的包裝函式,可自動處理必要的生命週期需求。

您可以在任何 ViewGroup 中使用 <fragment> 標記,搭配額外的 name 屬性,在版面配置檔案中加入 SupportMapFragment

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

MapsActivity.javaMapsActivity.java 檔案會將 onCreate() 方法中的 SupportMapFragment 執行個體化,並使用類別的getMapAsync() 用於自動初始化地圖系統和檢視畫面。包含 SupportMapFragment 的活動必須實作 OnMapReadyCallback 介面以及該介面的 onMapReady() 方法。載入地圖時,系統會呼叫 onMapReady() 方法。

步驟 2:取得 API 金鑰

  1. 開啟 google_maps_api.xml 檔案的偵錯版本。
  2. 在檔案中,找出含有長網址的註解。網址的參數包含應用程式的特定資訊。
  3. 複製網址並貼到瀏覽器中。
  4. 按照提示在 API 與「服務」頁面。由於提供網址中的參數,網頁知道要自動啟用 Maps SDK for Android。
  5. 按一下「建立 API 金鑰」
  6. 在下一頁的「API 金鑰」區段中,按一下您剛建立的金鑰。
  7. 按一下「Restrict Key」,然後選取「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 有一個名為 mMap 的私人 lateinit var,類型為 GoogleMap。如要遵循 Kotlin 命名慣例,請將 mMap 的名稱變更為 map

  1. MapsActivity 中的 mMap 上按一下滑鼠右鍵,然後依序點選「Refactor」>重新命名...

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. 在「Code」分頁中,將新檔案中的程式碼替換成下列程式碼,即可建立地圖選單選項。「無」「無」而省略地圖類型導致缺少任何地圖這個步驟會發生錯誤,但您將在下一個步驟中加以解決。
<?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.xml 中,新增 title 屬性的資源來解決錯誤。
<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() 函式,然後使用 CameraUpdateFactory.newLatLngZoom() 傳入 CameraUpdate 物件,將相機移至 homeLatLng。傳入 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. MapsActivity 中建立名為 setMapLongClick() 的方法虛設常式,並將 GoogleMap 做為引數。
  2. setOnMapLongClickListener 事件監聽器附加至地圖物件。
private fun setMapLongClick(map:GoogleMap) {
   map.setOnMapLongClickListener { }
}
  1. setOnMapLongClickListener() 中呼叫 addMarker() 方法。傳入新的 MarkerOptions 物件,並將位置設為傳入的 LatLng
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() 中,為 snippet 建立 val。文字片段是指標題後方顯示的附加文字。您的程式碼片段會顯示標記的經緯度。
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. 將標記的 snippet 設為 snippet

已完成的函式如下所示:

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:新增搜尋點事件監聽器

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

在這個步驟中,您將在地圖中加入 GoogleMap.OnPoiClickListener。這個點擊事件監聽器會在使用者點擊搜尋點時,立即在地圖上放置標記。點擊事件監聽器還會顯示包含搜尋點名稱的資訊視窗。

  1. MapsActivity 中建立名為 setPoiClick() 的方法虛設常式,並將 GoogleMap 做為引數。
  2. setPoiClick() 方法中,在傳入的 GoogleMap 上設定 OnPoiClickListener
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 提供地圖平台樣式精靈,在您視覺化呈現地圖樣式後,即可產生 JSON。在這項工作中,您要使用復古主題設定地圖的樣式,也就是讓地圖使用復古顏色,而新增彩色道路。

步驟 1:建立地圖樣式

  1. 在瀏覽器中前往 https://mapstyle.withgoogle.com/
  2. 選取「Create a Style」(建立樣式)
  3. 選取「懷舊」

208b3d3aeab0d9b6.png

  1. 按一下 [更多選項]

4a35faaf9535ee82.png

  1. 選取「道路」>填入
  2. 將道路顏色改成任何您選擇的顏色 (例如粉紅色)。

92c3293749293a4c.png

  1. 按一下 [完成]。

f1bfe8585eb69480.png

  1. 從產生的對話方塊中複製 JSON 程式碼,如有需要,可以將其儲存為純文字記事,以在下一個步驟中使用。

3c32168b299d6420.png

步驟 2:在地圖上新增樣式

  1. 在 Android Studio 的 res 目錄中,建立資源目錄並命名為 raw。您可以使用 raw 目錄資源,例如 JSON 程式碼。
  2. res/raw 中建立名為 map_style.json 的檔案。
  3. 將清單上的 JSON 程式碼貼到新的資源檔案中。
  4. MapsActivity 中,在 onCreate() 方法上方建立 TAG 類別變數。這會用於記錄。
private val TAG = MapsActivity::class.java.simpleName
  1. 此外,在 MapsActivity 中,建立接收 GoogleMapsetMapStyle() 函式。
  2. setMapStyle() 中新增 try{} 區塊。
  3. try{} 區塊中,建立 val success,以便成功設定樣式。(新增下列擷取區塊)。
  4. try{} 區塊中,將 JSON 樣式設為地圖,並針對 GoogleMap 物件呼叫 setMapStyle()。傳入 MapStyleOptions 物件,此物件會載入 JSON 檔案。
  5. 將結果指派給 successsetMapStyle() 方法會傳回布林值,表示剖析樣式檔案及設定樣式的成功狀態。
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. 最後,在傳入 GoogleMap 物件的 onMapReady() 方法中呼叫 setMapStyle() 方法。
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 物件:區域疊加層是指固定於地圖上的圖片。不同於標記,區域疊加層的方向看到的都是地球表面,而不是螢幕。旋轉、傾斜或縮放地圖會變更圖片的方向。想修正地圖上某個區域的單一圖片時,區域疊加層就非常實用。

步驟:新增區域疊加層

在這項工作中,您要將 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() 方法,並傳入 homeLatLng 物件和 overlaySize,藉此為 GroundOverlayOptions 物件設定 position 屬性。

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

使用者輕觸按鈕時,地圖會以裝置的位置為中心。如果裝置未移動,位置資訊會以藍點顯示;如果裝置正在移動,則會顯示為藍色 V 形。

在這項工作中,您要啟用位置資料層。

步驟:要求位置存取權

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

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

  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. 如要檢查是否已授予權限,請在 MapsActivity 中建立名為 isPermissionGranted() 的方法。透過這個方法,檢查使用者是否已授予權限。
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. 如要在應用程式中啟用位置追蹤功能,請在 MapsActivity 中建立 enableMyLocation() 方法,該方法不使用引數且不會傳回任何內容。在內部檢查 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() 方法。檢查 requestCode 是否等於 REQUEST_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. 解決方案程式碼

完成程式碼研究室後,請下載程式碼。

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

另外,您也能以 ZIP 檔案格式下載存放區,再將檔案解壓縮,然後在 Android Studio 中開啟。

10. 摘要

恭喜!您已將 Google 地圖新增至 Android Kotlin 應用程式並設定樣式。

11. 瞭解詳情

Android 開發人員說明文件:

參考說明文件:

12. 下一個程式碼研究室

如需本課程其他程式碼研究室的連結,請參閱「Android Kotlin 的進階程式碼研究室到達網頁」連結。