Получение расположения пользователя

Используйте API Windows.Devices.Geolocation для определения географического положения устройства в приложении на базе Windows App SDK (WinUI 3). Вы можете получить однократное исправление расположения или отслеживать позицию пользователя с течением времени. В этой статье рассматриваются обработка разрешений, однократное и непрерывное чтение расположения и обновление пользовательского интерфейса при изменении расположения.

Note

API Windows.Devices.Geolocation — это API среда выполнения Windows (WinRT), которые работают как в приложениях UWP, так и в настольных приложениях WinUI 3. В коде в этой статье используются шаблоны WinUI 3 (например, DispatcherQueue для маршалинга потоков).

Необходимые условия

  • Проект WinUI 3, созданный из шаблона "Пустое приложение" (WinUI 3 в классическом режиме).
  • Возможность расположения, объявленная в манифесте пакета (см. раздел "Включить возможность расположения").

Включение возможности расположения

Приложение должно объявить возможность расположения , прежде чем он сможет получить доступ к позиции пользователя.

  1. В Обозреватель решений дважды щелкните Package.appxmanifest и перейдите на вкладку "Возможности".
  2. Установите флажок " Расположение".

При этом в манифест добавляется следующая запись:

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

Tip

Для приложений без пакета не требуется указывать в манифесте возможность определения местоположения. Однако необходимо по-прежнему вызывать RequestAccessAsync , чтобы запрашивать у пользователя разрешение.

Получение текущего расположения

Выполните следующие действия, чтобы выполнить однократное чтение позиции.

Запрос доступа к расположению пользователя

Вызовите Geolocator.RequestAccessAsync перед доступом к данным о местоположении. Этот метод запрашивает пользователю разрешение при первом запуске. Его необходимо вызвать из потока пользовательского интерфейса, пока приложение находится на переднем плане.

using Windows.Devices.Geolocation;

var accessStatus = await Geolocator.RequestAccessAsync();

Чтение позиции

Если пользователь предоставляет разрешение, создайте геолокатор и вызовите 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, чтобы перенаправить обновления пользовательского интерфейса обратно в главный поток.

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}";
    });
}

Обрабатывать изменения статуса

Отслеживайте СостояниеChanged , чтобы определить, когда пользователь отключает службы расположения или 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"));

Отображение расположения на карте

Получив местоположение, вы можете отобразить его в элементе WinUI 3 MapControl, задав для него Center и добавив MapIcon. Полный рабочий пример, объединяющий геолокацию, отображение карты и геозонирование, см. в разделе «Обзор: карты и расположение».

Troubleshooting

Если приложение не может получить расположение, проверьте следующее в разделе "Параметры > конфиденциальности" и "Расположение безопасности>".

  • Службы геолокациивключены.
  • Ваше приложение отображается и имеет значение On в разделе "Разрешить приложениям получить доступ к вашему расположению".
  • Устройство оснащено работающим GPS-приемником или доступно определение местоположения по сети.