iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0
Mobile Development

Google Maps SDK for Android 與 GIS App 開發筆記系列 第 25

Day 25: Maps SDK for Android Utility 的運算工具與 Google Directions API Polyline Decoding

  • 分享至 

  • xImage
  •  

前言

今天剛好碰到一個有介接 Google Maps Directions API 的專案,赫然想到在 Maps SDK for Android Utility 上有一些工具程式在解析 Directions API 上很好用,那就藉著這次機會來介紹一下。

Maps SDK for Android Utility 的其它工具

在聊正題之前,先聊一下 Maps SDK for Android Utility 的其它工具。

其實除了前幾天介紹的那些東西,Maps SDK for Android Utility 還提供了不少的 Utility 能夠幫助開發者解析或運算空間資料。

如果要計算地圖上的距離或面積,可以看 SphericalUtil 這個類別,舉幾個例子來看:

  • SphericalUtil.computeArea(java.util.List<LatLng> path)
    • 計算面積
    • 單位為平方公尺
  • SphericalUtil.computeDistanceBetween(LatLng from, LatLng to)
    • 計算距離
    • 單位為公尺
  • SphericalUtil.computeHeading()
    • 計算兩個經緯度座標之間的航向/方向角
    • 單位為度數

待會要聊到資料解析會用到的是 PolyUtil,在後半段會詳細介紹,其他部分如果有需要更完整的說明可以參考 Java Doc

Google Maps Directions API

看到 Directions 這個單字可以略知一二,它就是 Google Maps App 上許多人常用的導航功能。

介紹

Directions API 目前只有提供 HTTPS 的服務,可以回傳 JSON 或 XML 格式的資料,資料將包含起點至終點的最佳路徑(最有效率與省時)、預估時間、距離、轉彎次數。(原則上你用手機 Google Maps 導航時,所看到的資訊幾乎都有。)

API 申請方式

如同 Day 6: Google Maps SDK–金鑰申請 中介紹過的,Directions API 的服務需要另外開通,且超過一定次數的呼叫會需要收取費用,使用上要特別留意。

金鑰的開通申請與 Maps SDK for Android 的步驟大同小異,在今天的介紹中就不贅述。

不過,要注意的是,Dirctions API 的金鑰要跟 Maps SDK 的分開申請,因為 Directions API 的 Key 只能透過 IP 位址做限制。

假設,API Key 已經有開啟 App 限制的話,如果有同時替這支 Key 啟用 Directions API,呼叫服務後會得到以下的錯誤訊息:

This IP, site or mobile application is not authorized to use this API key. Request received from IP address 111.251.85.249, with empty referer.

https://ithelp.ithome.com.tw/upload/images/20231008/20160271VkYCHsY22t.png

當然,以實際開發來說,最好的做法還是透過伺服器端去呼叫 Google Directions API 的服務,再將回應的結果傳給 App 端。

參數

API 的基本格式長這樣:

https://maps.googleapis.com/maps/api/directions/{outputFormat}?{parameters}
  • outputFormat 只有 jsonxml 兩種。
  • 必要的parameters 主要有以下這些
    • destination: 目的地
    • origin: 起點
    • key: 金鑰
    • 目的地與起點的資料格式相同,可以是經緯度、地址、Place ID

除了以上必要參數外,如果 App 有語系的需求,可以再加上 language 參數。

範例如下:

https://maps.googleapis.com/maps/api/directions/json?destination=Montreal&origin=Toronto&key=YOUR_API_KEY

回傳資料

