Esercitazione: Effettuare il push di notifiche in base alla posizione con Hub di notifica di Azure e i dati spaziali di BingTutorial: Push location-based notifications with Azure Notification Hubs and Bing Spatial Data

In questa esercitazione si apprenderà come recapitare le notifiche push in base alla posizione con Hub di notifica di Azure e i dati spaziali di Bing.In this tutorial, you learn how to deliver location-based push notifications with Azure Notification Hubs and Bing Spatial Data.

In questa esercitazione vengono completati i passaggi seguenti:In this tutorial, you take the following steps:

  • Configurare l'origine datiSet up the data source
  • Configurare l'applicazione UWPSet up the UWP application
  • Configurare il servizio back-endSet up the backend
  • Testare le notifiche push nelle app della piattaforma UWP (Universal Windows Platform)Test push notifications in the Universal Windows Platform (UWP) app

prerequisitiPrerequisites

Configurare l'origine datiSet up the data source

  1. Accedere a Bing Maps Dev Center.Log in to the Bing Maps Dev Center.
  2. Sulla barra di spostamento in alto, selezionare Origini dati e quindi Gestisci origini dati.In the top navigation bar, select Data sources, and select Manage Data Sources.

  3. Se non si dispone di un'origine dati esistente, viene visualizzato un collegamento per creare un'origine dati.If you don't have an existing data source, you see a link to create a data source. Selezionare Carica dati come origine dati.Select Upload data as a data source. È anche possibile usare il menu Origini dati > Carica dati.You can also use Data sources > Upload data menu.

  4. Creare un file NotificationHubsGeofence.pipe sul disco rigido con il contenuto seguente: in questa esercitazione si userà un file di esempio basato su pipe che delimita un'area del porto di 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))
    

    Il file pipe rappresenta questa entità:The pipe file represents this entity:

  5. Nella pagina Carica un'origine dati, procedere come segue:In the Upload a data source page, do the following actions:

    1. Selezionare pipe per Formato dati.Select pipe for Data format.
    2. Individuare e selezionare il file NotificationHubGeofence.pipe creato nel passaggio precedente.Browse and select NotificationHubGeofence.pipe file that you created in the previous step.
    3. Selezionare il pulsante Carica.Select Upload button.

      Nota

      È possibile che venga richiesto di specificare una nuova chiave per Master Key (Chiave master) diversa da Query Key (Chiave di query).You might be prompted to specify a new key for the Master Key that is different from the Query Key. Creare semplicemente una nuova chiave tramite il dashboard e aggiornare la pagina di caricamento dell'origine dati.Simply create a new key through the dashboard and refresh the data source upload page.

  6. Dopo aver caricato il file di dati, è necessario assicurarsi di pubblicare l'origine dati.Once you upload the data file, you need to make sure that you publish the data source. Selezionare Origini dati -> Gestisci origini dati come in precedenza.Select Data sources -> Manage Data Sources like you did before.
  7. Selezionare l'origine dati nell'elenco e scegliere Pubblica nella colonna Azioni.Select your data source in the list, and choose Publish in the Actions column.

  8. Passare alla scheda Origini dati pubblicati e verificare di visualizzare l'origine dati nell'elenco.Switch to the Published Data Sources tab, and confirm that you see your data source in the list.

  9. Selezionare Modifica.Select Edit. Vengono visualizzate (riepilogo) le posizioni introdotte nei dati.You see (at a glance) what locations you introduced in the data.

    A questo punto, il portale non visualizza i limiti del recinto virtuale creato. È sufficiente avere la conferma che la posizione specificata sia in prossimità del punto corretto.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. Ora sono disponibili tutti i requisiti per l'origine dati.Now you have all the requirements for the data source. Per altre informazioni sull'URL della richiesta per la chiamata API, in Bing Maps Dev Center fare clic su Data sources (Origini dati) e selezionare Data Source Information (Informazioni origine dati).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.

    L'URL query su cui è possibile eseguire query per verificare se il dispositivo si trova o meno entro i limiti di una posizione.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. Per eseguire questa verifica è sufficiente eseguire una chiamata GET con l'URL della query, aggiungendo i parametri seguenti: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
    

    Bing Maps esegue automaticamente i calcoli per determinare se il dispositivo è all'interno del confine virtuale.Bing Maps automatically performs the calculations to see whether the device is within the geofence. Dopo l'esecuzione della richiesta tramite un browser (o cURL), si ottiene una risposta JSON standard:Once you execute the request through a browser (or cURL), you get a standard JSON response:

    Questa risposta viene restituita solo quando il punto è effettivamente entro i limiti designati.This response only happens when the point is actually within the designated boundaries. In caso contrario, si ottiene un bucket results vuoto:If it is not, you get an empty results bucket:

