Notifiche push basate su recinto virtuale con Hub di notifica di Azure e dati spaziali di BingGeo-fenced push notifications with Azure Notification Hubs and Bing Spatial Data

Nota

Per completare l'esercitazione, è necessario disporre di un account Azure attivo.To complete this tutorial, you must have an active Azure account. Se non si dispone di un account, è possibile creare un account di valutazione gratuita in pochi minuti.If you don't have an account, you can create a free trial account in just a couple of minutes. Per informazioni dettagliate, vedere la pagina relativa alla versione di valutazione gratuita di Azure.For details, see Azure Free Trial.

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, sfruttando un'applicazione della piattaforma UWP (Universal Windows Platform).In this tutorial, you learn how to deliver location-based push notifications with Azure Notification Hubs and Bing Spatial Data, leveraged from within a Universal Windows Platform application.

PrerequisitiPrerequisites

Assicurarsi prima di tutto di avere tutti i prerequisiti software e relativi ai servizi:First and foremost, be sure that you have all the software and service pre-requisites:

IntroduzioneGetting Started

Si potrà quindi iniziare con la creazione del progetto.Let’s start by creating the project. 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, è disponibile un endpoint API REST pubblico che consente di eseguire query su frame di posizione specifici:Because we are going to use Bing services for this, there is a public REST API endpoint that allows us to query specific location frames:

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

Per renderlo funzionante, è necessario specificare i parametri seguenti:You must 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. Altre informazioni sono disponibili qui.You can read more about those here.
  • 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 : questa è la chiave ottenuta in precedenza durante la creazione dell'account Bing Dev Center.Bing Maps API Key – this is the key that you obtained earlier when you created the Bing Dev Center account.

Di seguito si esaminerà in dettaglio la configurazione per ognuno degli elementi precedenti.Let’s do a deep-dive on the set-up for each of the elements above.

Configurazione dell'origine datiSetting up the data source

È possibile configurare l'origine dati in Bing Maps Dev Center.You can set up the data source in the Bing Maps Dev Center. Nella barra di spostamento in alto scegliere Data Sources (Origini dati) > Manage Data Sources (Gestisci origini dati).In the top navigation bar, choose Data sources > Manage Data Sources.

Se l'API Bing Maps non è mai stata usata prima, molto probabilmente non saranno presenti origini dati, quindi è possibile crearne una scegliendo Data sources (Origini dati) > Upload data (Carica dati).If you have not worked with Bing Maps API before, most likely there won’t be any data sources present, so you can just create a new one by choosing Data sources > Upload data. Compilare tutti i campi obbligatori:Be sure you fill out all the required fields:

Ci si potrebbe chiedere che cos'è il file di dati e cosa si deve caricare.You might be wondering – what is the data file and what should you be uploading? Ai fini di questo test, è possibile usare semplicemente l'esempio basato su pipe che delimita un'area del porto di San Francisco:For the purposes of this test, we can just use the sample pipe-based 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 codice precedente rappresenta questa entità:The above represents this entity:

Copiare e incollare la stringa precedente in un nuovo file, salvarlo con il nome NotificationHubsGeofence.pipe, quindi caricarlo in Bing Dev Center.Copy and paste the string above into a new file, save it as NotificationHubsGeofence.pipe, and upload it in the Bing Dev Center.

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.

Dopo aver caricato il file di dati, è necessario assicurarsi di pubblicare l'origine dati.Once you upload the data file, you will need to make sure that you publish the data source.

Passare a Manage Data Sources (Gestisci origini dati), come in precedenza, trovare l'origine dati nell'elenco e fare clic su Publish (Pubblica) nella colonna Actions (Azioni).Go to Manage Data Sources, just like we did above, find your data source in the list, and choose Publish in the Actions column. Dopo un attimo l'origine dati verrà visualizzata nella scheda Published Data Sources :In a bit, you should see your data source in the Published Data Sources tab:

Se si fa clic su Edit (Modifica), si potrà vedere un riepilogo delle posizioni inserite:If you choose Edit, you will be able to see (at a glance) what locations you introduced in it:

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.

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'opzione da esaminare è Query URL .The Query URL is what we’re after here. Si tratta dell'endpoint su cui è possibile eseguire query per verificare se il dispositivo si trova o meno entro i limiti di una posizione.This is the endpoint against which we 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, we 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

