取得使用者的位置

注意

MapControl 和地圖服務要求地圖驗證金鑰,稱為 MapServiceToken。 如需取得和設定地圖驗證金鑰的詳細資訊,請參閱要求地圖驗證金鑰

尋找使用者的位置,並回應位置中的變更。 存取使用者的位置是由 設定 應用程式中的隱私權設定所管理。 本主題也會示範如何檢查您的應用程式是否有權存取使用者的位置。

秘訣 若要深入瞭解如何在應用程式中存取使用者的位置,請從 GitHub 上的 Windows-universal-samples 存放庫 下載下列範例。

啟用位置功能

  1. 方案總管 中,按兩下 package.appxmanifest,然後選取 [功能] 索引標籤。
  2. 在 [功能] 清單中,核取 [位置] 的方塊。 這會將 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 事件(定期型追蹤)。

如果兩個屬性都未設定,則會每隔 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 行動裝置版)
  • 位置服務設定 [位置] 已 開啟
  • 在 [ 選擇可使用您位置的應用程式] 下,您的應用程式會設定為 [開啟]