取得使用者的位置
注意
MapControl 和地圖服務要求地圖驗證金鑰,稱為 MapServiceToken。 如需取得和設定地圖驗證金鑰的詳細資訊,請參閱要求地圖驗證金鑰。
尋找使用者的位置,並回應位置中的變更。 存取使用者的位置是由 設定 應用程式中的隱私權設定所管理。 本主題也會示範如何檢查您的應用程式是否有權存取使用者的位置。
秘訣 若要深入瞭解如何在應用程式中存取使用者的位置,請從 GitHub 上的 Windows-universal-samples 存放庫 下載下列範例。
啟用位置功能
- 在 方案總管 中,按兩下 package.appxmanifest,然後選取 [功能] 索引標籤。
- 在 [功能] 清單中,核取 [位置] 的方塊。 這會將
location
裝置功能新增至套件指令清單檔。
<Capabilities>
<!-- DeviceCapability elements must follow Capability elements (if present) -->
<DeviceCapability Name="location"/>
</Capabilities>
取得目前的位置
本節說明如何使用 Windows.Devices.Geolocation 命名空間中的 API 來偵測使用者的地理位置。
步驟 1:要求存取使用者的位置
除非您的應用程式具有粗略的位置功能(請參閱附注),否則您必須使用 RequestAccessAsync 方法來要求存取使用者的位置,才能嘗試存取位置。 您必須從UI線程呼叫 RequestAccessAsync 方法,而且您的應用程式必須位於前景。 在使用者授與應用程式許可權之前,您的應用程式將無法存取使用者的位置資訊。*
using Windows.Devices.Geolocation;
...
var accessStatus = await Geolocator.RequestAccessAsync();
RequestAccessAsync 方法會提示使用者存取其位置的許可權。 使用者只會提示一次(每個應用程式)。 第一次授與或拒絕許可權之後,這個方法就不會再提示使用者提供許可權。 若要協助使用者在提示之後變更位置許可權,建議您提供位置設定的連結,如本主題稍後所示。
注意:粗略的位置功能可讓您的應用程式取得刻意模糊化(不精確)的位置,而不需取得使用者的明確許可權(不過,系統範圍的位置切換仍 必須開啟)。 若要瞭解如何在應用程式中利用粗略的位置,請參閱 Geolocator 類別中的 AllowFallbackToConsentlessPositions 方法。
步驟 2:取得使用者的位置,並註冊位置許可權的變更
GetGeopositionAsync 方法會執行目前位置的一次性讀取。 在這裡,switch 語句會與 accessStatus 搭配使用,只有在允許存取使用者的位置時才會採取行動。 如果允許存取使用者的位置,程式代碼會 建立 Geolocator 對象、註冊位置許可權的變更,以及要求使用者的位置。
switch (accessStatus)
{
case GeolocationAccessStatus.Allowed:
_rootPage.NotifyUser("Waiting for update...", NotifyType.StatusMessage);
// If DesiredAccuracy or DesiredAccuracyInMeters are not set (or value is 0), DesiredAccuracy.Default is used.
Geolocator geolocator = new Geolocator { DesiredAccuracyInMeters = _desireAccuracyInMetersValue };
// Subscribe to the StatusChanged event to get updates of location status changes.
_geolocator.StatusChanged += OnStatusChanged;
// Carry out the operation.
Geoposition pos = await geolocator.GetGeopositionAsync();
UpdateLocationData(pos);
_rootPage.NotifyUser("Location updated.", NotifyType.StatusMessage);
break;
case GeolocationAccessStatus.Denied:
_rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);
LocationDisabledMessage.Visibility = Visibility.Visible;
UpdateLocationData(null);
break;
case GeolocationAccessStatus.Unspecified:
_rootPage.NotifyUser("Unspecified error.", NotifyType.ErrorMessage);
UpdateLocationData(null);
break;
}
步驟 3:處理位置許可權中的變更
Geolocator 物件會觸發 StatusChanged 事件,指出使用者的位置設定已變更。 該事件會透過自變數的 Status 屬性傳遞對應的狀態(屬於 PositionStatus 類型)。 請注意,這個方法不會從UI線程呼叫,而且 Dispatcher 物件會叫用UI變更。
using Windows.UI.Core;
...
async private void OnStatusChanged(Geolocator sender, StatusChangedEventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// Show the location setting message only if status is disabled.
LocationDisabledMessage.Visibility = Visibility.Collapsed;
switch (e.Status)
{
case PositionStatus.Ready:
// Location platform is providing valid data.
ScenarioOutput_Status.Text = "Ready";
_rootPage.NotifyUser("Location platform is ready.", NotifyType.StatusMessage);
break;
case PositionStatus.Initializing:
// Location platform is attempting to acquire a fix.
ScenarioOutput_Status.Text = "Initializing";
_rootPage.NotifyUser("Location platform is attempting to obtain a position.", NotifyType.StatusMessage);
break;
case PositionStatus.NoData:
// Location platform could not obtain location data.
ScenarioOutput_Status.Text = "No data";
_rootPage.NotifyUser("Not able to determine the location.", NotifyType.ErrorMessage);
break;
case PositionStatus.Disabled:
// The permission to access location data is denied by the user or other policies.
ScenarioOutput_Status.Text = "Disabled";
_rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);
// Show message to the user to go to location settings.
LocationDisabledMessage.Visibility = Visibility.Visible;
// Clear any cached location data.
UpdateLocationData(null);
break;
case PositionStatus.NotInitialized:
// The location platform is not initialized. This indicates that the application
// has not made a request for location data.
ScenarioOutput_Status.Text = "Not initialized";
_rootPage.NotifyUser("No request for location is made yet.", NotifyType.StatusMessage);
break;
case PositionStatus.NotAvailable:
// The location platform is not available on this version of the OS.
ScenarioOutput_Status.Text = "Not available";
_rootPage.NotifyUser("Location is not available on this version of the OS.", NotifyType.ErrorMessage);
break;
default:
ScenarioOutput_Status.Text = "Unknown";
_rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
break;
}
});
}
回應位置更新
本節說明如何使用 PositionChanged 事件,在一段時間內接收使用者位置的更新。 因為使用者可以隨時撤銷對位置的存取權,所以請務必呼叫 RequestAccessAsync,並使用 StatusChanged 事件,如上一節所示。
本節假設您已經啟用位置功能,並從前景應用程式的 UI 線程呼叫 RequestAccessAsync。
步驟 1:定義報告間隔並註冊位置更新
在此範例中,switch 語句會與 accessStatus 搭配使用,只有在允許存取使用者的位置時才會採取行動。 如果允許存取使用者的位置,程式代碼會 建立 Geolocator 物件、指定追蹤類型,以及註冊位置更新。
Geolocator 物件可以根據位置變更(以距離為基礎的追蹤)或時間變更來觸發 PositionChanged 事件(定期型追蹤)。
- 針對以距離為基礎的追蹤,請設定 MovementThreshold 屬性。
- 針對定期型追蹤,請設定 ReportInterval 屬性。
如果兩個屬性都未設定,則會每隔 1 秒傳回一個位置(相當於 ReportInterval = 1000
)。 在這裡,會使用 2 秒 (ReportInterval = 2000
) 報告間隔。
using Windows.Devices.Geolocation;
...
var accessStatus = await Geolocator.RequestAccessAsync();
switch (accessStatus)
{
case GeolocationAccessStatus.Allowed:
// Create Geolocator and define perodic-based tracking (2 second interval).
_geolocator = new Geolocator { ReportInterval = 2000 };
// Subscribe to the PositionChanged event to get location updates.
_geolocator.PositionChanged += OnPositionChanged;
// Subscribe to StatusChanged event to get updates of location status changes.
_geolocator.StatusChanged += OnStatusChanged;
_rootPage.NotifyUser("Waiting for update...", NotifyType.StatusMessage);
LocationDisabledMessage.Visibility = Visibility.Collapsed;
StartTrackingButton.IsEnabled = false;
StopTrackingButton.IsEnabled = true;
break;
case GeolocationAccessStatus.Denied:
_rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);
LocationDisabledMessage.Visibility = Visibility.Visible;
break;
case GeolocationAccessStatus.Unspecified:
_rootPage.NotifyUser("Unspecificed error!", NotifyType.ErrorMessage);
LocationDisabledMessage.Visibility = Visibility.Collapsed;
break;
}
步驟 2:處理位置更新
Geolocator 物件會觸發 PositionChanged 事件,指出使用者的位置已變更或經過時間,視您設定的方式而定。 該事件會透過自變數的Position屬性(屬於Geoposition類型)傳遞對應的位置。 在此範例中,不會從UI線程呼叫 方法,而 Dispatcher 物件會叫用UI變更。
using Windows.UI.Core;
...
async private void OnPositionChanged(Geolocator sender, PositionChangedEventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
_rootPage.NotifyUser("Location updated.", NotifyType.StatusMessage);
UpdateLocationData(e.Position);
});
}
變更位置隱私權設定
如果位置隱私權設定不允許您的應用程式存取使用者的位置,建議您提供 設定 應用程式中位置隱私權設定的便利連結。 在此範例中,會使用 Hyperlink 控制項巡覽至 ms-settings:privacy-location
URI。
<!--Set Visibility to Visible when access to location is denied -->
<TextBlock x:Name="LocationDisabledMessage" FontStyle="Italic"
Visibility="Collapsed" Margin="0,15,0,0" TextWrapping="Wrap" >
<Run Text="This app is not able to access Location. Go to " />
<Hyperlink NavigateUri="ms-settings:privacy-location">
<Run Text="Settings" />
</Hyperlink>
<Run Text=" to check the location privacy settings."/>
</TextBlock>
或者,您的應用程式可以呼叫 LaunchUriAsync 方法來從程式代碼啟動 設定 應用程式。 如需詳細資訊,請參閱啟動 Windows 設定 應用程式。
using Windows.System;
...
bool result = await Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));
疑難排解您的應用程式
您的應用程式必須先在裝置上啟用 Location,才能存取使用者的位置。 在 設定 應用程式中,檢查是否已開啟下列位置隱私權設定:
- 此裝置的位置...已開啟 (不適用於 Windows 10 行動裝置版)
- 位置服務設定 [位置] 已 開啟
- 在 [ 選擇可使用您位置的應用程式] 下,您的應用程式會設定為 [開啟]
相關主題
意見反應
https://aka.ms/ContentUserFeedback。
即將推出:在 2024 年,我們將隨著內容的意見反應機制逐步淘汰 GitHub 問題,並以新的意見反應系統來取代。 如需詳細資訊,請參閱提交並檢視相關的意見反應