Configurare l'applicazione UWPSet up the UWP application

  1. In Visual Studio avviare un nuovo progetto di tipo App vuota (Windows universale).In Visual Studio, start a new project of type Blank App (Universal Windows).

    Una volta completata la creazione del progetto, saranno disponibili tutte le potenzialità per l'app stessa.Once the project creation is complete, you should have the harness for the app itself. Ora si procederà alla configurazione dell'intera struttura del recinto virtuale.Now let’s set up everything for the geo-fencing infrastructure. Poiché a questo scopo si vogliono usare i servizi di Bing per questa soluzione, è disponibile un endpoint API REST pubblico che consente di eseguire query su frame di posizione specifici: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/

    Per renderlo funzionante, specificare i parametri seguenti:Specify the following parameters to get it working:

    • ID origine dati e Nome origine dati: nell'API Bing Maps le origini dati contengono diversi metadati suddivisi in bucket, ad esempio posizioni e orario di ufficio dell'operazione.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 entità : l'entità che si vuole usare come punto di riferimento per la notifica.Entity Name – the entity you want to use as a reference point for the notification.
    • Chiave API di Bing Maps: la chiave ottenuta in precedenza durante la creazione dell'account Bing Dev Center.Bing Maps API Key – The key that you obtained earlier when you created the Bing Dev Center account.

      Ora che l'origine dati è pronta, è possibile iniziare a usare l'applicazione UWP.Now that you have the data source ready, you can start working on the UWP application.

  2. Abilitare i servizi di posizione per l'applicazione.Enable location services for your application. Aprire il Package.appxmanifest file in Esplora soluzioni.Open the Package.appxmanifest file in Solution Explorer.

  3. Nella scheda delle proprietà del pacchetto appena aperta passare alla scheda Funzionalità e selezionare Posizione.In the package properties tab that just opened, switch to the Capabilities tab, and select Location.

  4. Creare una nuova cartella denominata Core nella soluzione e aggiungervi un nuovo file denominato LocationHelper.cs:Create a new folder in your solution named Core, and add a new file within it, named LocationHelper.cs:

    La classe LocationHelper include il codice per ottenere la posizione dell'utente tramite l'API di 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;
                        }
                }
            }
    
        }
    }
    

    Per altre informazioni su come ottenere la posizione dell'utente nelle app UWP, vedere Ottenere la posizione dell'utente.To learn more about getting the user’s location in UWP apps, seeGet the user's location.

  5. Per verificare che l'acquisizione della posizione funzioni effettivamente, aprire il lato del codice della pagina principale (MainPage.xaml.cs).To check that the location acquisition is actually working, open the code side of your main page (MainPage.xaml.cs). Creare un nuovo gestore eventi per l'evento Loaded nel costruttore MainPage.Create a new event handler for the Loaded event in the MainPage constructor.

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

    Ecco l'implementazione del gestore eventi: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. Eseguire l'applicazione e consentire di accedere alla posizione.Run the application and allow it to access your location.

  7. Una volta avviata l'applicazione, sarà possibile visualizzare le coordinate nella finestra Output :Once the application launches, you should be able to see the coordinates in the Output window:

    Dopo aver stabilito che l'acquisizione della posizione funziona, è possibile rimuovere il gestore dell'evento per Loaded, perché non verrà più usato.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. Il passaggio successivo consiste nell'acquisire le modifiche della posizione.The next step is to capture location changes. Nella classe LocationHelper aggiungere il gestore dell'evento per PositionChanged:In the LocationHelper class, add the event handler for PositionChanged:

    geolocator.PositionChanged += Geolocator_PositionChanged;
    

    L'implementazione mostra le coordinate della posizione nella finestra Output: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));
        });
    }
    

