Tutorial: Com base na localização de notificações push com Notification Hubs do Azure e dados geográficos do BingTutorial: Push location-based notifications with Azure Notification Hubs and Bing Spatial Data

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.In this tutorial, you learn how to deliver location-based push notifications with Azure Notification Hubs and Bing Spatial Data.

Neste tutorial, siga os seguintes passos:In this tutorial, you take the following steps:

  • Configurar a origem de dadosSet up the data source
  • Configurar a aplicação UWPSet up the UWP application
  • Configurar o back-endSet up the backend
  • Testar as notificações push na aplicação de Plataforma Universal do Windows (UWP)Test push notifications in the Universal Windows Platform (UWP) app

Pré-requisitosPrerequisites

Configurar a origem de dadosSet up the data source

  1. Inicie sessão no Dev Center do Bing Maps.Log in to the Bing Maps Dev Center.

  2. Na barra de navegação superior, selecione Origens de dados e selecione Gerir Origens de Dados.In the top navigation bar, select Data sources, and select Manage Data Sources.

  3. Se não vir uma origem de dados existente, verá uma ligação para criar uma origem de dados.If you don't have an existing data source, you see a link to create a data source. Selecione Carregar dados como uma origem de dados.Select Upload data as a data source. Também pode utilizar o menu Origens de dados > Carregar dados.You can also use Data sources > Upload data menu.

  4. Crie um ficheiro NotificationHubsGeofence.pipe no disco rígido com o seguinte conteúdo: Neste tutorial, vai utilizar um ficheiro com base em pipe de exemplo que enquadra uma área da frente marítima de San Francisco:Create a file NotificationHubsGeofence.pipe on your hard drive with the following content: In this tutorial, you use a sample pipe-based file that frames an area of the San Francisco waterfront:

    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:The pipe file represents this entity:

  5. Na página Carregar uma origem de dados, faça o seguinte:In the Upload a data source page, do the following actions:

    1. Selecione pipe para Formato de dados.Select pipe for Data format.

    2. Procure e selecione o NotificationHubGeofence.pipe ficheiro que criou no passo anterior.Browse and select the NotificationHubGeofence.pipe file that you created in the previous step.

    3. Selecione o botão Carregar.Select Upload button.

      Nota

      Poderá ser-lhe pedido que especifique uma nova chave para a Chave Mestra diferente da Chave de Consulta.You might be prompted to specify a new key for the Master Key that is different from the Query Key. Crie simplesmente uma nova chave através do dashboard e atualize a página de carregamento da origem de dados.Simply create a new key through the dashboard and refresh the data source upload page.

  6. Uma vez carregado o ficheiro de dados, terá de se certificar de que pode publicar a origem de dados.Once you upload the data file, you need to make sure that you publish the data source. Selecione Origens de dados -> Gerir Origens de Dados como fez anteriormente.Select Data sources -> Manage Data Sources like you did before.

  7. Selecione a origem de dados na lista e selecione Publicar na coluna Ações.Select your data source in the list, and choose Publish in the Actions column.

  8. Mude para o separador Origens dos Dados Publicados e confirme que vê a origem de dados na lista.Switch to the Published Data Sources tab, and confirm that you see your data source in the list.

  9. Selecione Editar.Select Edit. Verá (de relance) as localizações que introduziu nos dados.You see (at a glance) what locations you introduced in the data.

    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.At this point, the portal does not show you the boundaries for the geofence that you created – all you need is confirmation that the location specified is in the right vicinity.

  10. Tem, agora, todos os requisitos para a origem de dados.Now you have all the requirements for the data source. 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.To get the details on the request URL for the API call, in the Bing Maps Dev Center, choose Data sources and select Data Source Information.

    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.The Query URL is the endpoint against which you can execute queries to check whether the device is currently within the boundaries of a location or not. Para executar esta verificação, basta executar uma chamada GET no URL de consulta, com os seguintes parâmetros anexados:To perform this check, you just execute a GET call against the query URL, with the following parameters appended:

    ?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.Bing Maps automatically performs the calculations to see whether the device is within the geofence. Uma vez executado o pedido por meio de um browser (ou cURL), obterá uma resposta JSON padrão:Once you execute the request through a browser (or cURL), you get a standard JSON response:

    Esta resposta só aparece quando o ponto está, de facto, dentro dos limites designados.This response only happens when the point is actually within the designated boundaries. Se não estiver, obterá um registo de resultados vazio:If it is not, you get an empty results bucket:

