Windows Phone 8–Runtime Location API - 1
在Windows Phone裡要做Background Service的方式,除了Background Agent、Background Audio、Background FileTransfer之外,
到了WP8針對Location的部分也提供允許背景執行的任務,這樣一來就做可以做例如:背景記錄慢跑的路線…這類型的應用。
對於Location的技術用於App上,可透過GPS、Wi-Fi與Cellular來取得座標搭配後端的Web Service或其他網路服務,
讓用戶得可location相關的整合劇情。
Windows Phone提供了二種APIs提供開發Location相關的服務,往下便針對這二個APIs加以介紹:
〉Windows Phone Runtime Location API:
屬於新的API在WP8開始才有支援,主要提供幾個重點特性:
a. 適用於Native Code與管理型的應用程式使用。例如:如果您寫Direct3D或管粴類型的應用程式均建議使用該API。
b. 對於一次性(one-shot)位置取得提供更大的支援。
API允許應用程式設指定位置的相關特性,例如:結果所需要的精準度、期望獲取的結果、平衡精準度與回應的最長時間;
需注意,如果實作的是Tracking(路線追踨),不要使用一次性(one-shot)位置取得,這樣可以有比較好使用者體驗,
也可以讓電力的使用比較少;
c. 在做Tracking location時,應用程式可以設定在固定的時間間隔或是位置移動多少距離(從上一個請求到目前移動的位置距離)後,
請求取得location的更新。
d. 該API雖然在Windows 8上也有,但API仍有些差距,但支援了大部分的功能。
〉.NET Location API:
該API與Windows Phone Runtime Location API不一樣,它是專用於Windows Phone上。所以該API同時也支援了WP 7.1,
這樣一來就可以將既有的App同時支援二個平台,不過未來會比較建議使用Windows Phone Runtime Location API。
相關內容可以參考<Windows Phone 7 - 學習Location Service與Map地圖>或<.NET Location API for Windows Phone 8>。
本篇將針對Windows Phone Runtime Location API加以介紹與說明。
[注意]
a. 要操作Location API別忘了至WMAppManifest.xml加上必要的<Capabilities/>的宣告:ID_CAP_LOCATION 。
b. 要記得在App中加上宣告該App將會取得用戶的Location資料,並彈出對話框讓用戶知道,並且實作管理Location權限的管理。
(1) 利用API取得電話目前所在的Location資訊;
這部分介紹是做用於Check-in、利用Location-based資料進行搜尋…等,一次性使用的情境,如果您的App是這類的應用,
就可以參考這個部分的介紹。以下是簡單作法的說明:
a. 宣告必要的Capabilities,並在OnNavigatedTo時判斷是否要宣告使用座標資訊提示讓用戶知道;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
//在進入畫面時即要宣告使用座標資訊
if (IsolatedStorageSettings.ApplicationSettings.Contains("AllowLocation") == false)
{
// 代表未顯示過宣告該App會使用location資訊讓用戶資料
MessageBoxResult result =
MessageBox.Show("是否允許本應用程式將萬您電話的地理座標資訊?",
"Location",
MessageBoxButton.OKCancel);
// 保存用戶選擇的值
if (result == MessageBoxResult.OK)
IsolatedStorageSettings.ApplicationSettings["AllowLocation"] = true;
else
IsolatedStorageSettings.ApplicationSettings["AllowLocation"] = false;
//保存設定值
IsolatedStorageSettings.ApplicationSettings.Save();
}
}
這個是必要的,而且要額外提供讓用戶可以管理該權限的功能,不然送審至DevCenter會被退件。
b. 透過Geolocator物件設定DesiredAccuracyInMeters屬性,呼叫GetGeopositionAsync非同步取得座標資訊;
private async void OneShotLocation_Click(object sender, EventArgs e)
{
if (bool.Parse(IsolatedStorageSettings.ApplicationSettings["AllowLocation"].ToString()) == false)
//代表用戶不允許使用他的座標資訊
return;
//初始化Geolocator物件,並設定DesiredAccuracyInMeters
Geolocator geolocator = new Geolocator();
//設定當從Location service返回的值以m為單位所需要精準度
geolocator.DesiredAccuracyInMeters = 50;
try
{
//要求取得Location資訊,並且設定最大暫存時間長度與timeout時間
Geoposition geoposition = await geolocator.GetGeopositionAsync(
maximumAge: TimeSpan.FromMinutes(5),
timeout: TimeSpan.FromSeconds(10));
LatitudeTextBlock.Text = geoposition.Coordinate.Latitude.ToString("0.00");
LongitudeTextBlock.Text = geoposition.Coordinate.Longitude.ToString("0.00");
}
catch (Exception ex)
{
if ((uint)ex.HResult == 0x80004004)
{
// the application does not have the right capability or the location master switch is off
StatusTextBlock.Text = "location is disabled in phone settings.";
}
//else
//{
// // something else happened acquring the location
//}
}
}
這個部分多設定最大座標資訊保存時間與取得座標的timeout時間,讓座標資訊取得可以有較好的回應。
上述僅擷錄了C#的部分,更詳細的內容可以參考<How to get the phone's current location for Windows Phone 8>。
(2) 持續更新手機的Location資訊;
如果需要在App在前景執行時,持續取得座標資訊,則需要考慮以下的作法。但需注意持續取得座標資訊將使用大量電力。
延用(1)的程式範例,針對Geolocator的幾事件加以處理進行控制與更新畫面中的值。
a. 為新的按鈕註冊啟動追蹤,並且註冊了相關的事件:
private void TrackLocation_Click(object sender, EventArgs e)
{
if (bool.Parse(IsolatedStorageSettings.ApplicationSettings["AllowLocation"].ToString()) == false)
//代表用戶不允許使用他的座標資訊
return;
if (tracking == false)
{
//啟動持續定位追蹤功能
geolocator = new Geolocator();
//設定精準度品質
geolocator.DesiredAccuracy = PositionAccuracy.High;
//設定座標移動間距多少了觸發事件,單位公尺
geolocator.MovementThreshold = 100;
//註冊監測狀態與座標變動的事件
geolocator.PositionChanged += geolocator_PositionChanged;
geolocator.StatusChanged += geolocator_StatusChanged;
tracking = true;
TrackLocationButton.Content = "stop tracking";
}
else
{
tracking = false;
geolocator.StatusChanged -= geolocator_StatusChanged;
geolocator.PositionChanged -= geolocator_PositionChanged;
geolocator = null;
TrackLocationButton.Content = "track location";
StatusTextBlock.Text = "stopped";
}
}
始化Geolocator物件時並給予了精準度程度與移動間距,因此,當設備從上一個位置開始移動超過指定的移動間距,
將會觸發事件以請求得到新的座標資訊。需要註冊StatusChanged與PositionChanged來注意目前Geolocator狀態與座標的改變。
b. 註冊依狀態改變與座標隨著用戶移動的距離來觸發擋件,進一步取得值來顯示與畫面:
void geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
{
string status = "";
switch (args.Status)
{
case PositionStatus.Disabled:
// 應用程式沒有能式操作location功能或被關閉
status = "location is disabled in phone settings";
break;
case PositionStatus.Initializing:
// geolocator初始化進行tracking operation
status = "initializing";
break;
case PositionStatus.NoData:
// location service沒有可用正確座標
status = "no data";
break;
case PositionStatus.Ready:
// location service 已準備開始建立geopositions經由換指定的參數
status = "ready";
break;
case PositionStatus.NotAvailable:
status = "not available";
// not used in WindowsPhone, Windows desktop uses this
// value to signal that there is no hardware capable to acquire location information
break;
case PositionStatus.NotInitialized:
// the initial state of the geolocator, once the tracking operation
// is stopped by the user the geolocator moves back to this state
break;
}
Dispatcher.BeginInvoke(() =>
{
StatusTextBlock.Text = status;
});
}
註冊StatusChanged的事件可觀查目前取得Location的狀態,例如:Disabled代表用戶未允許應用程式操作座標權限…等。
void geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
//隨著移動的座標改變修改畫面內容
Dispatcher.BeginInvoke(() =>
{
LatitudeTextBlock.Text = args.Position.Coordinate.Latitude.ToString("0.00");
LongitudeTextBlock.Text = args.Position.Coordinate.Longitude.ToString("0.00");
});
}
該段程式碼內容擷錄於<How to continuously track the phone's location for Windows Phone 8>裡的內容。其中對於StatusChanged與
PositionChanged事件的處理才是重點,因為App既是做持續取得座標的資訊,必須讓用戶有感該App是有在運作的,不然很容易被退件。
從上述得知了幾個重要的類別與事件,往下先解釋這幾個元素的功能。
提供取得目前所在的座標資訊的運作元件。主要透過該類別提供的屬性與事件加以設定擷取座標資訊的參數,
另外,搭配註冊處理StatusChanged與PositionChanged事件來提供具反應的運作。
類型 | 名稱 | 說明 |
屬性 | DesiredAccuracy | 設定/取得Geolocator提供座標資訊的精準度等級。
搭配:PositionAccuracy enumeration使用, ‧Default:最佳化電力、效能與其他成本的節省; ‧High:盡可能提供最準確的報告。 可能會降低系統的性能,應該只在必要時使用。 |
DesiredAccuracyInMeters | 獲取或設置從位置服務返回的數據以米為單位所需的精度。
未給予值時,視為default。 根據給予的值有所不同: ‧大於或等於100米,則為default; ‧小於100米,則視為high; 不可以給予null值。 |
|
LocationStatus | 取得識別目前Geolocator的可用性以識別是否有辦法取得座標資訊。 | |
MovementThreshold | 設定/取得移動距離。以公尺(米)為單位,從最後一個PositionChanged擷取的座標至目前移動的座標差距。
|
|
ReportInterval | 位置更新的要求最小時間間隔,單位為毫秒。如果您的應用程序需要經常更新,設置這個值,以便該位置提供者可以通過僅在需要時計算位置的節省電力。 | |
方法 | GetGeopositionAsync() | 開始非同步擷取設備現在的座標資訊。 |
GetGeopositionAsync(TimeSpan, TimeSpan) | 開始非同步擷取設備現在的座標資訊。搭配二個參數:
‧maximunAge:緩存座標資訊的最大時間。 ‧timeout:擷取超時的時間。 |
|
事件 | PositionChanged | 當座標被更新時所觸發的事件。第一次使用Geolocator物件時要記得宣告讓用戶知道,才能通過審查<Guidelines for devices that access personal data>。
主要過事件參數PositionChangedEventArgs進行座標資訊的取得與操作。 【注意】 Geolocator在連線待機時永遠可以被實例化,但Geolocator在叫調用GetGeopositionAsync()時,超過7秒沒有回應時,PositionChanged事件將永遠不會被呼叫,而StatusChanged將收到一個NoData的狀態。 |
StatusChanged | 當Geolocator狀態改變時,所觸發的事件。例如:像Geolocator擷取到可用資料時觸發事件通知、或是初始化的過程…等狀態。
主要透過事件參數StatusChangedEventArgs進行狀態的取得與操作。 【注意】 Geolocator在連線待機時永遠可以被實例化,但Geolocator在叫調用GetGeopositionAsync()時,超過7秒沒有回應時,PositionChanged事件將永遠不會被呼叫,而StatusChanged將收到一個NoData的狀態。 具有的PositionStatus清單: ‧Ready ‧Initializing ‧NoData ‧Disabled ‧NotInitialized ‧NotAvailable |
呈現由GetGeopositionAsync()取得的結果,其中可能包括了Latitude、Longitude或civic address資料。
二個重要的屬性如下:
名稱 | 說明 |
CivicAddress | 唯讀。取得包含Civic Address相關的座標資訊。
屬性均是唯讀,包括: ‧City ‧Country ‧PostalCode ‧State ‧Timestanp |
Coordinate | 唯讀。取得包含Latitude、Longitude相關的座標資訊。
屬性均是唯讀,包括: ‧Accuracy:座標精準度,以公尺(米)為主; ‧Latitude ‧Longitude ‧Point ‧PositionSource ‧SatelliteData ‧Speed ‧Timstanp |
[補充]
‧PositionStatus enumeration:
Member | Value | Description |
Ready | ready | 0 | 座標資訊是可用的。 |
Initializing | initializing | 1 | 代表Location Provider正在初始化。例如:GPS接收器尚未接收完畢所需衛星數量的資料源時。 |
NoData | noData | 2 | 代表無法從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 | Location Provider不可使用。這狀態代表用戶未允許應用程式取得座標的權限。 |
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. |
======
以上是介紹WP8提供與Win8 Store App使用相同取得Location能力的APIs。
下一篇將介紹如何搭配背景執行的方式來實作像是runing軌跡的App應用。
希望該篇文章對太家有所幫助,謝謝。
References:
‧How to get the phone's current location for Windows Phone 8
‧How to continuously track the phone's location for Windows Phone 8
‧How to run location-tracking apps in the background for Windows Phone 8
‧Location Sample for Windows Phone 8
‧NET Location API for Windows Phone 8.
‧Acquiring a single Geoposition in Windows Phone 8
‧Windows Phone 8 and Windows 8 platform comparison
‧Using the Location API in Your Windows Phone 8 Applications
‧Maps in Windows Phone 8 and Phone toolkit: a winning team – Part 1
‧Maps in Windows Phone 8 and Phone toolkit: a winning team – Part 2