In questo modo si specifica un punto di destinazione ottenuto dal dispositivo e Bing Maps esegue automaticamente i calcoli per vedere se si trova all'interno del recinto virtuale.That way you're specifying a target point that we obtain from the device and Bing Maps will automatically perform the calculations to see whether it is within the geofence. Dopo l'esecuzione della richiesta tramite un browser (o cURL), si otterrà una risposta JSON standard:Once you execute the request through a browser (or cURL), you will 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 otterrà un bucket results vuoto:If it is not, you will get an empty results bucket:

Configurazione dell'applicazione UWPSetting up the UWP application

Ora che l'origine dati è pronta, è possibile iniziare a utilizzare l'applicazione UWP avviata in precedenza.Now that we have the data source ready, we can start working on the UWP application that we bootstrapped earlier.

Prima di tutto è necessario abilitare i servizi di posizione per l'applicazione.First and foremost, we must enable location services for our application. A questo scopo aprire il file Package.appxmanifest in Esplora soluzioni.To do this, open the Package.appxmanifest file in Solution Explorer.

Nella scheda delle proprietà del pacchetto appena aperta fare clic su Funzionalità e assicurarsi di selezionare Posizione:In the package properties tab that just opened, choose Capabilities and be sure that you select Location:

Dopo aver dichiarato la funzionalità Posizione, creare una nuova cartella denominata Core nella soluzione e aggiungervi un nuovo file denominato LocationHelper.cs:As the location capability is declared, create a new folder in your solution named Core, and add a new file within it, named LocationHelper.cs:

La classe LocationHelper stessa a questo punto è abbastanza semplice: consente solo di ottenere la posizione dell'utente tramite l'API di sistema:The LocationHelper class itself is fairly basic at this point – all it does is let us 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 il documento ufficiale su MSDN.You can read more about getting the user’s location in UWP apps in the official MSDN document.

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));
    }
}

Si noti che il gestore è dichiarato come async, perché GetCurrentLocation è di tipo awaitable e quindi richiede l'esecuzione in un contesto asincrono.Notice that we declared the handler as async because GetCurrentLocation is awaitable, and therefore requires to be executed in an async context. Poiché in alcuni casi è possibile che venga restituita una posizione Null, ad esempio i servizi di posizione sono disabilitati o all'applicazione sono state negate le autorizzazioni per l'accesso alla posizione, è necessario assicurarsi che sia gestito correttamente con un controllo Null.Also, because under certain circumstances we might end up with a null location (for example, the location services are disabled or the application was denied permissions to access location), we need to make sure that it is properly handled with a null check.

Eseguire l'applicazione.Run the application. Accertarsi di consentire l'accesso alla posizione:Make sure you allow location access:

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 test per Loaded, perché non verrà più usato.Now you know that location acquisition works – feel free to remove the test event handler for Loaded because we won’t be using it anymore.

Il passaggio successivo consiste nell'acquisire le modifiche della posizione.The next step is to capture location changes. A questo scopo, tornare alla classe LocationHelper e aggiungere il gestore eventi per PositionChanged:For that, let’s go back to the LocationHelper class and add the event handler for PositionChanged:

geolocator.PositionChanged += Geolocator_PositionChanged;

L'implementazione mostrerà le coordinate della posizione nella finestra Output :The implementation will show 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));
    });
}

Configurazione del back-endSetting up the backend

Scaricare l' esempio di back-end .NET da GitHub.Download the .NET Backend Sample from GitHub. Al termine del download, aprire la cartella NotifyUsers e successivamente il file NotifyUsers.sln.Once the download completes, open the NotifyUsers folder, and subsequently – the NotifyUsers.sln file.

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 sostituire 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 we’ll need to do only two things – swap out the right connection string for the notification hub and add boundary identification to send the notification only when the user is within the geofence.

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 nel pannello 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 blade in Settings). Salvare il file di configurazione aggiornato.Save the updated configuration file.

A questo punto è necessario creare un modello per il risultato dell'API Bing Maps.Now we need to 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 open the Models folder and choose Add > Class. Denominarlo GeofenceBoundary.cs.Name it GeofenceBoundary.cs. Al termine, copiare il codice JSON dalla risposta dell'API descritta nella prima sezione e in Visual Studio usare Modifica > Incolla speciale > Incolla JSON come classi.Once done, copy the JSON from the API response that we discussed in the first section and in Visual Studio use Edit > Paste Special > Paste JSON as Classes.

