Windows Phone - 利用GeoLocation取得對應的Address - 1
這篇介紹二個比較常用在WP裡將Geolocation的座標轉換成對應地址的用法,
本篇支援的是Windows Phone 7.5、8.0、8.1(Silverlight App)所開發的App使用,如果您開發的8.1(XAML App)的話,
請另外參考<How to get locations and addresses>的說明。
[注意]
1. 記得要勾選WMAppManifest.xml中操作Location需要的Capabilities:
2. 在程式裡面向用戶宣告要使用定位的功能,才不會送Dev Center審核時被退件:
〉利用ReverseGeocodeQuery將座標轉換成地址:
首先,先了解怎麼取得目前座標,在WP 7.5/8.0支援二種取得座標的方式,分別說明如下:
》利用GeoCoordinateWatcher取得手機所在座標:
GeoCoordinateWatcher是比較舊的寫法,從過去7.5的時代就存在的使用方式,但它非常容易操作,
詳細操作方式可參考<Windows Phone 7 - 學習Location Service與Map地圖>的說明,裡面分別說明了如何設定
GeoCoordinateWatcher運作的參數、GeoCoordinate為何物…等。簡單的操作程式如下:
GeoCoordinateWatcher gLocationWatcher = null;
GeoPosition<GeoCoordinate> gPosition = null;
private void EnableGeoLocationWatcher()
{
gLocationWatcher = new GeoCoordinateWatcher();
gLocationWatcher.PositionChanged += LocationWatcher_PositionChanged;
gLocationWatcher.Start();
}
void LocationWatcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
gPosition = e.Position;
}
但要記得在OnNavigatedFrom記得釋放掉GeoCoordinateWatcher的使用與事件註冊,才不會造成下一次進來重覆建立。
》利用Geolocator取得手機所在座標:
這是WP 8.0開始支援新的取得座標的方式 ,主要利用Geolocator新的非同步操作方式來取得座標,以下將詳細說明:
(a) Geolocator:
可用來存取目前的地理位置。重要事件與屬性如下:
類型 | 名稱 | 說明 | |||||||||||||||||||||
Events | PositionChanged | 當監測到手機的座標改變時所觸發的事件,觸發條件依照MovementThreshold所設定值而定。 | |||||||||||||||||||||
StatusChanged | 當Geolocator的狀態改變時所觸發的事件,Geolocator的狀態會影響取得座標的改變。 | ||||||||||||||||||||||
Methods | GetGeopositionAsync | 啟動非同步擷取該設備現在的座標。 | |||||||||||||||||||||
GetGeopositionAsync(TimeSpan,TimeSpan) | 啟動非同步擷取該設備現在的座標,其二個參數:
maximumAge:設定cache座標資料的最大時效。以 100 毫微秒為單位表示的時間段。 timeout:非同步擷取時超過多少時間算timeout。以 100 毫微秒為單位表示的時間段。 |
||||||||||||||||||||||
Properties | DesiredAccuracy | (Read/write) 設定Geolocator的精度級別來提供位置更新。分成Default與High兩種。
相對的High需要更多的電力。 |
|||||||||||||||||||||
(Read/write) 設定或取得從Geolocator回傳精準級別為多少公尺為準。
DesiredAccuracyInMeters 屬性提供更多的細微性和控制的位置結果的準確性。大多數應用程式可以簡單地使用 DesiredAccuracy 屬性。 |
|||||||||||||||||||||||
LocationStatus | (Read-only) 取得Geolocator提供定位服務的狀態。舉例值,包括:
|
||||||||||||||||||||||
MovementThreshold | (Read/write) 設定/取得移動多少距離(以公尺為單位)後需要觸發離上一個座標差異的PositionChanged事件。 | ||||||||||||||||||||||
ReportInterval | (Read/write) 設定回傳定位狀態的最小時間區間(毫秒為單位)。如果App需要頻繁的更新,設定該屬性值愈小即可。 |
接著來看怎麼操作Geolocator類別取得座標:
private Geolocator geolocator = null;
private Geoposition gCurrentGeoposition = null;
private async void GetGeoLocationByeGeolocator()
{
geolocator = new Geolocator();
geolocator.PositionChanged += geolocator_PositionChanged;
geolocator.StatusChanged += geolocator_StatusChanged;
//設定geolocator在發現前一個座標與現在座標差距300公尺就觸發PositionChanged
geolocator.MovementThreshold = 300;
gCurrentGeoposition = await geolocator.GetGeopositionAsync();
string tLocation = string.Format("lat: {0};\r\nlng: {1}",
gCurrentGeoposition.Coordinate.Latitude.ToString("0.000000"),
gCurrentGeoposition.Coordinate.Longitude.ToString("0.000000"));
MessageBox.Show(tLocation);
}
void geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
{
switch (args.Status)
{
case PositionStatus.Disabled:
//代表App忘記開啟取得Location、MAP的權限
break;
case PositionStatus.Initializing:
//目前Geolocator正在初始化
break;
case PositionStatus.NoData:
//代表無法取得座標資訊
break;
case PositionStatus.NotAvailable:
//代表該API不支援現在設備的Windows版本
break;
case PositionStatus.NotInitialized:
//代表Geolocator未被請求註冊事件或請求座標
break;
case PositionStatus.Ready:
//代表Geolocator可以正常使用
break;
}
}
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
//當有座標改變時,要記得更新現在cache的座標資訊
gCurrentGeoposition = args.Position;
}
(b) Geoposition:
包含緯度和經度資料或市政位址資料的位置。與GeoCoordinate不太一樣,它包裝了更多的資訊內容。主要二個屬性都是Read-only,分別如下:
(b-1) CivicAddress:
記錄該座標對應的civic address(市政地址)。
Property | Access type | Description |
City | Read-only | The name of the city.Description |
Country | Read-only | The name of the country, represented by using a two-letter ISO-3166 country code. |
PostalCode | Read-only | The postal code of the current location. |
State | Read-only | The name of the state or province. |
Timestamp | Read-only | The time at which the location data was obtained. |
(b-2) Coordinate:
記錄該座標的詳細資訊,包括latitude、longitude、Heading、Accuracy…等。如下:
Property | Access type | Description |
Accuracy | Read-only | The accuracy of the location in meters. |
Altitude | Read-only | Altitude may be altered or unavailable after Windows 8.1 and Windows Phone 8.1. Instead, use Geocoordinate.Point.The altitude of the location, in meters. |
AltitudeAccuracy | Read-only | The accuracy of the altitude, in meters. |
Headling | Read-only | The current heading in degrees relative to true north. |
Latitude | Read-only | Latitude may be altered or unavailable after Windows 8.1 and Windows Phone 8.1. Instead, use Geocoordinate.Point. The latitude in degrees. |
Longitude | Read-only | Longitude may be altered or unavailable after Windows 8.1 and Windows Phone 8.1. Instead, use Geocoordinate.Point.The longitude in degrees. |
Point | Read-only | The location of the Geocoordinate. |
PositionSource | Read-only | Gets the source used to obtain a Geocoordinate. |
PositionSourceTimestamp | Read-only | Gets the time at which the associated Geocoordinate position was calculated. |
SatelliteData | Read-only | Gets information about the satellites used to obtain a Geocoordinate. |
Speed | Read-only | The speed in meters per second. |
Timestamp | Read-only | The system time at which the location was determined. |
以上說明了取得座標的方式,接下來說明怎麼拿Geocoordinate中的latitude與longitude轉換成
(c) ReverseGeocodeQuery:
表示反向地理編碼查詢物件。幾個重要的屬性與事件:
類型 | 名稱 | 說明 | ||||||||
Properties | GeoCoordinate | Gets or sets the coordinates to be used in the reverse geocode query. | ||||||||
IsBusy | Gets a value that indicates whether the query is busy gathering results.
如果Busy == true,再下一次Query它會被Panding,建議加上Busy的判斷。 |
|||||||||
Methods | CancelAsync | Cancels the query. | ||||||||
CheckThread | Checks if the current thread is on a UI thread. | |||||||||
OnQueryCompleted | Called when the query completes running. | |||||||||
QueryAsync | Starts the query. | |||||||||
Events | QueryCompleted | Occurs when the query completes running.
需注意幾個QueryCompletedEventArgs (e.Error.HResult)的錯誤代碼:
|
使用方式如下:
/// <summary>
/// 搜尋目前座標為地址。
/// </summary>
private void GeoLocationToAddress()
{
ReverseGeocodeQuery tQuery = new ReverseGeocodeQuery();
tQuery.GeoCoordinate = new (gCurrentGeoposition.Coordinate.Latitude, gCurrentGeoposition.Coordinate.Longitude);
tQuery.QueryCompleted += (s, e) =>
{
try
{
if (e.Error != null)
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("目前座標無法轉換成地址資訊");
});
}
else
{
//由於成功取得會有多個,需要用集合裝起來
List<MapLocation> locations;
locations = e.Result as List<MapLocation>;
Dispatcher.BeginInvoke(() =>
{
//取得第一個為最準確的座標資訊
MapAddress tAddress =locations.FirstOrDefault().Information.Address;
MessageBox.Show(string.Format("{0} {1} {2}", tAddress.City, tAddress.District, tAddress.Street));
tAddress = null;
});
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
};
tQuery.QueryAsync();
}
可得知查詢的結果可能存在多筆資料,這些資料被利用MapLocation類別包裝起來,但只要擷取第一個MapLocation即可以得到地址資訊。
======
使用座標轉換成地址對於很多App的使用情境是非常重要的,例如:打卡、分享座標…等,
所以整理在WP中可使用ReverseGeocodeQuery與Google API(Windows Phone - 利用GeoLocation取得對應的Address - 2)兩種的操作方式,
另外也補充了在WP中取得GeoLocation的方式,希望對大家有所幫助。
References:
》How to get locations and addresses (8.1)
》How to Reverse Geocode a Location to an Address on Windows Phone 7 (利用Bing Map API)
》Using ReverseGeocodeQuery for Windows Phone 8
》Google Geocoding API & The Google Maps Geolocation API
》Windows Phone ReverseGeocoding to get Address from Lat and Long
》Windows Phone 8: get current Address -Data (from your current location)
》Windows Phone - 取得圖像中的GeoLocation資訊
》Windows Phone 7 - 使用Google Map API將地址轉成座標