Tutorial: Enviar notificações por push baseadas em localização com Hubs de Notificação e Dados Espaciais do Bing
Neste tutorial, irá aprender a entregar notificações push com base na localização com Hubs de Notificação do Azure e Dados Geográficos do Bing.
Neste tutorial, siga os seguintes passos:
- Configurar a origem de dados
- Configurar a aplicação UWP
- Configurar o back-end
- Testar as notificações push na aplicação de Plataforma Universal do Windows (UWP)
Pré-requisitos
- Subscrição do Azure. Se não tiver uma subscrição do Azure, crie uma conta do Azure gratuita antes de começar.
- Visual Studio 2015 Update 1 ou posterior (Community Edition).
- Versão mais recente do Azure SDK.
- Conta do Dev Center do Bing Maps (pode criar uma gratuitamente e associá-la à conta Microsoft).
Configurar a origem de dados
Inicie sessão no Dev Center do Bing Maps.
Na barra de navegação superior, selecione Origens de dados e selecione Gerir Origens de Dados.
Se não vir uma origem de dados existente, verá uma ligação para criar uma origem de dados. Selecione Carregar dados como uma origem de dados. Também pode utilizar o menu Origens de dados>Carregar dados.
Crie um ficheiro
NotificationHubsGeofence.pipe
no seu disco rígido com o seguinte conteúdo: Neste tutorial, você usa um arquivo baseado em tubo de exemplo que enquadra uma área da orla de São Francisco:Bing Spatial Data Services, 1.0, TestBoundaries EntityID(Edm.String,primaryKey)|Name(Edm.String)|Longitude(Edm.Double)|Latitude(Edm.Double)|Boundary(Edm.Geography) 1|SanFranciscoPier|||POLYGON ((-122.389825 37.776598,-122.389438 37.773087,-122.381885 37.771849,-122.382186 37.777022,-122.389825 37.776598))
O ficheiro de pipe representa esta entidade:
Na página Carregar uma origem de dados, faça o seguinte:
Selecione pipe para Formato de dados.
Procure e selecione o
NotificationHubGeofence.pipe
arquivo que você criou na etapa anterior.Selecione o botão Carregar.
Nota
Poderá ser-lhe pedido que especifique uma nova chave para a Chave Mestra diferente da Chave de Consulta. Crie simplesmente uma nova chave através do dashboard e atualize a página de carregamento da origem de dados.
Uma vez carregado o ficheiro de dados, terá de se certificar de que pode publicar a origem de dados. Selecione Fontes de dados -> Gerencie fontes de dados como fazia antes.
Selecione a origem de dados na lista e selecione Publicar na coluna Ações.
Mude para o separador Origens dos Dados Publicados e confirme que vê a origem de dados na lista.
Selecione Editar. Verá (de relance) as localizações que introduziu nos dados.
Nesta fase, o portal não mostra os limites do perímetro geográfico que criou – só precisa de uma confirmação de que a localização especificada está na vizinhança certa.
Tem, agora, todos os requisitos para a origem de dados. Para obter os detalhes acerca do URL do pedido para a chamada de API, no Bing Maps Dev Center, escolha Origens de dados e selecione Informações das Origens de Dados.
O URL de Consulta é o ponto final relativamente ao qual pode executar consultas para verificar se o dispositivo está ou não atualmente dentro dos limites de uma localização. Para executar esta verificação, basta executar uma chamada GET no URL de consulta, com os seguintes parâmetros anexados:
?spatialFilter=intersects(%27POINT%20LONGITUDE%20LATITUDE)%27)&$format=json&key=QUERY_KEY
O Bing Maps efetua automaticamente os cálculos para ver se o dispositivo está dentro do perímetro geográfico. Uma vez executado o pedido por meio de um browser (ou cURL), obterá uma resposta JSON padrão:
Esta resposta só aparece quando o ponto está, de facto, dentro dos limites designados. Se não estiver, obterá um registo de resultados vazio:
Configurar a aplicação UWP
No Visual Studio, inicie um novo projeto do tipo Aplicação em Branco (Universal Windows).
Assim que a criação de projeto estiver concluída, deverá ter o escudo para a aplicação em si. Agora vamos configurar tudo para a infraestrutura de geo-fencing. Uma vez que irá utilizar serviços Bing para esta solução, existe um ponto final público da API REST que lhe permite consultar molduras de localização específicas:
http://spatial.virtualearth.net/REST/v1/data/
Especifique os seguintes parâmetros para fazer com que funcione:
ID da Origem de Dados e Nome da Origem de Dados – na API Bing Maps, origens de dados contêm vários metadados agrupados, como localizações e horas de expediente da operação.
Nome da Entidade – a entidade que pretende utilizar como um ponto de referência para a notificação.
Chave de API do Bing Maps – a chave que obteve anteriormente quando criou a conta do Dev Center do Bing.
Agora que já tem a origem de dados pronta, pode começar a trabalhar na aplicação UWP.
Ative os serviços de localização para a sua aplicação. Abra o ficheiro
Package.appxmanifest
no Explorador de Soluções.No separador de propriedades do pacote que acabou de abrir, mude para o separador Capacidades e selecione Localização.
Crie uma nova pasta na solução com o nome
Core
e adicione um novo ficheiro dentro da mesma, denominadoLocationHelper.cs
:A classe
LocationHelper
tem código para obter a localização do utilizador através da API do sistema:using System; using System.Threading.Tasks; using Windows.Devices.Geolocation; namespace NotificationHubs.Geofence.Core { public class LocationHelper { private static readonly uint AppDesiredAccuracyInMeters = 10; public async static Task<Geoposition> GetCurrentLocation() { var accessStatus = await Geolocator.RequestAccessAsync(); switch (accessStatus) { case GeolocationAccessStatus.Allowed: { Geolocator geolocator = new Geolocator { DesiredAccuracyInMeters = AppDesiredAccuracyInMeters }; return await geolocator.GetGeopositionAsync(); } default: { return null; } } } } }
Para saber mais sobre como obter a localização do usuário em aplicativos UWP, consulte Obter a localização do usuário.
Para verificar se a aquisição de localização está, de facto, a funcionar, abra o lado de código da sua página principal (
MainPage.xaml.cs
). Crie um novo processador de eventos para o eventoLoaded
no construtorMainPage
.public MainPage() { this.InitializeComponent(); this.Loaded += MainPage_Loaded; }
A implementação do processador de eventos é feita do seguinte modo:
private async void MainPage_Loaded(object sender, RoutedEventArgs e) { var location = await LocationHelper.GetCurrentLocation(); if (location != null) { Debug.WriteLine(string.Concat(location.Coordinate.Longitude, " ", location.Coordinate.Latitude)); } }
Execute a aplicação e permita que a mesma aceda à sua localização.
Uma vez iniciada a aplicação, deverá conseguir ver as coordenadas na janela Saída:
Agora que você sabe que a aquisição de local funciona, você pode remover o manipulador de eventos Loaded, se quiser, porque não o usará mais.
O passo seguinte é capturar as alterações de localização. Na classe
LocationHelper
, adicione o processador de eventos paraPositionChanged
:geolocator.PositionChanged += Geolocator_PositionChanged;
A implementação apresenta as coordenadas de localização na janela Saída:
private static async void Geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args) { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { Debug.WriteLine(string.Concat(args.Position.Coordinate.Longitude, " ", args.Position.Coordinate.Latitude)); }); }
Configurar o back-end
Transfira o Exemplo de Back-end do .NET a partir do GitHub.
Uma vez concluída a transferência, abra a pasta
NotifyUsers
e, em seguida, abra o ficheiroNotifyUsers.sln
no Visual Studio.Defina o projeto
AppBackend
como Projeto de Arranque e inicie-o.O projeto já está configurado para enviar notificações push para os dispositivos de destino, por isso só precisa de fazer duas coisas – especificar a cadeia de ligação correta para o Hub de Notificação e adicionar identificação de limites para enviar a notificação apenas quando o utilizador estiver dentro do perímetro geográfico.
Para configurar a cadeia de ligação, na pasta
Models
abraNotifications.cs
. A funçãoNotificationHubClient.CreateClientFromConnectionString
deve conter as informações acerca do Hub de Notificação que pode obter no portal do Azure (procure na página Políticas de Acesso em Definições). Guarde a configuração de ficheiro atualizada.Crie um modelo para o resultado da API do Bing Maps. A forma mais fácil de o fazer é abrir a pasta
Models
e selecionar Adicionar>Classe. Dê-lhe o nome deGeofenceBoundary.cs
. Quando tiver terminado, copie o JSON da resposta da API que obteve na primeira secção. No Visual Studio, utilize as opções Editar>Colar Especial>Colar JSON como Classes.Desta forma, garante que será anulada a serialização do objeto exatamente como se projetou. O conjunto de classes resultante deve assemelhar-se à seguinte classe:
namespace AppBackend.Models { public class Rootobject { public D d { get; set; } } public class D { public string __copyright { get; set; } public Result[] results { get; set; } } public class Result { public __Metadata __metadata { get; set; } public string EntityID { get; set; } public string Name { get; set; } public float Longitude { get; set; } public float Latitude { get; set; } public string Boundary { get; set; } public string Confidence { get; set; } public string Locality { get; set; } public string AddressLine { get; set; } public string AdminDistrict { get; set; } public string CountryRegion { get; set; } public string PostalCode { get; set; } } public class __Metadata { public string uri { get; set; } } }
Em seguida, abra
Controllers
>NotificationsController.cs
. Atualize a chamada Publicar para ter em conta a latitude e longitude do destino. Para o fazer, adicione duas cadeias à assinatura da função:latitude
elongitude
.public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag, string latitude, string longitude)
Crie uma nova classe no projeto denominada
ApiHelper.cs
– irá utilizá-la para ligar ao Bing para verificar intersecções de limites do ponto. Implemente uma funçãoIsPointWithinBounds
conforme apresentado no seguinte código:public class ApiHelper { public static readonly string ApiEndpoint = "{YOUR_QUERY_ENDPOINT}?spatialFilter=intersects(%27POINT%20({0}%20{1})%27)&$format=json&key={2}"; public static readonly string ApiKey = "{YOUR_API_KEY}"; public static bool IsPointWithinBounds(string longitude,string latitude) { var json = new WebClient().DownloadString(string.Format(ApiEndpoint, longitude, latitude, ApiKey)); var result = JsonConvert.DeserializeObject<Rootobject>(json); if (result.d.results != null && result.d.results.Count() > 0) { return true; } else { return false; } } }
Importante
Não se esqueça de substituir o Ponto Final de API com o URL de consulta que obteve anteriormente no Dev Center do Bing (o mesmo se aplica à chave de API).
Se não existirem resultados da consulta, isso significa que o ponto especificado está dentro dos limites do perímetro geográfico, pelo que a função devolve
true
. Se não existirem resultados, o Bing estará a informar que o ponto está fora do intervalo de pesquisa, pelo que a função devolvefalse
.No
NotificationsController.cs
, crie uma verificação mesmo antes da instrução switch:if (ApiHelper.IsPointWithinBounds(longitude, latitude)) { switch (pns.ToLower()) { case "wns": //// Windows 8.1 / Windows Phone 8.1 var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">" + "From " + user + ": " + message + "</text></binding></visual></toast>"; outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag); // Windows 10 specific Action Center support toast = @"<toast><visual><binding template=""ToastGeneric""><text id=""1"">" + "From " + user + ": " + message + "</text></binding></visual></toast>"; outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag); break; } }
Testar as notificações push na aplicação UWP
Na aplicação UWP, já deve poder testar as notificações. N classe
LocationHelper
, crie uma nova função –SendLocationToBackend
:public static async Task SendLocationToBackend(string pns, string userTag, string message, string latitude, string longitude) { var POST_URL = "http://localhost:8741/api/notifications?pns=" + pns + "&to_tag=" + userTag + "&latitude=" + latitude + "&longitude=" + longitude; using (var httpClient = new HttpClient()) { try { await httpClient.PostAsync(POST_URL, new StringContent("\"" + message + "\"", System.Text.Encoding.UTF8, "application/json")); } catch (Exception ex) { Debug.WriteLine(ex.Message); } } }
Nota
Defina o
POST_URL
para a localização da sua aplicação Web implementada. Por enquanto, não há problema em executá-lo localmente, mas à medida que você trabalha na implantação de uma versão pública, precisa hospedá-lo com um provedor externo.Registe a aplicação UWP para enviar notificações push. No Visual Studio, escolha Projeto>Armazenar>Associar a aplicação à loja.
Depois de iniciar sessão na conta de programador, certifique-se de que seleciona uma aplicação existente ou cria uma nova e associe-lhe o pacote.
Aceda ao Dev Center e abra a aplicação que criou. Escolha Serviços>Notificações Push>Site dos Serviços Live.
No site, tome nota do Segredo da Aplicação e do SID do Pacote. Vai precisar de ambos no portal do Azure. Abra o seu Hub de Notificação, selecione Definições>Serviços de Notificação>Windows (WNS) e introduza as informações nos campos obrigatórios.
Escolha Guardar.
Abra Referências, no Explorador de Soluções, e selecione Gerir Pacotes NuGet. Adicione uma referência à Biblioteca gerida do Microsoft Azure Service Bus. Para tal, procure
WindowsAzure.Messaging.Managed
e adicione ao projeto.Para fins de teste, crie novamente o processador de eventos
MainPage_Loaded
e adicione-lhe este fragmento de código:var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync(); var hub = new NotificationHub("HUB_NAME", "HUB_LISTEN_CONNECTION_STRING"); var result = await hub.RegisterNativeAsync(channel.Uri); // Displays the registration ID so you know it was successful if (result.RegistrationId != null) { Debug.WriteLine("Reg successful."); }
O código regista a aplicação com o Hub de Notificação. Está pronto para funcionar!
Em
LocationHelper
, no processadorGeolocator_PositionChanged
, pode adicionar um fragmento de código de teste que coloca forçadamente a localização dentro do perímetro geográfico:await LocationHelper.SendLocationToBackend("wns", "TEST_USER", "TEST", "37.7746", "-122.3858");
Como não está a transmitir as coordenadas reais (que podem não estar de momento dentro dos limites) e está a utilizar valores de teste predefinidos, verá aparecer uma notificação na atualização:
Próximos passos
Existem alguns passos que poderá ter de seguir para se certificar de que a solução está pronta para produção.
- Em primeiro lugar, tem de garantir que os perímetros geográficos são dinâmicos. Isto irá necessitar de algum trabalho adicional com a API do Bing para carregar novos limites na origem de dados existente. Para obter mais informações, veja Documentação da API dos Serviços de Dados Geográficos do Bing.
- Segundo, à medida que vai trabalhando para garantir que a entrega é efetuada aos participantes corretos, poderá querer segmentá-los através de etiquetagem.
A solução mostrada neste tutorial descreve um cenário em que poderá ter uma grande variedade de plataformas de destino, por isso não limita o perímetro geográfico para as capacidades específicas do sistema. Dito isto, a Plataforma Universal do Windows oferece capacidades para detetar perímetros geográficos logo na primeira execução.