Configurare il servizio back-endSet up the backend

  1. Scaricare l' esempio di back-end .NET da GitHub.Download the .NET Backend Sample from GitHub.
  2. Al termine del download, aprire la cartella NotifyUsers e successivamente il file NotifyUsers.sln in Visual Studio.Once the download completes, open the NotifyUsers folder, and then open NotifyUsers.sln file in Visual Studio.
  3. Impostare il progetto AppBackend come Progetto di avvio e avviarlo.Set the AppBackend project as the StartUp Project and launch it.

    Il progetto è già configurato per l'invio di notifiche push ai dispositivi di destinazione, quindi sarà necessario eseguire solo due operazioni, ovvero specificare la stringa di connessione con quella corretta per l'hub di notifica e aggiungere l'identificazione del limite per inviare la notifica solo quando l'utente si trova all'interno del recinto virtuale.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. Per configurare la stringa di connessione, nella cartella Models aprire Notifications.cs.To configure the connection string, in the Models folder open Notifications.cs. La funzione NotificationHubClient.CreateClientFromConnectionString deve contenere le informazioni sull'hub di notifica che è possibile ottenere dal portale di Azure, ovvero in Impostazioni nella pagina Criteri di accesso.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). Salvare il file di configurazione aggiornato.Save the updated configuration file.
  5. Creare un modello per il risultato dell'API Bing Maps.Create a model for the Bing Maps API result. Il modo più semplice è aprire la cartella Models e scegliere Aggiungi > Classe.The easiest way to do that is to open the Models folder and choose Add > Class. Denominarlo GeofenceBoundary.cs.Name it GeofenceBoundary.cs. Al termine, copiare JSON dalla risposta API ottenuta nella prima sezione.Once done, copy the JSON from the API response that you got in the first section. In Visual Studio, usare Modifica > Incolla speciale > Incolla JSON come classi.In Visual Studio, use Edit > Paste Special > Paste JSON as Classes.

    In questo modo si assicura che l'oggetto viene deserializzato esattamente nel modo previsto.This way you ensure that the object is deserialized exactly as it was intended. Il set di classi risultante sarà analogo alla classe seguente: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. Aprire quindi Controllers > NotificationsController.cs.Next, open Controllers > NotificationsController.cs. Aggiornare la chiamata Post per tenere conto della longitudine e latitudine della destinazione.Update the Post call to account for the target longitude and latitude. A questo scopo, è sufficiente aggiungere due stringhe alla firma della funzione: 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. Creare una nuova classe all'interno del progetto chiamata ApiHelper.cs. Verrà usata per connettersi a Bing per controllare le intersezioni dei limiti del punto.Create a new class within the project called ApiHelper.cs – you use it to connect to Bing to check point boundary intersections. Implementare una funzione IsPointWithinBounds come illustrato nel codice seguente: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

    Assicurarsi di sostituire l'endpoint API con l'URL della query ottenuto in precedenza da Bing Dev Center (lo stesso vale per la chiave 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 sono presenti risultati per la query, significa che il punto specificato si trova entro i limiti del recinto virtuale, quindi la funzione viene restituita 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 non sono presenti risultati, significa che il punto è all'esterno del frame di ricerca, quindi la funzione restituisce false.If there are no results, Bing is telling you that the point is outside the lookup frame, so the function returns false.

  8. In NotificationsController.cs creare un controllo prima dell'istruzione 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;
        }
    }
    