以新北市某兩個地址的查詢結果為例,可以看到以下的回傳資料中有

  1. 兩點的 place id 與類型
  2. routes:包含導航邊界、起訖點位置、預估時間與距離、導航指示、路徑。
{
    "geocoded_waypoints": [
        {
            "geocoder_status": "OK",
            "place_id": "ChIJUTsDnNapQjQRdNvGQpJ-jRU",
            "types": [
                "street_address"
            ]
        },
        {
            "geocoder_status": "OK",
            "place_id": "ChIJUTsDnNapQjQRdNvGQpJ-jRU",
            "types": [
                "street_address"
            ]
        }
    ],
    "routes": [
        {
            "bounds": {
                "northeast": {
                    "lat": 25.0033493,
                    "lng": 121.4974714
                },
                "southwest": {
                    "lat": 25.0033493,
                    "lng": 121.4974714
                }
            },
            "copyrights": "Map data ©2022 Google",
            "legs": [
                {
                    "distance": {
                        "text": "1 公尺",
                        "value": 0
                    },
                    "duration": {
                        "text": "1 分鐘",
                        "value": 0
                    },
                    "end_address": "235台灣新北市中和區中山路二段250巷24號",
                    "end_location": {
                        "lat": 25.0033493,
                        "lng": 121.4974714
                    },
                    "start_address": "235台灣新北市中和區中山路二段250巷24號",
                    "start_location": {
                        "lat": 25.0033493,
                        "lng": 121.4974714
                    },
                    "steps": [
                        {
                            "distance": {
                                "text": "1 公尺",
                                "value": 0
                            },
                            "duration": {
                                "text": "1 分鐘",
                                "value": 0
                            },
                            "end_location": {
                                "lat": 25.0033493,
                                "lng": 121.4974714
                            },
                            "html_instructions": "走<b>中山路二段242巷</b>",
                            "polyline": {
                                "points": "}mrwCe~pdV"
                            },
                            "start_location": {
                                "lat": 25.0033493,
                                "lng": 121.4974714
                            },
                            "travel_mode": "DRIVING"
                        }
                    ],
                    "traffic_speed_entry": [],
                    "via_waypoint": []
                }
            ],
            "overview_polyline": {
                "points": "}mrwCe~pdV"
            },
            "summary": "中山路二段242巷",
            "warnings": [],
            "waypoint_order": []
        }
    ],
    "status": "OK"
}

但以上這些主要都是 JSON 資料的解析,重點其實是要看 polylineoverview_polyline 這兩個欄位中的神秘字串。

Polyline Encoding 解析

這串神秘的字串其實是 Polyline Encoding,是一種有損壓縮的字串格式,能讓我們將一串座標陣列轉換成單一字串。

如果要進一步瞭解他的轉換方式,可以查閱Polyline Encoding 的原理這份文件。

針對這個字串的解析方式,官方不建議自行寫工具去解析,而是使用 Utility 裡 PolyUtil.decode()

透過 PolyUtil.decode() 可以直接將

val encodedString = "{gsrCivj_Vw@@IECQCgHOaOAaCGe@GKQOWKSGq@e@pIMtMOlCB~EBbECnBDhI@`G?lA?lBErA@tB@bEIEoCA}GBuDDa@ZG`D_@|Eo@|@@`G]bESvF[|@Ip@OLKdAzAbAjA~DtFdA|AjAxAnAtAzAzAtApA~CdCtA|@jDjBzEtCVLR_@tDyIzD{IpG}Mj@{ARH\y@nCuFr@kBl@}A\m@l@eAJQ~@Wj@ILHNHrCzA~@j@JUl@kAtBlA`CtAVm@"

這樣的一段 Polyline Encoding 字串,還原成完整的經緯度陣列。

val latLngList = PolyUtil.decode(encodedString)
// Output: LatLngList size = 77

https://ithelp.ithome.com.tw/upload/images/20231008/20160271avWcwIWCrN.png

除了解碼外,Utility 也提供編碼的方法 PolyUtil.encode(latLngList),可以將經緯度陣列轉為 Polyline Encoding 的字串。

參考資料

小結

以上就是今天的內容,其實 Maps SDK for Android Utility 中有許多實用的工具程式,在開發上可以多多利用,這樣就不用重複造輪子啦~

鐵人賽挑戰倒數中,繼續努力,明天見!!/images/emoticon/emoticon08.gif


上一篇
Day 24: Maps SDK for Android Utility–LayerManager
下一篇
Day 26: Geofence 地理圍欄
系列文
Google Maps SDK for Android 與 GIS App 開發筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言