取得使用者的位置

用 Windows。Devices.Geolocation API 用於偵測裝置在 Windows 應用程式 SDK(WinUI 3)應用程式中的地理位置。 你可以取得一次性位置資訊,或隨時間持續追蹤使用者的位置。 本文涵蓋權限處理、一次性及連續位置讀取,以及如何在位置變更時更新使用者介面。

附註

這些 Windows.Devices.Geolocation API 是 Windows 執行階段(WinRT)API,適用於 UWP 和 WinUI 3 桌面應用程式。 本文中的程式碼使用了 WinUI 3 模式(例如使用 DispatcherQueue 進行執行緒封送處理)。

先決條件

  • 這是一個由 Blank App, Packaged(桌面版 WinUI 3) 範本建立的 WinUI 3 專案。
  • 在套件資訊清單中宣告的 定位 功能(請參閱 啟用定位功能)。

啟用位置功能

你的應用程式必須先宣告 位置 功能,才能存取使用者的位置。

  1. 在 方案總管 中,雙擊 Package.appxmanifest,然後選擇「能力」標籤。
  2. 勾選 地點方框。

這在清單中新增了以下條目:

<Capabilities>
    <DeviceCapability Name="location"/>
</Capabilities>

Tip

對於未封裝的應用程式,清單中不需要位置功能。 不過,你仍然必須呼叫 RequestAccessAsync 來提示使用者取得許可。

取得目前的位置

請依照以下步驟執行單次位置讀取。

請求存取使用者位置

在存取位置資料前,請先先聯絡 Geolocator.RequestAccessAsync 。 此方法在首次執行時會提示使用者取得權限。 你必須在應用程式位於前景時,從 UI 執行緒呼叫它。

using Windows.Devices.Geolocation;

var accessStatus = await Geolocator.RequestAccessAsync();

請閱讀立場

如果使用者授予權限,請建立 Geolocator 並呼叫 GetGeopositionAsync,以取得一次性的位置資訊。

switch (accessStatus)
{
    case GeolocationAccessStatus.Allowed:
        var geolocator = new Geolocator { DesiredAccuracyInMeters = 50 };
        Geoposition position = await geolocator.GetGeopositionAsync();

        double latitude = position.Coordinate.Point.Position.Latitude;
        double longitude = position.Coordinate.Point.Position.Longitude;

        StatusText.Text = $"Location: {latitude:F4}, {longitude:F4}";
        break;

    case GeolocationAccessStatus.Denied:
        StatusText.Text = "Location access is denied.";
        break;

    case GeolocationAccessStatus.Unspecified:
        StatusText.Text = "An unspecified error occurred.";
        break;
}

追蹤使用者位置隨時間的變化

欲定期接收位置更新,請訂閱 PositionChanged 活動。 設定 ReportInterval 用於時間追蹤,或設定 MovementThreshold 用於距離追蹤。

if (accessStatus == GeolocationAccessStatus.Allowed)
{
    var geolocator = new Geolocator { ReportInterval = 2000 }; // 2-second interval

    geolocator.PositionChanged += OnPositionChanged;
    geolocator.StatusChanged += OnStatusChanged;
}

處理位置更新

PositionChanged事件會在背景線程觸發。 用 DispatcherQueue 來將 UI 更新匯回主執行緒。

private void OnPositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
    DispatcherQueue.TryEnqueue(() =>
    {
        var position = args.Position.Coordinate.Point.Position;
        StatusText.Text = $"Updated: {position.Latitude:F4}, {position.Longitude:F4}";
    });
}

處理狀態變更

監控 狀態變更 以偵測使用者何時關閉定位服務或 GPS 訊號中斷。

private void OnStatusChanged(Geolocator sender, StatusChangedEventArgs args)
{
    DispatcherQueue.TryEnqueue(() =>
    {
        switch (args.Status)
        {
            case PositionStatus.Ready:
                StatusText.Text = "Location is available.";
                break;
            case PositionStatus.Disabled:
                StatusText.Text = "Location is disabled. Check Settings.";
                break;
            case PositionStatus.NoData:
                StatusText.Text = "Unable to determine location.";
                break;
            case PositionStatus.NotAvailable:
                StatusText.Text = "Location is not available on this device.";
                break;
        }
    });
}

引導使用者前往位置設定

如果使用者拒絕存取位置,請提供 Windows 隱私設定的連結,讓他們可以更改偏好設定。

<HyperlinkButton Content="Open location settings"
                 NavigateUri="ms-settings:privacy-location" />

你也可以從程式碼開啟設定頁面:

await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));

在地圖上顯示位置

取得位置後,您可以藉由設定其 Center 並新增 MapIcon,將其顯示在 WinUI 3 的 MapControl 上。 若想看結合地理定位、地圖顯示與地理圍欄的完整工作範例,請參見 地圖與位置概述。

Troubleshooting

如果您的應用程式無法取得位置,請在 設定 > 隱私與安全 > 位置中確認以下事項:

  • 定位服務已開啟。
  • 你的應用程式在「讓應用程式存取你的位置」下被列為開啟。
  • 裝置配備可運作的GPS接收器或網路定位功能。