Tutorial: Enviar notificações por push baseadas em localização com os Hubs de Notificação e o Bing Spatial Data

Neste tutorial, você aprenderá a entregar notificações por push baseadas na localização com os Hubs de Notificação do Azure e o Bing Spatial Data.

Neste tutorial, você deve executar as seguintes etapas:

  • Configurar a fonte de dados
  • Configurar o aplicativo UWP
  • Configurar o back-end
  • Enviar notificações por push de teste no aplicativo da UWP (Plataforma Universal do Windows)

Pré-requisitos

Configurar a fonte de dados

  1. Faça logon no Centro de Desenvolvimento do Bing Mapas.

  2. Na barra de navegação superior, selecione Fontes de dados e selecione Gerenciar Fontes de Dados.

    Captura de tela do Centro de Desenvolvimento do Bing Mapas, na página gerenciar fontes de dados, com a opção Carregar dados como uma fonte de dados delineada em vermelho.

  3. Se você não tiver uma fonte de dados, você verá um link para criar uma fonte de dados. Selecione Carregar os dados como uma fonte de dados. Você também pode usar o menu Fontes de dados>Carregar dados.

    Captura de tela da caixa de diálogo Carregar uma fonte de dados.

  4. Crie um arquivo NotificationHubsGeofence.pipe no disco rígido com o seguinte conteúdo: Neste tutorial, use um arquivo de exemplo baseado em pipe que enquadra uma área da orla marítima 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 arquivo de pipe representa esta entidade:

    Captura de tela de um mapa da orla marítima de São Francisco (EUA) com um polígono vermelho delineando uma área dos píeres.

  5. Na página Carregar uma fonte de dados, execute as seguintes ações:

    1. Selecione pipe para Formato de dados.

    2. Procure e selecione o arquivo NotificationHubGeofence.pipe que você criou na etapa anterior.

    3. Selecione o botão Carregar.

      Observação

      Poderá ser solicitada uma nova chave para a Chave Mestra, que é diferente da Chave de Consulta. Basta criar uma nova chave por meio do painel e atualizar a página de carregamento da fonte de dados.

  6. Depois que você carregar o arquivo de dados, você deve certificar-se de que publicou a fonte de dados. Selecione Fontes de dados ->Gerenciar Fontes de Dados como você fez antes.

  7. Selecione a fonte de dados na lista e escolha Publicar na coluna Ações.

    Captura de tela do Centro de Desenvolvimento do Bing Mapas, na página gerenciar fontes de dados, com a guia Dados com Codificação Geográfica selecionada e a opção Publicar delineada em vermelho.

  8. Altere para a guia Fontes de Dados Publicadas e confirme se você vê sua fonte de dados na lista.

    Captura de tela do Centro de Desenvolvimento do Bing Mapas na página Gerenciar Fontes de Dados com a guia Fontes de Dados Publicadas selecionada.

  9. Selecione Editar. Você vê (em um relance) locais que você introduziu nos dados.

    Captura de tela da página Editar dados de entidade, mostrando um mapa da parte ocidental dos Estados Unidos e um ponto magenta sobre a orla marítima de São Francisco.

    Neste ponto, o portal não mostrará os limites geográficos que criamos. Tudo o que você precisa é de uma confirmação de que o local especificado está na vizinhança certa.

  10. Agora você tem todos os requisitos da fonte de dados. Para obter os detalhes na URL de solicitação para a chamada à API, no Centro de Desenvolvimento do Bing Mapas, escolha Fontes de dados e selecione Informações da Fonte de Dados.

    Captura de tela do Centro de Desenvolvimento do Bing Mapas na página de Informações da fonte de dados.

    A URL de consulta é o ponto de extremidade no qual você pode executar consultas para verificar se o dispositivo ainda está dentro dos limites de um local ou não. Para realizar essa verificação, simplesmente execute uma chamada GET na URL de consulta, com os seguintes parâmetros anexados:

    ?spatialFilter=intersects(%27POINT%20LONGITUDE%20LATITUDE)%27)&$format=json&key=QUERY_KEY
    

    O Bing Mapas executa automaticamente os cálculos para ver se o dispositivo está dentro do geofence. Depois de executar a solicitação por meio de um navegador (ou cURL), você obterá uma resposta JSON padrão:

    Captura de tela da resposta JSON padrão.

    Essa resposta só acontece quando o ponto está realmente dentro dos limites designados. Caso contrário, você obterá um bucket vazio de resultados:

    Captura de tela de uma resposta JSON com um bucket de resultados vazio.