Testare le notifiche push nell'app UWPTest push notifications in the UWP app

  1. Nell'app UWP si sarà in grado di testare le notifiche.In the UWP app, you should now be able to test notifications. Nella classe LocationHelper creare una nuova funzione 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

    Impostare POST_URL nel percorso dell'applicazione web distribuita.Set the POST_URL to the location of your deployed web application. Per ora è possibile eseguirla in locale, ma quando si lavora alla distribuzione di una versione pubblica, sarà necessario ospitarla presso un provider esterno.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. Registrare l'app UWP per le notifiche push.Register the UWP app for push notifications. In Visual Studio fare clic su Progetto > Store > Associa applicazione a Store.In Visual Studio, choose Project > Store > Associate app with the store.

  3. Dopo l'accesso con l'account per sviluppatore, assicurarsi di selezionare un'app esistente o crearne una nuova a cui si deve associare il pacchetto.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. Usare Dev Center e aprire l'app creata.Go to the Dev Center and open the app that you created. Fare clic su Servizi > Notifiche push > Sito dei servizi Live.Choose Services > Push Notifications > Live Services site.

  5. Nel sito prendere nota del segreto dell'applicazione e del SID del pacchetto.On the site, take note of the Application Secret and the Package SID. Saranno necessari entrambi nel portale di Azure. Aprire l'hub di notifica, fare clic su Impostazioni > Servizi di notifica > Windows (WNS) e immettere le informazioni nei campi obbligatori.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. Scegliere Salva.Choose Save.
  7. In Esplora soluzioni aprire Riferimenti e scegliere Gestisci pacchetti NuGet.Open References in Solution Explorer and select Manage NuGet Packages. Aggiungere un riferimento alla libreria gestita del bus di servizio di Microsoft Azure. Cercare semplicemente WindowsAzure.Messaging.Managed e aggiungerlo al progetto.Add a reference to the Microsoft Azure Service Bus managed library – simply search for WindowsAzure.Messaging.Managed and add it to your project.

  8. A scopo di test, creare di nuovo il gestore eventi MainPage_Loaded e aggiungervi questo frammento di codice: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.");
    }
    

    Il codice registra l'app con l'hub di notifica.The code registers the app with the notification hub. Ora si è pronti per iniziare.You are ready to go!

  9. In LocationHelper, all'interno del gestore Geolocator_PositionChanged, è possibile aggiungere un frammento di codice di test che inserirà la posizione all'interno del recinto virtuale in modo forzato: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. Poiché non vengono passate le coordinate reali (è possibile che al momento non ci si trovi entro i limiti) e si usano valori di test predefiniti, al momento dell'aggiornamento verrà visualizzata una notifica: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:

Passaggi successiviNext steps

È possibile eseguire un paio di passaggi per assicurarsi che la soluzione sia pronta per la produzione.There are a couple of steps that you might need to follow to make the solution production-ready.

  1. Prima è necessario assicurarsi che i recinti virtuali siano dinamici.First, you need to ensure that geofences are dynamic. A questo scopo è necessario eseguire altre operazioni con l'API Bing per poter caricare nuovi limiti nell'origine dati esistente.It requires some extra work with the Bing API to be able to upload new boundaries within the existing data source. Per altre informazioni, vedere Documentazione dell'API dei servizi dati spaziali di Bing.For more information, see Bing Spatial Data Services API documentation.
  2. Dato che lo scopo è assicurarsi che le notifiche siano recapitate ai partecipanti corretti, è consigliabile usare l' assegnazione di tag.Second, as you are working to ensure that the delivery is done to the right participants, you might want to target them via tagging.

La soluzione illustrata in questa esercitazione descrive uno scenario in cui è possibile avere un'ampia gamma di piattaforme di destinazione, quindi il recinto virtuale non limita le funzionalità specifiche del 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. Ciò premesso, la piattaforma UWP (Universal Windows Platform) offre funzionalità per rilevare automaticamente i recinti virtuali.That said, the Universal Windows Platform offers capabilities to detect geofences right out-of-the-box.