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

本程式碼研究室是 Kotlin 進階課程的一部分。只要您按部就班完成程式碼研究室,就能發揮本課程的最大效益。不過,您不一定要這麼做。所有課程程式碼研究室清單均列於進階 Android 版的 Kotlin 程式碼研究室到達網頁中。

透過「Google 地圖」建立應用程式後,您還能在應用程式中添加各種功能,例如衛星圖像、強大的地圖 UI 控制項、位置追蹤以及位置標記。您可以在自己的標準 Google 地圖中新增資訊,例如自己的資料集相關資訊,例如知名的釣魚地點或攀岩區等。您也可以建立可讓玩家探索實體世界的遊戲,例如尋寶遊戲或擴增實境遊戲。

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

必要條件

對下列事項有深刻的瞭解:

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

課程內容

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

在這個程式碼研究室中,您會建立 Wander 應用程式,顯示包含自訂樣式的 Google 地圖。「Wander」應用程式可讓您將標記放置到位置、新增疊加層以及即時檢視您的位置。

Maps SDK for Android 需要 API 金鑰。如要取得 API 金鑰,請前往 API 與服務頁面註冊專案。該 API 金鑰會與數位憑證相連結,並將應用程式連結至作者。如要進一步瞭解如何使用數位憑證以及簽署應用程式,請參閱簽署應用程式

在這個程式碼研究室中,您是針對偵錯憑證使用 API 金鑰。如簽署偵錯版本所述,偵錯憑證在設計上並不安全。已發布的 Android 應用程式若使用 Maps SDK for Android,就必須提供第二個 API 金鑰:版本憑證的金鑰。如要進一步瞭解如何取得發布憑證,請參閱取得 API 金鑰

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

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

  1. 建立新的 Android Studio 專案。
  2. 選取 [Google 地圖活動] 範本。

  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:這個版面配置檔案包含填滿整個畫面的單一片段。SupportMapFragmentFragment 類別的子類別。SupportMapFragment 是在應用程式中放入地圖的最簡單方式。它是環繞地圖檢視的包裝函式,可以自動處理必要的生命週期需求。

您可以在任何版面配置中加入 SupportMapFragment 標記,只要在任何 ViewGroup 中使用 <fragment> 標記和額外的 name 屬性即可。

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

MapsActivity.javaMapsActivity.kt 檔案將 onCreate() 方法中的 SupportMapFragment 執行個體化,並使用 class' getMapAsync() 來初始化地圖系統和視圖。包含 SupportMapFragment 的活動必須導入 OnMapReadyCallback 介面和該介面的 onMapReady() 方法。地圖載入時,系統會呼叫 onMapReady() 方法。

步驟 2:取得 API 金鑰

  1. 開啟 google_maps_api.xml 檔案的偵錯版本。
  2. 在該檔案中尋找含有長網址的留言。URL 參數包含您應用程式的特定資訊。
  3. 將網址複製並貼到瀏覽器中。
  4. 按照 API 與服務頁面中的提示建立專案。因為網址中提供的參數,網頁會知道自動啟用 Maps SDK for Android。
  5. 按一下 [建立 API 金鑰]
  6. 在下一頁前往「API 金鑰」部分,然後按一下您剛建立的金鑰。
  7. 按一下 [限制金鑰],然後選取 [Maps SDK for Android],即可將該金鑰限制在 Android 應用程式中使用。
  8. 複製產生的 API 金鑰。開頭是「AIza"」。
  9. google_maps_api.xml 檔案中,將金鑰貼到顯示 YOUR_KEY_HEREgoogle_maps_key 字串中。
  10. 執行您的應用程式。您應該會在活動中看見嵌入的地圖,而且在澳洲雪梨設定標記。(範本中包含了雪梨標記,日後可加以變更)。

步驟 3:重新命名 mMap

MapsActivity有一個名為「mMap」的私人lateinit var,屬於「GoogleMap」類型。如要遵循 Kotlin 命名慣例,請將 mMap 的名稱變更為 map

  1. MapsActivity 上按一下滑鼠右鍵 mMap,接著點選 [重構] > [重新命名...]

  1. 將變數名稱變更為 map

請注意,onMapReady() 函式中所有參照的 mMap 都會變更為 map

「Google 地圖」包含數種地圖類型:一般、混合、衛星、地形以及「無」;完全沒有地圖。

法線貼圖

衛星地圖

混合地圖

地形地圖

每種地圖都有不同類型的資訊。例如,在車上使用地圖進行導航時,查看街道名稱會很有幫助,因此您可以使用一般選項。當您攀登時,地形圖就能幫助您判斷自己需要爬上多少步才能抵達頂端。

在這項工作中,您會執行下列作業:

  1. 新增含有選項選單的應用程式列,方便使用者變更地圖類型。
  2. 將地圖的起點移至您自己的住家位置。
  3. 新增支援標記,可指出地圖上的單一位置,也可以加上標籤。

新增地圖類型選單

在這個步驟中,您會新增應用程式列,並含有選項選單,方便使用者變更地圖類型。

  1. 如要建立新的選單 XML 檔案,請在「res」目錄上按一下滑鼠右鍵,然後選取 [New] (Android 資源檔案)。
  2. 在對話方塊中,將檔案命名為「map_options」。
  3. 選擇資源類型的 [Menu] (選單)
  4. 按一下「OK」(確定)
  5. 在「程式碼」分頁中,將新檔案的程式碼替換成下列程式碼,即可建立地圖選單選項。「無」表示地圖類型為「無」,因為沒有選取任何「任何」的;這個步驟會發生錯誤,但您必須在下一個步驟中解決。
