Configurar uma cerca geográfica
Configure uma cerca geográfica em seu aplicativo e saiba como lidar com notificações em primeiro e segundo plano.
Ativar a funcionalidade de localização
- No Gerenciador de Soluções, clique duas vezes em package.appxmanifest e selecione a guia Recursos .
- Na lista Recursos, marque Local. Isso adiciona a funcionalidade do
Location
dispositivo ao arquivo de manifesto do pacote.
<Capabilities>
<!-- DeviceCapability elements must follow Capability elements (if present) -->
<DeviceCapability Name="location"/>
</Capabilities>
Configuração de cerca geográfica
Etapa 1: Solicitar acesso à localização do usuário
Importante
Você deve solicitar acesso ao local do usuário usando o método RequestAccessAsync antes de tentar acessar o local do usuário. Você deve chamar o método RequestAccessAsync do thread da interface do usuário e seu aplicativo deve estar em primeiro plano. Seu aplicativo não poderá acessar as informações de localização do usuário até que o usuário conceda permissão ao seu aplicativo.
using Windows.Devices.Geolocation;
...
var accessStatus = await Geolocator.RequestAccessAsync();
O método RequestAccessAsync solicita permissão ao usuário para acessar sua localização. O usuário é solicitado apenas uma vez (por aplicativo). Após a primeira vez que eles concedem ou negam permissão, esse método não solicita mais permissão ao usuário. Para ajudar o usuário a alterar as permissões de localização depois de solicitado, recomendamos que você forneça um link para as configurações de localização, conforme demonstrado posteriormente neste tópico.
Etapa 2: Registrar-se para alterações no estado da cerca geográfica e nas permissões de localização
Neste exemplo, uma instrução switch é usada com accessStatus (do exemplo anterior) para agir somente quando o acesso ao local do usuário é permitido. Se o acesso à localização do usuário for permitido, o código acessará as cercas geográficas atuais, registrará as alterações de estado da cerca geográfica e registrará as alterações nas permissões de localização.
Dica Ao usar uma cerca geográfica, monitore as alterações nas permissões de localização usando o evento StatusChanged da classe GeofenceMonitor em vez do evento StatusChanged da classe Geolocator. Um GeofenceMonitorStatus de Disabled é equivalente a um PositionStatus desabilitado – ambos indicam que o aplicativo não tem permissão para acessar a localização do usuário.
switch (accessStatus)
{
case GeolocationAccessStatus.Allowed:
geofences = GeofenceMonitor.Current.Geofences;
FillRegisteredGeofenceListBoxWithExistingGeofences();
FillEventListBoxWithExistingEvents();
// Register for state change events.
GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;
GeofenceMonitor.Current.StatusChanged += OnGeofenceStatusChanged;
break;
case GeolocationAccessStatus.Denied:
_rootPage.NotifyUser("Access denied.", NotifyType.ErrorMessage);
break;
case GeolocationAccessStatus.Unspecified:
_rootPage.NotifyUser("Unspecified error.", NotifyType.ErrorMessage);
break;
}
Em seguida, ao sair do aplicativo em primeiro plano, cancele o registro dos ouvintes de eventos.
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
GeofenceMonitor.Current.GeofenceStateChanged -= OnGeofenceStateChanged;
GeofenceMonitor.Current.StatusChanged -= OnGeofenceStatusChanged;
base.OnNavigatingFrom(e);
}
Etapa 3: criar a cerca geográfica
Agora, você está pronto para definir e configurar um objeto de cerca geográfica. Há várias sobrecargas de construtor diferentes para escolher, dependendo de suas necessidades. No construtor de cerca geográfica mais básico, especifique apenas o Id e a Geoforma, conforme mostrado aqui.
// Set the fence ID.
string fenceId = "fence1";
// Define the fence location and radius.
BasicGeoposition position;
position.Latitude = 47.6510;
position.Longitude = -122.3473;
position.Altitude = 0.0;
double radius = 10; // in meters
// Set a circular region for the geofence.
Geocircle geocircle = new Geocircle(position, radius);
// Create the geofence.
Geofence geofence = new Geofence(fenceId, geocircle);
Você pode ajustar ainda mais sua cerca geográfica usando um dos outros construtores. No próximo exemplo, o construtor de cerca geográfica especifica estes parâmetros adicionais:
- MonitoredStates - Indica quais eventos de cerca geográfica você deseja receber notificações por entrar na região definida, sair da região definida ou remover a cerca geográfica.
- SingleUse - Remove a cerca geográfica depois que todos os estados para os quais a cerca geográfica está sendo monitorada forem atendidos.
- DwellTime - Indica quanto tempo o usuário deve estar dentro ou fora da área definida antes que os eventos de entrada/saída sejam disparados.
- StartTime - Indica quando começar a monitorar a cerca geográfica.
- Duração - Indica o período para monitorar a cerca geográfica.
// Set the fence ID.
string fenceId = "fence2";
// Define the fence location and radius.
BasicGeoposition position;
position.Latitude = 47.6510;
position.Longitude = -122.3473;
position.Altitude = 0.0;
double radius = 10; // in meters
// Set the circular region for geofence.
Geocircle geocircle = new Geocircle(position, radius);
// Remove the geofence after the first trigger.
bool singleUse = true;
// Set the monitored states.
MonitoredGeofenceStates monitoredStates =
MonitoredGeofenceStates.Entered |
MonitoredGeofenceStates.Exited |
MonitoredGeofenceStates.Removed;
// Set how long you need to be in geofence for the enter event to fire.
TimeSpan dwellTime = TimeSpan.FromMinutes(5);
// Set how long the geofence should be active.
TimeSpan duration = TimeSpan.FromDays(1);
// Set up the start time of the geofence.
DateTimeOffset startTime = DateTime.Now;
// Create the geofence.
Geofence geofence = new Geofence(fenceId, geocircle, monitoredStates, singleUse, dwellTime, startTime, duration);
Depois de criar, lembre-se de registrar sua nova cerca geográfica no monitor.
// Register the geofence
try {
GeofenceMonitor.Current.Geofences.Add(geofence);
} catch {
// Handle failure to add geofence
}
Etapa 4: Lidar com alterações nas permissões de localização
O objeto GeofenceMonitor dispara o evento StatusChanged para indicar que as configurações de localização do usuário foram alteradas. Esse evento passa o status correspondente por meio do remetente do argumento. Status (do tipo GeofenceMonitorStatus). Observe que esse método não é chamado do thread da interface do usuário e o objeto Dispatcher invoca as alterações da interface do usuário.
using Windows.UI.Core;
...
public async void OnGeofenceStatusChanged(GeofenceMonitor sender, object e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// Show the location setting message only if the status is disabled.
LocationDisabledMessage.Visibility = Visibility.Collapsed;
switch (sender.Status)
{
case GeofenceMonitorStatus.Ready:
_rootPage.NotifyUser("The monitor is ready and active.", NotifyType.StatusMessage);
break;
case GeofenceMonitorStatus.Initializing:
_rootPage.NotifyUser("The monitor is in the process of initializing.", NotifyType.StatusMessage);
break;
case GeofenceMonitorStatus.NoData:
_rootPage.NotifyUser("There is no data on the status of the monitor.", NotifyType.ErrorMessage);
break;
case GeofenceMonitorStatus.Disabled:
_rootPage.NotifyUser("Access to location is denied.", NotifyType.ErrorMessage);
// Show the message to the user to go to the location settings.
LocationDisabledMessage.Visibility = Visibility.Visible;
break;
case GeofenceMonitorStatus.NotInitialized:
_rootPage.NotifyUser("The geofence monitor has not been initialized.", NotifyType.StatusMessage);
break;
case GeofenceMonitorStatus.NotAvailable:
_rootPage.NotifyUser("The geofence monitor is not available.", NotifyType.ErrorMessage);
break;
default:
ScenarioOutput_Status.Text = "Unknown";
_rootPage.NotifyUser(string.Empty, NotifyType.StatusMessage);
break;
}
});
}
Configurar notificações em primeiro plano
Depois que suas cercas geográficas forem criadas, você deverá adicionar a lógica para lidar com o que acontece quando ocorre um evento de cerca geográfica. Dependendo dos MonitoredStates que você configurou, você pode receber um evento quando:
- O usuário entra em uma região de interesse.
- O usuário sai de uma região de interesse.
- A cerca geográfica expirou ou foi removida. Observe que um aplicativo em segundo plano não é ativado para um evento de remoção.
Você pode escutar eventos diretamente do seu aplicativo quando ele estiver em execução ou registrar-se em uma tarefa em segundo plano para receber uma notificação em segundo plano quando ocorrer um evento.
Etapa 1: Registrar-se para eventos de alteração de estado de cerca geográfica
Para que seu aplicativo receba uma notificação em primeiro plano de uma alteração de estado de cerca geográfica, você deve registrar um manipulador de eventos. Isso normalmente é configurado quando você cria a cerca geográfica.
private void Initialize()
{
// Other initialization logic
GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;
}
Etapa 2: Implementar o manipulador de eventos de cerca geográfica
A próxima etapa é implementar os manipuladores de eventos. A ação executada aqui depende do motivo pelo qual seu aplicativo está usando a cerca geográfica.
public async void OnGeofenceStateChanged(GeofenceMonitor sender, object e)
{
var reports = sender.ReadReports();
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
foreach (GeofenceStateChangeReport report in reports)
{
GeofenceState state = report.NewState;
Geofence geofence = report.Geofence;
if (state == GeofenceState.Removed)
{
// Remove the geofence from the geofences collection.
GeofenceMonitor.Current.Geofences.Remove(geofence);
}
else if (state == GeofenceState.Entered)
{
// Your app takes action based on the entered event.
// NOTE: You might want to write your app to take a particular
// action based on whether the app has internet connectivity.
}
else if (state == GeofenceState.Exited)
{
// Your app takes action based on the exited event.
// NOTE: You might want to write your app to take a particular
// action based on whether the app has internet connectivity.
}
}
});
}
Configurar notificações em segundo plano
Depois que suas cercas geográficas forem criadas, você deverá adicionar a lógica para lidar com o que acontece quando ocorre um evento de cerca geográfica. Dependendo dos MonitoredStates que você configurou, você pode receber um evento quando:
- O usuário entra em uma região de interesse.
- O usuário sai de uma região de interesse.
- A cerca geográfica expirou ou foi removida. Observe que um aplicativo em segundo plano não é ativado para um evento de remoção.
Para escutar um evento de cerca geográfica em segundo plano
- Declare a tarefa em segundo plano no manifesto do aplicativo.
- Registre a tarefa em segundo plano em seu aplicativo. Se seu aplicativo precisar de acesso à Internet, digamos, para acessar um serviço de nuvem, você poderá definir um sinalizador para isso quando o evento for disparado. Você também pode definir um sinalizador para garantir que o usuário esteja presente quando o evento for disparado, para que você tenha certeza de que o usuário será notificado.
- Enquanto seu aplicativo estiver em execução em primeiro plano, solicite que o usuário conceda permissões de localização ao aplicativo.
Etapa 1: Registrar-se para alterações de estado de cerca geográfica
No manifesto do aplicativo, na guia Declarações , adicione uma declaração para uma tarefa em segundo plano de localização. Para fazer isso:
- Adicione uma declaração do tipo Tarefas em segundo plano.
- Defina um tipo de tarefa de propriedade de Local.
- Defina um ponto de entrada em seu aplicativo para chamar quando o evento for disparado.
Etapa 2: Registrar a tarefa em segundo plano
O código nesta etapa registra a tarefa em segundo plano de cerca geográfica. Lembre-se de que, quando a cerca geográfica foi criada, verificamos as permissões de localização.
async private void RegisterBackgroundTask(object sender, RoutedEventArgs e)
{
// Get permission for a background task from the user. If the user has already answered once,
// this does nothing and the user must manually update their preference via PC Settings.
BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();
// Regardless of the answer, register the background task. Note that the user can use
// the Settings app to prevent your app from running background tasks.
// Create a new background task builder.
BackgroundTaskBuilder geofenceTaskBuilder = new BackgroundTaskBuilder();
geofenceTaskBuilder.Name = SampleBackgroundTaskName;
geofenceTaskBuilder.TaskEntryPoint = SampleBackgroundTaskEntryPoint;
// Create a new location trigger.
var trigger = new LocationTrigger(LocationTriggerType.Geofence);
// Associate the location trigger with the background task builder.
geofenceTaskBuilder.SetTrigger(trigger);
// If it is important that there is user presence and/or
// internet connection when OnCompleted is called
// the following could be called before calling Register().
// SystemCondition condition = new SystemCondition(SystemConditionType.UserPresent | SystemConditionType.InternetAvailable);
// geofenceTaskBuilder.AddCondition(condition);
// Register the background task.
geofenceTask = geofenceTaskBuilder.Register();
// Associate an event handler with the new background task.
geofenceTask.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);
BackgroundTaskState.RegisterBackgroundTask(BackgroundTaskState.LocationTriggerBackgroundTaskName);
switch (backgroundAccessStatus)
{
case BackgroundAccessStatus.Unspecified:
case BackgroundAccessStatus.Denied:
rootPage.NotifyUser("This app is not allowed to run in the background.", NotifyType.ErrorMessage);
break;
}
}
Etapa 3: Manipulando a notificação em segundo plano
A ação que você executa para notificar o usuário depende do que seu aplicativo faz, mas você pode exibir uma notificação do sistema, reproduzir um som de áudio ou atualizar um bloco dinâmico. O código nesta etapa manipula a notificação.
async private void OnCompleted(IBackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs e)
{
if (sender != null)
{
// Update the UI with progress reported by the background task.
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
try
{
// If the background task threw an exception, display the exception in
// the error text box.
e.CheckResult();
// Update the UI with the completion status of the background task.
// The Run method of the background task sets the LocalSettings.
var settings = ApplicationData.Current.LocalSettings;
// Get the status.
if (settings.Values.ContainsKey("Status"))
{
rootPage.NotifyUser(settings.Values["Status"].ToString(), NotifyType.StatusMessage);
}
// Do your app work here.
}
catch (Exception ex)
{
// The background task had an error.
rootPage.NotifyUser(ex.ToString(), NotifyType.ErrorMessage);
}
});
}
}
Alterar as configurações de privacidade
Se as configurações de privacidade de localização não permitirem que seu aplicativo acesse a localização do usuário, recomendamos que você forneça um link conveniente para as configurações de privacidade de localização no aplicativo Configurações. Neste exemplo, um controle Hyperlink é usado para navegar até o ms-settings:privacy-location
URI.
<!--Set Visibility to Visible when access to the user's location is denied. -->
<TextBlock x:Name="LocationDisabledMessage" FontStyle="Italic"
Visibility="Collapsed" Margin="0,15,0,0" TextWrapping="Wrap" >
<Run Text="This app is not able to access Location. Go to " />
<Hyperlink NavigateUri="ms-settings:privacy-location">
<Run Text="Settings" />
</Hyperlink>
<Run Text=" to check the location privacy settings."/>
</TextBlock>
Como alternativa, seu aplicativo pode chamar o método LaunchUriAsync para iniciar o aplicativo Configurações do código. Para saber mais, consulte Iniciar o aplicativo Configurações do Windows.
using Windows.System;
...
bool result = await Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-location"));
Testar e depurar seu aplicativo
Testar e depurar aplicativos de cerca geográfica pode ser um desafio porque eles dependem da localização de um dispositivo. Aqui, descrevemos vários métodos para testar cercas geográficas em primeiro plano e em segundo plano.
Para depurar um aplicativo de cerca geográfica
- Mova fisicamente o dispositivo para novos locais.
- Teste a inserção de uma cerca geográfica criando uma região de cerca geográfica que inclua sua localização física atual, para que você já esteja dentro da cerca geográfica e o evento "cerca geográfica inserida" seja acionado imediatamente.
- Use o emulador do Microsoft Visual Studio para simular locais para o dispositivo.
Testar e depurar um aplicativo de cerca geográfica que está sendo executado em primeiro plano
Para testar seu aplicativo de cerca geográfica que está sendo executado em primeiro plano
- Crie seu aplicativo no Visual Studio.
- Inicie seu aplicativo no emulador do Visual Studio.
- Use essas ferramentas para simular vários locais dentro e fora da região da cerca geográfica. Aguarde o tempo suficiente após o tempo especificado pela propriedade DwellTime para disparar o evento. Observe que você deve aceitar o prompt para habilitar permissões de localização para o aplicativo. Para obter mais informações sobre como simular locais, consulte Definir a localização geográfica simulada do dispositivo.
- Você também pode usar o emulador para estimar o tamanho das cercas e os tempos de permanência aproximadamente necessários para serem detectados em velocidades diferentes.
Testar e depurar um aplicativo de cerca geográfica que está sendo executado em segundo plano
Para testar seu aplicativo de cerca geográfica que está executando o plano de fundo
- Crie seu aplicativo no Visual Studio. Observe que seu aplicativo deve definir o tipo de tarefa em segundo plano Local .
- Implante o aplicativo localmente primeiro.
- Feche o aplicativo que está sendo executado localmente.
- Inicie seu aplicativo no emulador do Visual Studio. Observe que a simulação de cerca geográfica em segundo plano é compatível com apenas um aplicativo por vez no emulador. Não inicie vários aplicativos de cerca geográfica no emulador.
- No emulador, simule vários locais dentro e fora da região de cerca geográfica. Aguarde o tempo suficiente após o DwellTime para disparar o evento. Observe que você deve aceitar o prompt para habilitar permissões de localização para o aplicativo.
- Use o Visual Studio para disparar a tarefa em segundo plano de localização. Para obter mais informações sobre como disparar tarefas em segundo plano no Visual Studio, consulte Como disparar tarefas em segundo plano.
Solucionar problemas em seu aplicativo
Antes que seu aplicativo possa acessar a localização, a localização deve estar habilitada no dispositivo. No aplicativo Configurações, verifique se as seguintes configurações de privacidade de localização estão ativadas:
- Localização para este dispositivo... está ativado (não aplicável no Windows 10 Mobile)
- A configuração dos serviços de localização, Localização, está ativada
- Em Escolher aplicativos que podem usar sua localização, seu aplicativo é definido como ativado