Windows Phone - 利用GeoLocation取得對應的Address - 1

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:

    image

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需要更多的電力。
 

DesiredAccuracyInMeters

(Read/write) 設定或取得從Geolocator回傳精準級別為多少公尺為準。
DesiredAccuracyInMeters 屬性提供更多的細微性和控制的位置結果的準確性。大多數應用程式可以簡單地使用 DesiredAccuracy 屬性。
  LocationStatus (Read-only) 取得Geolocator提供定位服務的狀態。舉例值,包括:
Member Value Description
Ready | ready 0 Location data is available.
Initializing | initializing 1 The location provider is initializing. This is the status if a GPS is the source of location data and the GPS receiver does not yet have the required number of satellites in view to obtain an accurate position.
NoData | noData 2

No location data is available from any location provider.

LocationStatus will have this value if the application calls GetGeopositionAsync or registers an event handler for the PositionChanged event, before data is available from a location sensor.

Once data is available LocationStatus transitions to the Ready state.

Disabled | disabled 3 The location provider is disabled. This status indicates that the user has not granted the application permission to access location.
NotInitialized | notInitialized 4 An operation to retrieve location has not yet been initialized. LocationStatus will have this value if the application has not yet called GetGeopositionAsync or registered an event handler for the PositionChanged event.
NotAvailable | notAvailable 5 The Windows Sensor and Location Platform is not available on this version of Windows.
  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)的錯誤代碼:

HResult

Symbolic Code

0x80041B58

EErrorBadLocation

0x80041B57

EErrorIndexFailure

0x80041B56

EErrorCancelled

使用方式如下:

/// <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

Windows Phone Runtime API

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將地址轉成座標

存取個人資料裝置適用的指導方針

 

Dotblogs Tags: