Condividi tramite


Esercitazione: Inviare notifiche push basate sulla posizione con Hub di notifica e Dati spaziali Bing

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 questa esercitazione vengono completati i passaggi seguenti:

  • Configurare l'origine dati
  • Configurare l'applicazione UWP
  • Configurare il servizio back-end
  • Testare le notifiche push nelle app della piattaforma UWP (Universal Windows Platform)

Prerequisiti

Configurare l'origine dati

  1. Accedere a Bing Maps Dev Center.

  2. Sulla barra di spostamento in alto, selezionare Origini dati e quindi Gestisci origini dati.

    Screenshot di Bing Maps Dev Center nella pagina Manage Data Sources con l'opzione Upload data as a data source con contorno rosso.

  3. Se non si dispone di un'origine dati esistente, viene visualizzato un collegamento per creare un'origine dati. Selezionare Carica dati come origine dati. È anche possibile usare il menu Origini dati>Carica dati.

    Screenshot della finestra di dialogo Carica un'origine dati.

  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:

    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à:

    Screenshot di una mappa del lungomare di San Francisco con un poligono rosso che delinea un'area dei moli.

  5. Nella pagina Carica un'origine dati, procedere come segue:

    1. Selezionare pipe per Formato dati.

    2. Individuare e selezionare il file NotificationHubGeofence.pipe creato nel passaggio precedente.

    3. Selezionare il pulsante Carica.

      Nota

      È possibile che venga richiesto di specificare una nuova chiave per Master Key (Chiave master) diversa da Query Key (Chiave di query). Creare semplicemente una nuova chiave tramite il dashboard e aggiornare la pagina di caricamento dell'origine dati.

  6. Dopo aver caricato il file di dati, è necessario assicurarsi di pubblicare l'origine dati. Selezionare Origini dati - >Gestisci origini dati come in precedenza.

  7. Selezionare l'origine dati nell'elenco e scegliere Pubblica nella colonna Azioni.

    Screenshot di Bing Maps Dev Center nella pagina Gestisci origini dati con la scheda Geocoded Data selezionata e l'opzione Publish con contorno rosso.

  8. Passare alla scheda Origini dati pubblicati e verificare di visualizzare l'origine dati nell'elenco.

    Screenshot di Bing Maps Dev Center nella pagina Manage Data Sources con la scheda Published Data Sources selezionata.

  9. Seleziona Modifica Vengono visualizzate (riepilogo) le posizioni introdotte nei dati.

    Screenshot della pagina Edit entity data che mostra una mappa degli Stati Uniti occidentali e un punto magenta sul waterfront di San Francisco.

    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.

  10. Ora sono disponibili tutti i requisiti per l'origine dati. 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).

    Screenshot di Bing Maps Dev Center nella pagina 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. Per eseguire questa verifica è sufficiente eseguire una chiamata GET con l'URL della query, aggiungendo i parametri seguenti:

    ?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. Dopo l'esecuzione della richiesta tramite un browser (o cURL), si ottiene una risposta JSON standard:

    Screenshot della risposta JSON standard.

    Questa risposta viene restituita solo quando il punto è effettivamente entro i limiti designati. In caso contrario, si ottiene un bucket results vuoto:

    Screenshot di una risposta JSON con un bucket results vuoto.

