Obter a localização do utilizador

Utilize as APIs Windows.Devices.Geolocation para detetar a posição geográfica do dispositivo numa aplicação do SDK de Aplicações Windows (WinUI 3). Pode obter a localização uma única vez ou seguir a posição do utilizador ao longo do tempo. Este artigo aborda o tratamento de permissões, leituras de localização pontual e contínuas, e como atualizar a sua interface quando a localização muda.

Note

As Windows.Devices.Geolocation APIs são APIs do Windows Runtime (WinRT) que funcionam tanto em aplicações desktop UWP como WinUI 3. O código neste artigo utiliza padrões do WinUI 3 (como o DispatcherQueue, para encaminhamento de threads).

Prerequisites

  • Um projeto WinUI 3 criado a partir do modelo Blank App, Packaged (WinUI 3 in Desktop).
  • A capacidade de localização declarada no manifesto do pacote (ver Ativar a capacidade de localização).

Ativar a capacidade de localização

A sua aplicação deve declarar a capacidade de Localização antes de poder aceder à posição do utilizador.

  1. No Explorador de Soluções, clique duas vezes em Package.appxmanifest e selecione o separador Capabilities.
  2. Selecione a caixa de verificação Localização.

Isto acrescenta a seguinte entrada ao manifesto:

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

Sugestão

Para aplicações não encapsuladas, a funcionalidade de Localização não é necessária num manifesto. No entanto, tem ainda de chamar RequestAccessAsync para solicitar autorização ao utilizador.

Obter a localização atual

Siga estes passos para realizar uma leitura única da posição.

Solicitar acesso à localização do utilizador

Chame Geolocator.RequestAccessAsync antes de aceder aos dados de localização. Este método pede permissão ao utilizador logo na primeira execução. Tens de o chamar a partir do tópico da interface enquanto a tua aplicação está em primeiro plano.

using Windows.Devices.Geolocation;

var accessStatus = await Geolocator.RequestAccessAsync();

Leia a posição

Se o utilizador der permissão, crie um Geolocalizador e ligue para o GetGeopositionAsync para obter uma solução única de posição.

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

Rastreie a localização do utilizador ao longo do tempo

Para receber atualizações periódicas de localização, subscreva o evento PositionChanged . Defina ReportInterval para rastreamento baseado no tempo ou MovementThreshold para rastreamento baseado em distâncias.

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

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

Atualizações da posição das alças

O evento PositionChanged é acionado numa thread em segundo plano. Use DispatcherQueue para redirecionar as atualizações da interface de volta ao tópico principal.

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

Gerir alterações de estado

Monitorize StatusChanged para detetar quando o utilizador desativa os serviços de localização ou se o sinal GPS se perder.

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

Dirija o utilizador para as definições de localização

Se o utilizador negar o acesso à localização, forneça um link para as definições de privacidade do Windows para que possa alterar a sua preferência.

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

Também podes abrir a página de definições a partir do código:

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

Mostrar a localização num mapa

Depois de recuperares uma posição, podes exibi-la num MapControl do WinUI 3 definindo o seu Center e adicionando um MapIcon. Para um exemplo completo e funcional que combine geolocalização, visualização de mapas e geofencing, consulte os Mapas e a visão geral da localização.

Troubleshooting

Se a sua aplicação não conseguir recuperar uma localização, verifique o seguinte nas Definições > Localização de Privacidade e Segurança>:

  • Os serviços de localização estão ativados.
  • A sua aplicação está listada e definida para Ligado em Deixar que as aplicações acedam à sua localização.
  • O dispositivo tem um recetor GPS funcional ou está disponível posicionamento baseado em rede.