Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
SDK do Aplicativo Windows e WinUI 3 fornecem APIs e controles para exibir mapas, detectar a localização do usuário e configurar cercas geográficas. Use esses recursos para criar aplicativos que mostram mapas interativos com pinos, acompanhar a posição do usuário e disparar ações quando o usuário entra ou sai de uma área geográfica.
Este artigo apresenta cada funcionalidade e inclui um exemplo completo que combina MapControl, Geolocatore GeofenceMonitor em um único aplicativo de trabalho.
Exibir mapas com MapControl
O MapControl exibe um mapa interativo alimentado por Azure Mapas. Você pode adicionar pinos, camadas e responder a interações do usuário, como arrastar, aplicar zoom e clicar.
MapControl requer uma conta de Azure Mapas. Consulte Gerenciar sua conta Azure Mapas para criar uma conta e obter um token de serviço.
Para obter instruções detalhadas de uso, consulte MapControl.
<MapControl x:Name="myMap"
MapServiceToken="YOUR_AZURE_MAPS_TOKEN"
Height="400" />
Note
As APIs UWP MapControl e Windows.Services.Maps estão obsoletas e podem não estar disponíveis em versões futuras do Windows. Os aplicativos WinUI 3 devem usar o novo MapControl descrito acima. Para obter mais informações, veja Recursos para funcionalidades preteridas.
Detectar a localização do usuário
As APIs Windows.Devices.Geolocation permitem obter a posição geográfica do dispositivo. Essas APIs funcionam em aplicativos UWP e SDK do Aplicativo Windows (WinUI 3). É possível:
- Obtenha uma posição única usando Geolocator.GetGeopositionAsync.
- Acompanhe as alterações de posição ao longo do tempo usando o evento Geolocator.PositionChanged .
- Monitore as alterações de estado de visita usando o GeovisitMonitor para reconhecimento de localização com eficiência de bateria.
Para obter um guia passo a passo, consulte Obter a localização do usuário.
Configurar cercas geográficas
Uma cerca geográfica define um limite geográfico. Seu aplicativo recebe notificações quando o usuário entra ou sai do limite. As geocercas são úteis para lembretes, alertas ou fornecimento de conteúdo com base na localização.
Para obter instruções sobre como criar e monitorar cercas geográficas, consulte Configurar uma cerca geográfica.
Capacidade de localização e privacidade
Todas as APIs de localização exigem a funcionalidade Local declarada no manifesto do pacote do aplicativo. Você também deve chamar Geolocator.RequestAccessAsync em runtime antes de acessar dados de localização.
Windows fornece aos usuários controle sobre quais aplicativos podem acessar sua localização por meio do Local de Privacidade e Segurança > de Configurações>. Seu aplicativo deve lidar com o caso em que o usuário nega ou revoga o acesso ao local.
Exemplo completo
O exemplo a seguir reúne MapControl, Geolocatore GeofenceMonitor em uma única janela do WinUI 3. Se nenhuma chave do Azure Mapas estiver configurada, o mapa se degrada normalmente, enquanto a geolocalização e o geofencing continuam funcionando.
Pré-requisitos
- SDK do Aplicativo Windows 2.2 ou posterior
- Uma chave Azure Mapas – necessária para exibir blocos de mapa. Sem uma chave válida, o MapControl é renderizado, mas mostra um mapa em branco.
- A funcionalidade do dispositivo Location declarada em
Package.appxmanifest:
<DeviceCapability Name="location" />
Defina sua chave Azure Mapas como uma variável de ambiente antes de executar o aplicativo:
$env:AZURE_MAPS_KEY = "your-key-here"
MainWindow.xaml
Um painel de controle de 300 pixels à esquerda com botões e texto de status e um MapControl à direita. Uma sobreposição é exibida quando a chave do Azure Mapas está ausente.
<?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}");
}
Principais padrões
-
MapControlé integrado ao SDK do Aplicativo Windows 1.6 e posterior. DefinaMapServiceTokencomo sua chave de Azure Mapas. -
TryConfigureMapverifica a variável deAZURE_MAPS_KEYambiente na inicialização. Se a variável estiver vazia, o mapa se recolhe e uma sobreposição explica como corrigir o problema — sem travamentos, sem mapa em branco. -
DeviceCapability Name="location"emPackage.appxmanifesté necessário ouGeolocator.RequestAccessAsyncretornaDenied. -
GeofenceMonitor.GeofenceStateChangedé executado em uma thread em segundo plano, portanto, useDispatcherQueue.TryEnqueuepara atualizar a interface do usuário.
Artigos relacionados
Windows developer