Configurar a aplicação UWPSet up the UWP application

  1. No Visual Studio, inicie um novo projeto do tipo Aplicação em Branco (Universal Windows).In Visual Studio, start a new project of type Blank App (Universal Windows).

    Assim que a criação de projeto estiver concluída, deverá ter o escudo para a aplicação em si.Once the project creation is complete, you should have the harness for the app itself. Vamos agora configurar tudo para a infraestrutura de perímetro geográfico.Now let’s set up everything for the geo-fencing infrastructure. 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:Because you are going to use Bing services for this solution, there is a public REST API endpoint that allows you to query specific location frames:

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

    Especifique os seguintes parâmetros para fazer com que funcione:Specify the following parameters to get it working:

    • 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.Data Source ID and Data Source Name – in Bing Maps API, data sources contain various bucketed metadata, such as locations and business hours of operation.

    • Nome da Entidade – a entidade que pretende utilizar como um ponto de referência para a notificação.Entity Name – the entity you want to use as a reference point for the notification.

    • Chave de API do Bing Maps – a chave que obteve anteriormente quando criou a conta do Dev Center do Bing.Bing Maps API Key – The key that you obtained earlier when you created the Bing Dev Center account.

      Agora que já tem a origem de dados pronta, pode começar a trabalhar na aplicação UWP.Now that you have the data source ready, you can start working on the UWP application.

  2. Ative os serviços de localização para a sua aplicação.Enable location services for your application. Abra o ficheiro Package.appxmanifest no Explorador de Soluções.Open the Package.appxmanifest file in Solution Explorer.

  3. No separador de propriedades do pacote que acabou de abrir, mude para o separador Capacidades e selecione Localização.In the package properties tab that just opened, switch to the Capabilities tab, and select Location.

  4. Crie uma nova pasta na solução com o nome Core e adicione um novo ficheiro dentro da mesma, denominado LocationHelper.cs:Create a new folder in your solution named Core, and add a new file within it, named LocationHelper.cs:

    A classe LocationHelper tem código para obter a localização do utilizador através da API do sistema:The LocationHelper class has code to obtain the user location through the system API:

    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 utilizador em aplicações UWP, veja Obter a localização do utilizador.To learn more about getting the user’s location in UWP apps, seeGet the user's location.

  5. 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).To check that the location acquisition is actually working, open the code side of your main page (MainPage.xaml.cs). Crie um novo processador de eventos para o evento Loaded no construtor MainPage.Create a new event handler for the Loaded event in the MainPage constructor.

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

    A implementação do processador de eventos é feita do seguinte modo:The implementation of the event handler is as follows:

    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. Execute a aplicação e permita que a mesma aceda à sua localização.Run the application and allow it to access your location.

  7. Uma vez iniciada a aplicação, deverá conseguir ver as coordenadas na janela Saída:Once the application launches, you should be able to see the coordinates in the Output window:

    Agora que já sabe que a aquisição de localização funciona, pode remover o processador de eventos Carregado se preferir, uma vez que não voltará a utilizá-lo.Now you know that location acquisition works, you can remove the Loaded event handler if you like because you won’t be using it anymore.

  8. O passo seguinte é capturar as alterações de localização.The next step is to capture location changes. Na classe LocationHelper, adicione o processador de eventos para PositionChanged:In the LocationHelper class, add the event handler for PositionChanged:

    geolocator.PositionChanged += Geolocator_PositionChanged;
    

    A implementação apresenta as coordenadas de localização na janela Saída:The implementation shows the location coordinates in the Output window:

    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-endSet up the backend

  1. Transfira o Exemplo de Back-end do .NET a partir do GitHub.Download the .NET Backend Sample from GitHub.

  2. Uma vez concluída a transferência, abra a pasta NotifyUsers e, em seguida, abra o ficheiro NotifyUsers.sln no Visual Studio.Once the download completes, open the NotifyUsers folder, and then open NotifyUsers.sln file in Visual Studio.

  3. Defina o projeto AppBackend como Projeto de Arranque e inicie-o.Set the AppBackend project as the StartUp Project and launch it.

    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.The project is already configured to send push notifications to target devices, so you need to do only two things – specify right connection string for the notification hub and add boundary identification to send the notification only when the user is within the geofence.

  4. Para configurar a cadeia de ligação, na pasta Models abra Notifications.cs.To configure the connection string, in the Models folder open Notifications.cs. A função NotificationHubClient.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).The NotificationHubClient.CreateClientFromConnectionString function should contain the information about your notification hub that you can get in the Azure portal (look inside the Access Policies page in Settings). Guarde a configuração de ficheiro atualizada.Save the updated configuration file.

  5. Crie um modelo para o resultado da API do Bing Maps.Create a model for the Bing Maps API result. A forma mais fácil de o fazer é abrir a pasta Models e selecionar Adicionar > Classe.The easiest way to do that is to open the Models folder and choose Add > Class. Dê-lhe o nome GeofenceBoundary.cs.Name it GeofenceBoundary.cs. Quando tiver terminado, copie o JSON da resposta da API que obteve na primeira secção.Once done, copy the JSON from the API response that you got in the first section. No Visual Studio, utilize as opções Editar > Colar Especial > Colar JSON como Classes.In Visual Studio, use Edit > Paste Special > Paste JSON as Classes.

    Desta forma, garante que será anulada a serialização do objeto exatamente como se projetou.This way you ensure that the object is deserialized exactly as it was intended. O conjunto de classes resultante deve assemelhar-se à seguinte classe:Your resulting class set should resemble the following class:

    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.Next, open Controllers > NotificationsController.cs. Atualize a chamada Publicar para ter em conta a latitude e longitude do destino.Update the Post call to account for the target longitude and latitude. Para o fazer, adicione duas cadeias à assinatura da função: latitude e longitude.To do so, add two strings to the function signature – latitude and 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 denominada ApiHelper.cs – irá utilizá-la para ligar ao Bing para verificar intersecções de limites do ponto.Create a new class within the project called ApiHelper.cs – you use it to connect to Bing to check point boundary intersections. Implemente uma função IsPointWithinBounds conforme apresentado no seguinte código:Implement a IsPointWithinBounds function as shown in the following code:

    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).Make sure to substitute the API endpoint with the query URL that you obtained earlier from the Bing Dev Center (same applies to the API key).

    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.If there are results to the query, that means that the specified point is within the boundaries of the geofence, so the function returns 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 devolve false.If there are no results, Bing is telling you that the point is outside the lookup frame, so the function returns false.

  8. No NotificationsController.cs, crie uma verificação mesmo antes da instrução switch:In NotificationsController.cs, create a check right before the switch statement:

    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 UWPTest push notifications in the UWP app

  1. Na aplicação UWP, já deve poder testar as notificações.In the UWP app, you should now be able to test notifications. N classe LocationHelper, crie uma nova função – SendLocationToBackend:Within the LocationHelper class, create a new function – 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.Set the POST_URL to the location of your deployed web application. Para já, é possível executá-la localmente, mas à medida que for trabalhando na implementação de uma versão pública, será necessário alojá-la num fornecedor externo.For now, it’s OK to run it locally, but as you work on deploying a public version, you need to host it with an external provider.

  2. Registe a aplicação UWP para enviar notificações push.Register the UWP app for push notifications. No Visual Studio, escolha Projeto > Armazenar > Associar a aplicação à loja.In Visual Studio, choose Project > Store > Associate app with the store.

  3. 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.Once you sign in to your developer account, make sure you select an existing app or create a new one and associate the package with it.

  4. Aceda ao Dev Center e abra a aplicação que criou.Go to the Dev Center and open the app that you created. Escolha Serviços > Notificações Push > Site dos Serviços Live.Choose Services > Push Notifications > Live Services site.

  5. No site, tome nota do Segredo da Aplicação e do SID do Pacote.On the site, take note of the Application Secret and the Package SID. 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.You need both in the Azure portal – open your notification hub, choose Settings > Notification Services > Windows (WNS) and enter the information in the required fields.

  6. Escolha Guardar.Choose Save.

  7. Abra Referências, no Explorador de Soluções, e selecione Gerir Pacotes NuGet.Open References in Solution Explorer and select Manage NuGet Packages. Adicione uma referência à Biblioteca gerida do Microsoft Azure Service Bus. Para tal, procure WindowsAzure.Messaging.Managed e adicione ao projeto.Add a reference to the Microsoft Azure Service Bus managed library – simply search for WindowsAzure.Messaging.Managed and add it to your project.

  8. Para fins de teste, crie novamente o processador de eventos MainPage_Loaded e adicione-lhe este fragmento de código:For testing purposes, create the MainPage_Loaded event handler once again, and add this code snippet to it:

    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.The code registers the app with the notification hub. Está pronto para funcionar!You are ready to go!

  9. Em LocationHelper, no processador Geolocator_PositionChanged, pode adicionar um fragmento de código de teste que coloca forçadamente a localização dentro do perímetro geográfico:In LocationHelper, inside the Geolocator_PositionChanged handler, you can add a piece of test code that forcefully puts the location inside the geofence:

    await LocationHelper.SendLocationToBackend("wns", "TEST_USER", "TEST", "37.7746", "-122.3858");
    
  10. 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:Because you are not passing the real coordinates (which might not be within the boundaries at the moment) and are using predefined test values, you see a notification show up on update:

Passos SeguintesNext steps

Existem alguns passos que poderá ter de seguir para se certificar de que a solução está pronta para produção.There are a couple of steps that you might need to follow to make the solution production-ready.

  1. Em primeiro lugar, tem de garantir que os perímetros geográficos são dinâmicos.First, you need to ensure that geofences are dynamic. Isto irá necessitar de algum trabalho adicional com a API do Bing para carregar novos limites na origem de dados existente.It requires some extra work with the Bing API to be able to upload new boundaries within the existing data source. Para obter mais informações, veja Documentação da API dos Serviços de Dados Geográficos do Bing.For more information, see Bing Spatial Data Services API documentation.
  2. Segundo, à medida que vai trabalhando para garantir que a entrega é efetuada aos participantes corretos, poderá querer segmentá-los através de etiquetagem.Second, as you are working to ensure that the delivery is done to the right participants, you might want to target them via tagging.

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.The solution shown in this tutorial describes a scenario in which you might have a wide variety of target platforms, so it does not limit the geofencing to system-specific capabilities. Dito isto, a Plataforma Universal do Windows oferece capacidades para detetar perímetros geográficos logo na primeira execução.That said, the Universal Windows Platform offers capabilities to detect geofences right out-of-the-box.