Configurar o aplicativo UWP

  1. No Visual Studio, inicie um novo projeto do tipo Aplicativo em Branco (Universal do Windows) .

    Captura de tela de uma caixa de diálogo de Novo Projeto do Visual Studio, com a opção de Aplicativo em Branco (Universal do Windows) para Visual C# realçada.

    Uma vez concluída a criação do projeto, você deverá ter o agente para o próprio aplicativo. Agora vamos configurar tudo para a infraestrutura de isolamento geográfico. Como você vai usar os serviços do Bing para essa solução, há um ponto de extremidade de API REST público que permite consultar quadros de local específico:

    http://spatial.virtualearth.net/REST/v1/data/
    

    Especifique os parâmetros a seguir para fazer isso funcionar:

    • ID da Fonte de Dados e Nome da Fonte de Dados – na API do Bing Mapas, as fontes de dados contêm diversos metadados classificados, como locais e horas comerciais de operação.

    • Nome da Entidade – a entidade que você deseja usar como um ponto de referência para a notificação.

    • Chave de API do Bing Mapas – a chave que você obteve anteriormente quando criou a conta do Centro de Desenvolvimento do Bing.

      Agora que a fonte de dados está pronta, você pode começar a trabalhar no aplicativo UWP.

  2. Habilite serviços de localização para o seu aplicativo. Abra o arquivo Package.appxmanifest no Gerenciador de Soluções.

    Captura de tela de Gerenciador de Soluções, com o arquivo Package.appxmanifest realçado.

  3. Na guia de propriedades do pacote que acabou de abrir, alterne para a guia Recursos e selecione Local.

    Captura de tela da caixa de diálogo Propriedades do Pacote, mostrando a guia Funcionalidades com a opção Localização realçada.

  4. Crie uma nova pasta na solução denominada Core e adicione um novo arquivo a ela, chamado LocationHelper.cs:

    Captura de tela do Gerenciador de Soluções, com a nova pasta Núcleo realçada.

    A classe LocationHelper tem um código para obter o local do usuário por meio 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 o local do usuário em aplicativos UWP, confiraObter a localização do usuário.

  5. Para verificar se a aquisição da localização está funcionando, abra o lado do código da página principal (MainPage.xaml.cs). Criar um novo manipulador de eventos para o evento Loaded no construtor MainPage.

    public MainPage()
    {
        this.InitializeComponent();
        this.Loaded += MainPage_Loaded;
    }
    

    A implementação do manipulador de eventos é a seguinte:

    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));
        }
    }
    
  6. Executar o aplicativo e permitir que ele acesse seu local.

    Captura de tela da caixa de diálogo Permitir que os Hubs de Notificação Limitem Geograficamente o acesso à sua localização.

  7. Assim que o aplicativo for iniciado, você deverá ser capaz de ver as coordenadas na janela Saída :

    Captura de tela da Janela de Saída exibindo as coordenadas.

    Agora você sabe que a aquisição de localização funciona, você pode remover o manipulador de eventos carregado se desejar, porque você não o usará mais.

  8. A próxima etapa é capturar as alterações de localização. Na classe LocationHelper, adicione o manipulador de eventos para PositionChanged:

    geolocator.PositionChanged += Geolocator_PositionChanged;
    

    A implementação mostra 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

  1. Baixe o exemplo de back-end .NET do GitHub.

  2. Quando o download for concluído, abra a pasta NotifyUsers e depois o arquivo NotifyUsers.sln no Visual Studio.

  3. Defina o projeto AppBackend como o Projeto de Inicialização e inicie-o.

    Captura de tela do menu de clique com o botão direito do mouse da solução com a opção Definir como Projeto de Inicialização realçada.

    O projeto já está configurado para enviar notificações por push para dispositivos de destino e, portanto, você precisa fazer somente duas coisas – especificar a cadeia de conexão correta para o hub de notificação e adicionar identificação de limite para enviar a notificação somente quando o usuário estiver dentro do limite geográfico.

  4. Para configurar a cadeia de conexão, abra Notifications.cs na pasta Models. A função NotificationHubClient.CreateClientFromConnectionString deve conter as informações sobre o hub de notificação que você pode obter no portal do Azure (examine a página Políticas de Acesso em Configurações). Salve o arquivo de configuração atualizado.

  5. Crie um modelo para o resultado da API do Bing Mapas. A maneira mais fácil de fazer isso é abrir a pasta Models e escolher Adicionar>Classe. Nomeie-o GeofenceBoundary.cs. Depois, copie o JSON da resposta de API que você obteve na primeira seção. No Visual Studio, use Editar>Colar especial>Colar JSON como Classes.

    Dessa forma, você garante que o objeto será desserializado exatamente como foi pretendido. O conjunto de classes resultante deve ter a seguinte aparência:

    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; }
        }
    }
    
  6. Em seguida, abra Controllers>NotificationsController.cs. Atualize a chamada Post para levar em consideração a latitude e a longitude do destino. Para isso, adicione duas cadeias de caracteres à assinatura da função – latitude e longitude.

    public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag, string latitude, string longitude)
    
  7. Crie uma nova classe no projeto chamado ApiHelper.cs – você a usa para a conexão com o Bing para criarmos pontos de verificação em interseções de limite. Implemente uma função IsPointWithinBounds conforme mostrado no código a seguir:

    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

    Substitua o ponto de extremidade de API pela URL de consulta obtida anteriormente do Centro de Desenvolvimento do Bing (o mesmo se aplica à chave de API).

    Se houver resultados para a consulta, isso significa que o ponto especificado está nos limites da delimitação geográfica e, portanto, a função retorna true. Se não houver nenhum resultado, o Bing está dizendo que o ponto está fora do quadro de pesquisa e, portanto, a função retorna false.

  8. Em NotificationsController.cs, crie uma verificação logo 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;
        }
    }
    