Configurare l'applicazione UWP

  1. In Visual Studio avviare un nuovo progetto di tipo App vuota (Windows universale).

    Screenshot della finestra di dialogo Nuovo progetto di Visual Studio con l'opzione App vuota (Windows universale) Visual C# evidenziata.

    Una volta completata la creazione del progetto, saranno disponibili tutte le potenzialità per l'app stessa. Ora si procederà alla configurazione degli elementi necessari per l'infrastruttura del recinto virtuale. 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:

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

    Per renderlo funzionante, specificare i parametri seguenti:

    • 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.

    • Nome entità : l'entità che si vuole usare come punto di riferimento per la notifica.

    • Chiave API di Bing Maps: la chiave ottenuta in precedenza durante la creazione dell'account Bing Dev Center.

      Ora che l'origine dati è pronta, è possibile iniziare a usare l'applicazione UWP.

  2. Abilitare i servizi di posizione per l'applicazione. Aprire il Package.appxmanifest file in Esplora soluzioni.

    Screenshot di Esplora soluzioni con il file Package.appxmanifest evidenziato.

  3. Nella scheda delle proprietà del pacchetto appena aperta passare alla scheda Funzionalità e selezionare Posizione.

    Screenshot della finestra di dialogo Proprietà pacchetto che mostra la scheda Funzionalità con l'opzione Posizione evidenziata.

  4. Creare una nuova cartella denominata Core nella soluzione e aggiungervi un nuovo file denominato LocationHelper.cs:

    Screenshot di Esplora soluzioni con la nuova cartella Core evidenziata.

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

    Per altre informazioni su come ottenere la posizione dell'utente nelle app della piattaforma UWP, vedere Ottenere la posizione dell'utente.

  5. Per verificare che l'acquisizione della posizione funzioni effettivamente, aprire il lato del codice della pagina principale (MainPage.xaml.cs). Creare un nuovo gestore eventi per l'evento Loaded nel costruttore MainPage.

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

    Ecco l'implementazione del gestore eventi:

    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.

    Screenshot della finestra di dialogo Let NotificationHubs.Geofence.

  7. Una volta avviata l'applicazione, sarà possibile visualizzare le coordinate nella finestra Output :

    Screenshot della finestra di output che visualizza le coordinate.

    Dopo aver stabilito che l'acquisizione della posizione funziona, è possibile rimuovere il gestore eventi per Loaded, perché non verrà più usato.

  8. Il passaggio successivo consiste nell'acquisire le modifiche della posizione. Nella classe LocationHelper aggiungere il gestore dell'evento per PositionChanged:

    geolocator.PositionChanged += Geolocator_PositionChanged;
    

    L'implementazione mostra le coordinate della posizione nella finestra Output:

    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-end

  1. Scaricare l' esempio di back-end .NET da GitHub.

  2. Al termine del download, aprire la cartella NotifyUsers e successivamente il file NotifyUsers.sln in Visual Studio.

  3. Impostare il progetto AppBackend come Progetto di avvio e avviarlo.

    Screenshot del menu della soluzione accessibile facendo clic con il pulsante destro del mouse con l'opzione Imposta come progetto di avvio evidenziata.

    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.

  4. Per configurare la stringa di connessione, nella cartella Models aprire 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. Salvare il file di configurazione aggiornato.

  5. Creare un modello per il risultato dell'API Bing Maps. Il modo più semplice è aprire la cartella Models e scegliere Aggiungi>Classe. Assegna il nomeGeofenceBoundary.cs. Al termine, copiare JSON dalla risposta API ottenuta nella prima sezione. In Visual Studio, usare Modifica>Incolla speciale>Incolla JSON come classi.

    In questo modo si assicura che l'oggetto viene deserializzato esattamente nel modo previsto. Il set di classi risultante sarà analogo alla classe seguente:

    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. Apri quindi Controllers>NotificationsController.cs. Aggiornare la chiamata Post per tenere conto della longitudine e latitudine della destinazione. A questo scopo, è sufficiente aggiungere due stringhe alla firma della funzione: latitude e 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. Implementare una funzione IsPointWithinBounds come illustrato nel codice seguente:

    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).

    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. Se non sono presenti risultati, significa che il punto è all'esterno del frame di ricerca, quindi la funzione restituisce false.

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

Testare le notifiche push nell'app UWP

  1. Nell'app UWP si sarà in grado di testare le notifiche. Nella classe LocationHelper creare una nuova funzione 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. Per ora è possibile eseguirla in locale, ma quando si distribuisce una versione pubblica, sarà necessario ospitarla presso un provider esterno.

  2. Registrare l'app UWP per le notifiche push. In Visual Studio fare clic su Progetto>Store>Associa applicazione a Store.

    Screenshot del menu della soluzione accessibile facendo clic con il pulsante destro del mouse con le opzioni Store e Associa applicazione a Store evidenziate.

  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.

  4. Usare Dev Center e aprire l'app creata. Fare clic su Servizi>Notifiche push>Sito dei servizi Live.

  5. Nel sito prendere nota del segreto dell'applicazione e del SID del pacchetto. 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.

    Screenshot che mostra la pagina Impostazioni con le opzioni Servizi di notifica e Windows (WNS) evidenziate e i valori del SID e della chiave di sicurezza del pacchetto già inseriti.

  6. Scegliere Salva.

  7. In Esplora soluzioni aprire Riferimenti e scegliere Gestisci pacchetti NuGet. Aggiungere un riferimento alla libreria gestita del bus di servizio di Microsoft Azure. Cercare semplicemente WindowsAzure.Messaging.Managed e aggiungerlo al progetto.

    Screenshot della finestra di dialogo Gestisci pacchetti NuGet con il pacchetto WindowsAzure.Messaging.Managed evidenziato.

  8. A scopo di test, creare di nuovo il gestore eventi MainPage_Loaded e aggiungervi questo frammento di codice:

    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. Ora si è pronti per iniziare.

  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:

    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:

    Screenshot di un desktop Windows che visualizza il messaggio TEST.

Passaggi successivi

È possibile eseguire un paio di passaggi per assicurarsi che la soluzione sia pronta per la produzione.

  1. Prima è necessario assicurarsi che i recinti virtuali siano dinamici. A questo scopo è necessario eseguire altre operazioni con l'API Bing per poter caricare nuovi limiti nell'origine dati esistente. Per altre informazioni, vedere Documentazione dell'API dei servizi dati spaziali di Bing.
  2. Dato che lo scopo è assicurarsi che le notifiche siano recapitate ai partecipanti corretti, è consigliabile usare l' assegnazione di tag.

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. Ciò premesso, la piattaforma UWP (Universal Windows Platform) offre funzionalità per rilevare automaticamente i recinti virtuali.