app定位、地圖、座標系的那些坑


開發App時會遇到各種坑,本文分享我們在iOS/Android系統中定位和地圖中遇到的坑,以及攜程App的解決方案。

定位


定位即獲取用戶當前經緯度,iOS平臺都是通過系統SDK接口獲取的,因此所有App獲取定位及精度的能力是相同的,即使Google Maps、百度地圖、高德地圖這種專業地圖App也是如此;Android平臺由於Google Service被閹割,國內App通常是通過高德、百度等第三方SDK接口獲取定位信息,因此在定位能力和精度上會有些差異。

座標系問題

App定位遇到的第一個坑是座標系問題。目前常見的座標系有三種:地球座標(WGS84,國際公認座標),火星座標(GCJ02,國家標準,適用於高德百度地圖大陸+港澳部分、Google地圖大陸部分),百度座標(BD09,適用於百度地圖大陸+港澳臺部分)。座標系需要和地圖關連纔有意義,只有正確匹配地圖座標系的座標才能在該地圖上完美標識位置,否則就會存在偏移。另外對於旅行類App而言,經常需要根據用戶當前位置查詢周圍酒店或者其他POI信息,並且按距離排序,如果座標系不匹配,就會由於座標系偏移產生排序問題。

iOS系統上通過定位服務CLLocation相關接口獲取定位信息時,獲取的經緯度座標系是WGS84地球座標,如果直接將該座標系在iOS系統地圖中打點,會發現存在偏移,因爲iOS系統地圖查看國內時使用的是高德地圖數據(這裏有另一個坑,詳見下文),因此只接受GCJ02火星座標。如果使用高德或者百度iOS定位SDK中的接口,是可以直接獲得火星偏移後的座標的,由於App Size問題,攜程App沒有集成第三方SDK,而是通過近似偏移算法直接做偏移(自行Google『transform From WGS To GCJ』)。然而如果在iOS系統地圖中獲取當前位置,同時在國內,那麼獲取到的座標系直接是GCJ02火星座標系,這點需要小心。

Android系統上通常使用高德或者百度定位SDK獲取定位信息。高德SDK沒有座標系參數設定,在大陸和港澳地區獲取的座標系即爲GCJ02座標系,在臺灣和海外地區都是WGS84座標系;百度SDK可以自行設定座標系參數,即返回WGS84座標系,還是GCJ02座標系或者BD09座標系(注意BD09座標系只適用於百度地圖),如果設定的是GCJ02座標系,它在大陸+港澳臺地區獲取的座標系都是GCJ02座標系。

海外地圖(非大陸和非港澳臺地區)是沒有火星座標或者百度座標之說,都是標準的WGS84地球座標系。

精度問題

第二個常見的坑是定位精度問題,經常有用戶或者Boss反饋,爲什麼兩臺一樣的手機,獲取的當前位置不一樣?我明明在這個位置,爲什麼定位卻顯示在附件另一個位置,相差那麼遠?

這類問題的根源是手機不同定位方式導致的,通常手機定位方式有三種:

1. GPS:根據系統GPS模塊獲取經緯度,精度10-100米左右,限制是容易受環境影響,在室內幾乎不起作用。

2. 基站:根據運營商基站位置計算經緯度,精度1000-3000米左右,限制是定位較慢,精度差。

3. WIFI:根據周圍WIFI路由器位置計算經緯度,精度100-200米左右,限制是受周圍WIFI數量和分佈影響,需要打開手機WIFI開關。

如果用戶沒有打開WIFI開關,定位的精度會受到極大的影響,下圖是同一部iPhone手機在相同位置,百度地圖在打開或者關閉WIFI場景下的效果對比,直觀反映出是否打開WIFI開關對於定位精度的影響。攜程iOS App的用戶統計數據顯示37.1%在非WIFI情況下定位精度超過了1000米,因而用戶會感覺偏移很厲害。


打開WIFI

關閉WIFI

一定會有同學疑問,開車導航時周圍通常沒有WIFI,爲什麼地圖軟件可以精確的把用戶當前位置顯示在道路上。那是因爲在導航模式下,用戶的運動速度和方向信息是可以獲取的,導航算法會將用戶位置重新計算後定位在道路上,如果把車停在路邊,關閉WIFI,一樣有可能偏移很嚴重。

地圖


App地圖同樣存在座標系和精度問題。前面說過在地圖裏顯示座標點時,需要匹配正確的座標系,否則就會產生偏移。

iOS平臺的系統地圖就存在數據源地圖座標系導致的一個大坑,iOS系統地圖App以及系統地圖組件MKMapView的數據源分爲兩種:高德數據源和TomTom數據源。最坑的是iOS地圖使用的數據源和當前手機所處的位置是相關的:

如果手機在大陸地區,iOS地圖使用的是高德地圖數據源:此時用戶查看大陸和港澳臺地圖細節信息時,使用的是GCJ02火星座標系,同時地圖顯示精度很高,但是看海外地圖時,由於數據源問題精度就會很差(座標系是WGS84),例如下圖看新加坡,如果你要在地圖中顯示POI打點,效果可想而知。


iOS海外地圖

如果手機在港澳臺和海外地區,iOS地圖使用的是TomTom地圖數據源,該地圖匹配的是WGS84地球座標系,如果用戶在海外查看國內地圖,同時你的POI打點座標系是GCJ02火星座標系,那麼就會產生偏差;另外手機在港澳臺和海外地區時查看港澳臺和海外的地圖數據精度很好,然而查看國內地圖便會精度偏低。

因此要想在iOS地圖中正確打點,就需要先行判斷使用的地圖數據源,以及對應的座標系,同時使用的POI座標系務必與地圖座標系匹配,否則就會出現偏差。下圖是旅行類App顯示香港一家酒店的POI打點,可以看出除了攜程外其他App都有偏差,其中三家偏差的方式還是一樣的,原因應該是他們服務端僅保存了這家酒店的WGS84地球座標系座標。


POI顯示對比

Android平臺我們使用的是百度地圖(高德地圖情況相同),然而百度地圖在大陸+港澳臺地區的數據源精度是正常的,海外地區的精度就和iOS平臺下高德數據源在海外的精度類似,不夠詳盡(百度在日韓地區的地圖精度已經變好,數據源的精度提升確實需要一個過程)。我們的解決辦法是開發WebView版的Google地圖組件,載入ditu.google.cn,見下圖效果。


Android自定義WebView地圖

前面提到的iOS系統地圖精度問題我們也是用相同方法解決的,只是顯示時處理邏輯更復雜,人在國內看國外地圖,人在國外看國內地圖兩種情況就會使用自定義Google地圖替代,其他情況下繼續使用系統地圖。


iOS自定義WebView地圖

WebView版地圖雖然操作體驗比Native地圖差一些,但是顯示數據源精度高很多,對用戶價值更大。

綜述


App定位和地圖存在問題其實都是國內地理信息特殊標準導致的,我們只能使用一些tricky的方式解決,一切都是爲了部落,不對,爲了用戶:)

歡迎關注攜程無線技術公衆號『CtripMobile』:



文/hrchen(簡書作者)
原文鏈接:http://www.jianshu.com/p/f8224779ca63
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章