Teste de notificações por push no aplicativo UWP

  1. No aplicativo UWP, agora você deve conseguir testar as notificações. Na 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);
            }
        }
    }
    

    Observação

    Defina o POST_URL para o local do seu aplicativo web implantado. Por enquanto, é possível executá-lo localmente, mas à medida que você trabalhar na implantação de uma versão pública, precisará hospedá-lo em um provedor externo.

  2. Registre o aplicativo UWP para notificações por push. No Visual Studio, escolha Projeto>Loja>Associar aplicativo à loja.

    Captura de tela do menu de clique com o botão direito do mouse da solução com as opções Loja e Associar o Aplicativo à Loja realçadas.

  3. Depois que você entrar em sua conta de desenvolvedor, selecione um aplicativo existente ou crie um novo e associe o pacote a ele.

  4. Vá para o Centro de Desenvolvimento e abra o aplicativo que você criou. Escolha Serviços>Notificações por Push>Site do Live Services.

    Captura de tela do Centro de Desenvolvimento do Windows exibindo a página Notificações por push com o site do Live Services realçado.

  5. No site, anote o Segredo do Aplicativo e o SID do Pacote. Você precisa deles no portal do Azure – abra seu hub de notificação, escolha Configurações>Serviços de Notificação>Windows (WNS) e insira as informações nos campos obrigatórios.

    Captura de tela mostrando a página de Configurações com as opções WNS (Notification Services e Windows) realçadas e os valores de Chave de Segurança e SID do Pacote preenchidos.

  6. Escolha Salvar.

  7. Abra Referências no Gerenciador de Soluções e selecione Gerenciar Pacotes NuGet. Adicione uma referência à biblioteca gerenciada do Barramento de Serviço do Microsoft Azure – basta procurar WindowsAzure.Messaging.Managed e adicioná-lo ao seu projeto.

    Captura de tela da caixa de diálogo Gerenciar Pacotes NuGet com o pacote WindowsAzure.Messaging.Managed realçado.

  8. Para fins de teste, crie o manipulador de eventos MainPage_Loaded novamente e adicionar este snippet de código a ele:

    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 registra o aplicativo no hub de notificação. Você está pronto!

  9. Em LocationHelper, no manipulador Geolocator_PositionChanged, você pode adicionar uma parte do código de teste que impõe a colocação da localização dentro do limite geográfico:

    await LocationHelper.SendLocationToBackend("wns", "TEST_USER", "TEST", "37.7746", "-122.3858");
    
  10. Como você não está passando as coordenadas reais (que podem não estar nos limites no momento) e como estamos usando valores predefinidos de teste, você verá uma notificação sobre atualização:

    Captura de tela de uma área de trabalho do Windows exibindo a mensagem TESTE.

Próximas etapas

Existem algumas etapas que talvez você precise seguir para que a solução esteja pronta para produção.

  1. Primeiro, você precisa garantir que os limites geográficos sejam dinâmicos. Isso requer algum trabalho extra com a API do Bing para poder carregar novos limites na fonte de dados existente. Para obter mais informações, consulte Documentação da API de Serviços de Dados Espaciais do Bing.
  2. Segundo, como você está trabalhando para garantir que a entrega seja feita aos participantes certos, talvez você queira usar a marcaçãopara tê-los como destino.

A solução mostrada neste tutorial descreve um cenário em que você pode ter uma ampla variedade de plataformas de destino e, portanto, não limita a delimitação geográfica a recursos específicos do sistema. Dito isso, a Plataforma Universal do Windows oferece recursos para detectar delimitações geográficas prontas.