In questo modo si assicura che l'oggetto verrà deserializzato esattamente nel modo previsto.This way we ensure that the object will be deserialized exactly as it was intended. Il set di classi risultante sarà analogo al seguente:Your resulting class set should resemble this:

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; }
    }
}

Aprire quindi Controllers > NotificationsController.cs.Next, open Controllers > NotificationsController.cs. È necessario modificare la chiamata Post per tenere conto della longitudine e latitudine della destinazione.We need to tweak 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.For that, simply 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)

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 – we’ll use it to connect to Bing to check point boundary intersections. Implementare una funzione IsPointWithinBounds simile alla seguente:Implement a IsPointWithinBounds function, like this:

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;
        }
    }
}

Nota

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 viene restituito true.If there are results to the query, that means that the specified point is within the boundaries of the geofence, so we return true. Se non sono presenti risultati, significa che il punto è all'esterno del frame di ricerca, quindi viene restituito false.If there are no results, Bing is telling us that the point is outside the lookup frame, so we return false.

Tornare a NotificationsController.cse creare un controllo prima dell'istruzione switch:Back 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;
    }
}

In questo modo la notifica viene inviata solo se il punto si trova entro i limiti.That way, the notification is only sent when the point is within the boundaries.

Test delle notifiche push nell'app UWPTesting push notifications in the UWP app

Tornando all'app UWP si sarà in grado di testare le notifiche.Going back to the UWP app, we 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

Scambiare POST_URL con il percorso dell'applicazione Web distribuita creata nella sezione precedente.Swap the POST_URL to the location of your deployed web application that we created in the previous section. 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 will need to host it with an external provider.

È importante, a questo punto, accertarsi di registrare l'app UWP per le notifiche push.Let’s now make sure that we 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.

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.

Usare Dev Center e aprire l'app appena creata.Go to the Dev Center and open the app that you just created. Fare clic su Servizi > Notifiche push > Sito dei servizi Live.Choose Services > Push Notifications > Live Services site.

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 will need both in the Azure Portal – open your notification hub, choose Settings > Notification Services > Windows (WNS) and enter the information in the required fields.

Scegliere Salva.Choose Save.

In Esplora soluzioni aprire Riferimenti e scegliere Gestisci pacchetti NuGet.Open References in Solution Explorer and select Manage NuGet Packages. Sarà necessario aggiungere un riferimento alla libreria gestita del bus di servizio di Microsoft Azure. Cercare semplicemente WindowsAzure.Messaging.Managed e aggiungerlo al progetto.We will need to add a reference to the Microsoft Azure Service Bus managed library – simply search for WindowsAzure.Messaging.Managed and add it to your project.

A scopo di test, è possibile creare di nuovo il gestore eventi MainPage_Loaded e aggiungervi questo frammento di codice:For testing purposes, we can 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 precedente registra l'app con l'hub di notifica.The above registers the app with the notification hub. Ora si è pronti per iniziare.You are ready to go!

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 will forcefully put the location inside the geofence:

await LocationHelper.SendLocationToBackend("wns", "TEST_USER", "TEST", "37.7746", "-122.3858");

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 we are not passing the real coordinates (which might not be within the boundaries at the moment) and are using predefined test values, we will see a notification show up on update:

Passaggi successiviNext steps

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

Prima di tutto è necessario assicurarsi che i recinti virtuali siano dinamici.First and foremost, you might 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.This will require some extra work with the Bing API in order to be able to upload new boundaries within the existing data source. Per altre informazioni sull'argomento, vedere la documentazione dell'API dei servizi dati spaziali di Bing .Consult the Bing Spatial Data Services API documentation for more details on the subject.

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 sopra descrive uno scenario in cui è possibile avere un'ampia gamma di piattaforme di destinazione, quindi il recinto virtuale non è stato limitato alle funzionalità specifiche del sistema.The solution shown above describes a scenario in which you might have a wide variety of target platforms, so we did 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.

Per altri dettagli relativi alle funzionalità di Hub di notifica, vedere il portale di documentazione.For more details regarding Notification Hubs capabilities, check out our documentation portal.