Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O SDK de Aplicações Windows e o WinUI 3 fornecem APIs e controlos para mostrar mapas, detetar a localização do utilizador e configurar geofences. Use estas capacidades para construir aplicações que mostrem mapas interativos com pinos, rastreiem a posição do utilizador e desencadeem ações quando este entra ou sai de uma área geográfica.
Este artigo apresenta cada capacidade e inclui um exemplo completo que combina MapControl, Geolocator, e GeofenceMonitor numa única aplicação funcional.
Mostrar mapas com o MapControl
O MapControl apresenta um mapa interativo alimentado pelo Azure Maps. Pode adicionar marcadores, camadas e reagir às interações do utilizador, como deslocação, zoom e clique.
O MapControl requer uma conta no Azure Maps. Consulte Gerir a sua conta Azure Maps para criar uma conta e obter um token de serviço.
Para instruções de utilização detalhadas, consulte MapControl.
<MapControl x:Name="myMap"
MapServiceToken="YOUR_AZURE_MAPS_TOKEN"
Height="400" />
Note
O MapControl do UWP e as APIs Windows.Services.Maps estão obsoletos e poderão não estar disponíveis em versões futuras do Windows. As aplicações WinUI 3 devem usar o novo MapControl descrito acima. Para obter mais informações, consulte Recursos para funcionalidades descontinuadas.
Detetar a localização do utilizador
As APIs Windows.Devices.Geolocation permitem-lhe obter a posição geográfica do dispositivo. Estas APIs funcionam tanto em aplicações UWP como em SDK de Aplicações Windows (WinUI 3). É possível:
- Obtenha uma posição única usando Geolocator.GetGeopositionAsync.
- Acompanhe as alterações de posição ao longo do tempo utilizando o evento Geolocator.PositionChanged.
- Monitorize as alterações no estado da visita com GeovisitMonitor para deteção da localização com eficiência energética.
Para um guia passo a passo, consulte Obter a localização do utilizador.
Instalar geofences
Uma geocerca define uma fronteira geográfica. A sua aplicação recebe notificações quando o utilizador entra ou sai do limite. As geofences são úteis para lembretes baseados na localização, alertas ou entrega de conteúdos.
Para instruções sobre como criar e monitorizar geofences, veja Configurar uma geofence.
Capacidade de localização e privacidade
Todas as APIs de localização exigem a capacidade de Localização declarada no manifesto do pacote da sua aplicação. Também tem de chamar Geolocator.RequestAccessAsync em tempo de execução antes de aceder aos dados de localização.
O Windows dá aos utilizadores controlo sobre quais as aplicações que podem aceder à sua localização através das Definições > Localização de Privacidade e Segurança>. A sua aplicação deve lidar com o caso em que o utilizador nega ou revoga o acesso à localização.
Exemplo completo
O exemplo seguinte reúne MapControl, Geolocator, e GeofenceMonitor numa única janela do WinUI 3. Se não houver uma chave do Azure Maps configurada, o mapa degrada-se de forma natural enquanto a geolocalização e a geofencing continuam a funcionar.
Prerequisites
- SDK de Aplicações Windows 2.2 ou posterior
- Uma chave do Azure Maps — necessária para mostrar as peças do mapa. Sem uma chave válida, o MapControl renderiza mas mostra um mapa em branco.
- A capacidade do dispositivo de localização declarada em
Package.appxmanifest:
<DeviceCapability Name="location" />
Defina a sua chave Azure Maps como variável de ambiente antes de executar a aplicação:
$env:AZURE_MAPS_KEY = "your-key-here"
MainWindow.xaml
Um painel de controlo de 300 píxeis à esquerda com botões e texto de estado, e um MapControl à direita. Uma sobreposição é apresentada quando a chave do Azure Maps estiver em falta.
<?xml version="1.0" encoding="utf-8" ?>
<Window
x:Class="MapLocationDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Map Location Demo">
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TitleBar Title="Map Location Demo" />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Margin="16" RowSpacing="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="Location Demo" FontSize="20" FontWeight="Bold"/>
<StackPanel Grid.Row="1" Spacing="8">
<Button x:Name="FindMeButton" Content="Find My Location"
Click="FindMeButton_Click" HorizontalAlignment="Stretch"/>
<Button x:Name="AddGeofenceButton" Content="Add Geofence Here"
Click="AddGeofenceButton_Click" HorizontalAlignment="Stretch"/>
</StackPanel>
<TextBlock x:Name="StatusText" Grid.Row="2"
Text="Click 'Find My Location' to begin." TextWrapping="Wrap"/>
<ListView x:Name="EventLog" Grid.Row="3" Header="Event Log"/>
</Grid>
<Grid Grid.Column="1">
<MapControl x:Name="MyMap" />
<StackPanel x:Name="MapKeyMissing" Visibility="Collapsed"
HorizontalAlignment="Center" VerticalAlignment="Center"
Spacing="8">
<FontIcon Glyph="" FontSize="48"
HorizontalAlignment="Center"
Foreground="{ThemeResource SystemFillColorCautionBrush}" />
<TextBlock Text="Azure Maps key not configured"
FontSize="18" FontWeight="SemiBold"
HorizontalAlignment="Center" />
<TextBlock x:Name="MapKeyHint" TextWrapping="Wrap" MaxWidth="400"
HorizontalAlignment="Center" TextAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel>
</Grid>
</Grid>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Devices.Geolocation;
using Windows.Devices.Geolocation.Geofencing;
namespace MapLocationDemo;
public sealed partial class MainWindow : Window
{
private Geolocator? _geolocator;
private BasicGeoposition _lastPosition;
private bool _mapAvailable;
public MainWindow()
{
InitializeComponent();
_mapAvailable = TryConfigureMap();
GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;
}
// Read the Azure Maps key from an environment variable.
// If missing, collapse the map and show an informational overlay.
private bool TryConfigureMap()
{
var key = Environment.GetEnvironmentVariable("AZURE_MAPS_KEY");
if (string.IsNullOrWhiteSpace(key))
{
MyMap.Visibility = Visibility.Collapsed;
MapKeyMissing.Visibility = Visibility.Visible;
MapKeyHint.Text = "Set the AZURE_MAPS_KEY environment variable "
+ "and restart.\nGeolocation and geofencing still work "
+ "without the map.";
Log("Azure Maps key not found — map disabled");
return false;
}
MyMap.MapServiceToken = key;
return true;
}
private async void FindMeButton_Click(object sender, RoutedEventArgs e)
{
FindMeButton.IsEnabled = false;
StatusText.Text = "Requesting location access...";
var access = await Geolocator.RequestAccessAsync();
if (access != GeolocationAccessStatus.Allowed)
{
StatusText.Text =
"Location access denied. Check Settings > Privacy > Location.";
FindMeButton.IsEnabled = true;
return;
}
_geolocator = new Geolocator { DesiredAccuracyInMeters = 100 };
try
{
var pos = await _geolocator.GetGeopositionAsync();
var lat = pos.Coordinate.Point.Position.Latitude;
var lon = pos.Coordinate.Point.Position.Longitude;
_lastPosition = new BasicGeoposition
{
Latitude = lat, Longitude = lon
};
StatusText.Text =
$"Location: {lat:F5}, {lon:F5} ({pos.Coordinate.Accuracy:F0} m)";
Log($"Position: {lat:F5}, {lon:F5}");
if (_mapAvailable)
{
var pt = new Geopoint(_lastPosition);
MyMap.Center = pt;
MyMap.ZoomLevel = 15;
var layer = new MapElementsLayer();
layer.MapElements = new List<MapElement>
{
new MapIcon { Location = pt }
};
MyMap.Layers.Clear();
MyMap.Layers.Add(layer);
}
}
catch (Exception ex) { StatusText.Text = $"Error: {ex.Message}"; }
finally { FindMeButton.IsEnabled = true; }
}
private void AddGeofenceButton_Click(object sender, RoutedEventArgs e)
{
if (_lastPosition.Latitude == 0 && _lastPosition.Longitude == 0)
{
StatusText.Text = "Get your location first.";
return;
}
var fence = new Geofence("MyGeofence",
new Geocircle(_lastPosition, 200),
MonitoredGeofenceStates.Entered | MonitoredGeofenceStates.Exited,
false, TimeSpan.FromSeconds(5));
GeofenceMonitor.Current.Geofences.Add(fence);
StatusText.Text = $"Geofence added at "
+ $"{_lastPosition.Latitude:F5}, {_lastPosition.Longitude:F5}";
Log("Geofence registered");
}
private void OnGeofenceStateChanged(
GeofenceMonitor sender, object args)
{
var reports = sender.ReadReports();
DispatcherQueue.TryEnqueue(() =>
{
foreach (var r in reports)
{
var msg = r.NewState switch
{
GeofenceState.Entered => $"Entered: {r.Geofence.Id}",
GeofenceState.Exited => $"Exited: {r.Geofence.Id}",
GeofenceState.Removed => $"Removed: {r.Geofence.Id}",
_ => null
};
if (msg != null) { StatusText.Text = msg; Log(msg); }
}
});
}
private void Log(string msg) =>
EventLog.Items.Insert(0, $"[{DateTime.Now:HH:mm:ss}] {msg}");
}
Padrões-chave
-
MapControlestá integrado no SDK de Aplicações Windows 1.6 e versões posteriores. DefineMapServiceTokenpara a tua chave Azure Maps. -
TryConfigureMapverifica aAZURE_MAPS_KEYvariável ambiente no arranque. Se a variável estiver vazia, o mapa colapsa e uma sobreposição explica como corrigi-la — sem crash, sem mapa vazio. -
DeviceCapability Name="location"emPackage.appxmanifesté obrigatório ouGeolocator.RequestAccessAsyncdevolveDenied. -
GeofenceMonitor.GeofenceStateChangedé acionado numa thread em segundo plano, por isso useDispatcherQueue.TryEnqueuepara atualizar a IU.
Artigos relacionados
Windows developer