<?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. 按一下 即可變更地圖類型。請注意地圖在不同模式間的外觀變化。

根據預設,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. 執行你的應用程式。地圖應該會平移到你的住家、縮放到所需的縮放等級,並在住家中放置標記。

步驟 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() 方法的結尾,呼叫 setMapLongClick()map
override fun onMapReady(googleMap: GoogleMap) {
   ...
  
   setMapLongClick(map)
}
  1. 執行應用程式。
  2. 按住地圖即可在地圖上放置標記。
  3. 輕觸標記的中央,將標記置於畫面中央。

步驟 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. 輕觸標記即可顯示資訊視窗。

步驟 4:新增搜尋點監聽器

根據預設,搜尋點會與其對應的圖示一併顯示在地圖上。搜尋點包括公園、學校、政府大樓等。地圖類型設為 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() 設定為標記,並使用 MarkerOptions,將 title 設為搜尋點的名稱。
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. 輕觸搜尋點以放置標記,並在資訊視窗中顯示搜尋點的名稱。

您可以透過多種方式自訂「Google 地圖」,讓地圖擁有獨特的外觀與風格。

您可以使用可用的 XML 屬性自訂 MapFragment 物件,方法就跟自訂其他片段一樣。但在這個步驟中,您可以使用 GoogleMap 物件的方法,自訂 MapFragment內容外觀和風格。

如要為地圖建立自訂樣式,您可以產生 JSON 檔案,以指定地圖上地圖項目的顯示方式。您無須手動建立這個 JSON 檔案。Google 提供 Google 地圖平台樣式精靈,您只要為圖像設定樣式,然後為 JSON 產生 JSON 檔案即可。在這項工作中,您會使用復古主題為地圖設定樣式,這表示地圖使用復古色彩,並新增彩色的道路。

步驟 1:建立地圖樣式

  1. 透過瀏覽器前往 https://mapstyle.withgoogle.com/
  2. 選取 [建立樣式]
  3. 選取 [復古]

  1. 按一下 [更多選項]

  1. 在「Feature type」(功能類型) 清單中,選取 [Road] (Road) > [填充]
  2. 將道路的顏色變更為您選擇的任何顏色 (例如粉紅色)。

  1. 按一下 [Finish]

  1. 從系統產生的對話方塊中複製 JSON 程式碼,並視需要將程式碼貼到純文字訊息中,以供下一個步驟使用。

步驟 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()。傳入會載入 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 的 if 陳述式為 false。如果樣式失敗,請列印剖析失敗的記錄。
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 模式,新的樣式應該會隨著復古顏色顯示,以及所選顏色的道路顯示。

步驟 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() 方法並未加入樣式,因此搜尋點標記依然為紅色。

自訂 Google 地圖的方式之一,就是在地圖上方繪圖。如果您想強調特定類型的位置 (例如熱門釣魚地點),這項技巧就相當實用。

  • 形狀:您可以在地圖中新增折線多邊形圓形
  • GroundOverlay 物件:區域疊加層是固定於地圖上的圖片。有別於標記,區域疊加層是以地球表面的方式 (而非螢幕) 顯示。旋轉、傾斜或縮放地圖會改變圖片的方向。當您想修正地圖上某個區域的單一圖片時,區域疊加層就非常實用。

步驟:新增區域疊加層

在這項工作中,您會新增 Android 形狀的區域疊加層,並在當中加入住家位置。

  1. 下載這個 Android 圖片,並將圖片儲存到 res/drawable 資料夾中。(請確認檔案名稱為 android.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 圖片顯示為疊加層。

使用者通常會使用 Google 地圖查看目前的位置。如要在地圖上顯示裝置位置,您可以使用位置資料圖層

位置資料層會在地圖上新增「我的位置」。使用者輕觸該按鈕後,地圖就會以裝置的位置為中心。如果裝置未移動,位置會以藍點標示;

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

步驟:要求位置存取權

只要一行程式碼,就能在「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 陣列為空白,請呼叫 enableMyLocation()
override fun onRequestPermissionsResult(
   requestCode: Int,
   permissions: Array<String>,
   grantResults: IntArray) {
   if (requestCode == REQUEST_LOCATION_PERMISSION) {
       if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
           enableMyLocation()
       }
   }
}
  1. 執行您的應用程式。系統會顯示對話方塊,讓您要求存取裝置的位置資訊。請直接授予權限。

地圖現在會透過藍點顯示裝置目前的所在位置。請注意,有一個位置按鈕。如果您將地圖移離位置並按下這個按鈕,地圖就會將地圖移回裝置的位置。

下載已完成程式碼研究室的程式碼。

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


或者,您也可以將存放區下載為 zip 檔案,然後解壓縮,然後在 Android Studio 中開啟該檔案。

下載 zip

  • 如要使用 Maps API,您必須具備 Google API 控制台中的 API 金鑰。
  • 在 Android Studio 中,使用 Google 地圖活動範本會產生一個 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 權限,您就可以透過設定 map.isMyLocationEnabled = true 來啟用位置追蹤功能。
  • 本程式碼研究室並未涵蓋其他相關資訊,但您可以透過 Google 街景服務提供地點的額外資訊 (該位置可瀏覽的全景相片)。

Android 開發人員說明文件:

參考說明文件:

如要瞭解本課程中其他程式碼研究室的連結,請參閱進階 Android 版 Kotlin 程式碼研究室到達網頁