Linee guida per l'uso del monitoraggio delle visite

La funzionalità Visite semplifica il processo di rilevamento della posizione per renderlo più efficace per gli scopi pratici di molte app. Una visita è definita come un'area geografica significativa da cui l'utente entra ed esce. Le visite sono simili ai recinti virtuali in quanto consentono all'app di ricevere una notifica solo quando l'utente entra o esce da determinate aree di interesse, eliminando la necessità di un rilevamento continuo della posizione che può essere un prosciugamento della durata della batteria. Tuttavia, a differenza dei recinti virtuali, le aree Visita vengono identificate dinamicamente a livello di piattaforma e non devono essere definite in modo esplicito da singole app. Inoltre, la selezione che effettua Visite in un'app viene gestita da un'unica impostazione di granularità, anziché sottoscrivendo singole posizioni.

Impostazioni preliminari

Prima di procedere, assicurarsi che l'app sia in grado di accedere alla posizione del dispositivo. Sarà necessario dichiarare la funzionalità Location del manifesto e chiamare il metodo Geolocator.RequestAccessAsync per assicurarsi che gli utenti concedano all'app le autorizzazioni per la posizione. Per altre informazioni su come eseguire questa operazione, vedere Ottenere la posizione dell'utente.

Ricordarsi di aggiungere lo spazio dei nomi Geolocation alla classe. Questo sarà necessario per il funzionamento di tutti i frammenti di codice in questa guida.

using Windows.Devices.Geolocation;

Controllare la Visita più recente

Il modo più semplice per usare la funzionalità rilevamento Visite consiste nel recuperare l'ultima modifica dello stato correlata alla Visita nota. Una modifica dello stato è un evento registrato dalla piattaforma in cui l'utente entra o esce da una posizione di significatività, si verifica un movimento significativo dall'ultimo report o la posizione dell'utente viene persa (vedere l'enumerazione VisitStateChange). Le modifiche di stato sono rappresentate dalle istanze di Geovisit. Per recuperare l'istanza Geovisit per l'ultima modifica dello stato registrato, è sufficiente usare il metodo designato nella classe GeovisitMonitor.

Nota

Il controllo dell'ultima visita registrata non garantisce che le visite siano attualmente monitorate dal sistema. Per tenere traccia delle Visite man mano che si verificano, è necessario monitorarle in primo piano o registrarsi per il rilevamento in background (vedere le sezioni seguenti).

private async void GetLatestStateChange() {
    // retrieve the Geovisit instance
    Geovisit latestVisit = await GeovisitMonitor.GetLastReportAsync();

    // Using the properties of "latestVisit", parse out the time that the state 
    // change was recorded, the device's location when the change was recorded,
    // and the type of state change.
}

Analizzare un'istanza di Geovisit (facoltativo)

Il metodo seguente converte tutte le informazioni archiviate in un'istanza Geovisit in una stringa facilmente leggibile. Può essere usato in uno degli scenari di questa guida per fornire commenti e suggerimenti per le Visite segnalate.

private string ParseGeovisit(Geovisit visit){
    string visitString = null;

    // Use a DateTimeFormatter object to process the timestamp. The following
    // format configuration will give an intuitive representation of the date/time
    Windows.Globalization.DateTimeFormatting.DateTimeFormatter formatterLongTime;
    
    formatterLongTime = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter(
        "{hour.integer}:{minute.integer(2)}:{second.integer(2)}", new[] { "en-US" }, "US", 
        Windows.Globalization.CalendarIdentifiers.Gregorian, 
        Windows.Globalization.ClockIdentifiers.TwentyFourHour);
    
    // use this formatter to convert the timestamp to a string, and add to "visitString"
    visitString = formatterLongTime.Format(visit.Timestamp);

    // Next, add on the state change type value
    visitString += " " + visit.StateChange.ToString();

    // Next, add the position information (if any is provided; this will be null if 
    // the reported event was "TrackingLost")
    if (visit.Position != null) {
        visitString += " (" +
        visit.Position.Coordinate.Point.Position.Latitude.ToString() + "," +
        visit.Position.Coordinate.Point.Position.Longitude.ToString() + 
        ")";
    }

    return visitString;
}

Monitorare le Visite in primo piano

La classe GeovisitMonitor usata nella sezione precedente gestisce anche lo scenario di ascolto delle modifiche di stato in un periodo di tempo. A tale scopo, è possibile creare un'istanza di questa classe, registrare un metodo del gestore per il relativo evento e chiamare il metodo Start.

// this GeovisitMonitor instance will belong to the class scope
GeovisitMonitor monitor;

public void RegisterForVisits() {

    // Create and initialize a new monitor instance.
    monitor = new GeovisitMonitor();
    
    // Attach a handler to receive state change notifications.
    monitor.VisitStateChanged += OnVisitStateChanged;
    
    // Calling the start method will start Visits tracking for a specified scope:
    // For higher granularity such as venue/building level changes, choose Venue.
    // For lower granularity in the range of zipcode level changes, choose City.
    monitor.Start(VisitMonitoringScope.Venue);
}

In questo esempio, il metodo OnVisitStateChanged gestisce i report Visita in ingresso. L'istanza Geovisit corrispondente viene passata tramite il parametro dell'evento.

private void OnVisitStateChanged(GeoVisitWatcher sender, GeoVisitStateChangedEventArgs args) {
    Geovisit visit = args.Visit;
    
    // Using the properties of "visit", parse out the time that the state 
    // change was recorded, the device's location when the change was recorded,
    // and the type of state change.
}

Al termine del monitoraggio dell'app per le modifiche dello stato correlate a Visit, l'app deve arrestare il monitoraggio e annullare la registrazione dei gestori eventi. Questa operazione deve essere eseguita anche ogni volta che l'app viene sospesa o chiusa.

public void UnregisterFromVisits() {
    
    // Stop the monitor to stop tracking Visits. Otherwise, tracking will
    // continue until the monitor instance is destroyed.
    monitor.Stop();
    
    // Remove the handler to stop receiving state change events.
    monitor.VisitStateChanged -= OnVisitStateChanged;
}

Monitorare le visite in background

Si può anche implementare il monitoraggio visit in un'attività in background, in modo che l'attività relativa a Visit possa essere gestita nel dispositivo anche quando l'app non è aperta. Questo è il metodo consigliato, perché è più versatile ed energeticamente efficiente.

Questa guida usa il modello in Creare e registrare un'attività in background out-of-process, in cui i file principali dell'applicazione risiedono in un progetto e il file di attività in background si trova in un progetto separato nella stessa soluzione. Se non si ha esperienza nell'implementazione delle attività in background, è consigliabile seguire principalmente queste indicazioni, effettuando le sostituzioni necessarie di seguito per creare un'attività in background di gestione delle visite.

Nota

Nei frammenti di codice seguenti alcune importanti funzionalità, ad esempio la gestione degli errori e l'archiviazione locale, sono assenti per semplicità. Per un'implementazione affidabile della gestione delle visite in background, vedere l'app di esempio.

Assicurarsi prima di tutto che l'app abbia dichiarato le autorizzazioni per le attività in background. Nell'elemento Application/Extensions del file Package.appxmanifest aggiungere l'estensione seguente (aggiungere un elemento Extensions se non ne esiste già uno).

<Extension Category="windows.backgroundTasks" EntryPoint="Tasks.VisitBackgroundTask">
    <BackgroundTasks>
        <Task Type="location" />
    </BackgroundTasks>
</Extension>

Nella definizione della classe dell'attività in background incollare quindi il codice seguente. Il metodo Run di questa attività in background passa semplicemente i dettagli del trigger (che contengono le informazioni visite) in un metodo separato.

using Windows.ApplicationModel.Background;

namespace Tasks {
    
    public sealed class VisitBackgroundTask : IBackgroundTask {
        
        public void Run(IBackgroundTaskInstance taskInstance) {
            
            // get a deferral
            BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
            
            // this task's trigger will be a Geovisit trigger
            GeovisitTriggerDetails triggerDetails = taskInstance.TriggerDetails as GeovisitTriggerDetails;

            // Handle Visit reports
            GetVisitReports(triggerDetails);         

            finally {
                deferral.Complete();
            }
        }        
    }
}

Definire il metodo GetVisitReports in un punto qualsiasi della stessa classe.

private void GetVisitReports(GeovisitTriggerDetails triggerDetails) {

    // Read reports from the triggerDetails. This populates the "reports" variable 
    // with all of the Geovisit instances that have been logged since the previous
    // report reading.
    IReadOnlyList<Geovisit> reports = triggerDetails.ReadReports();

    foreach (Geovisit report in reports) {
        // Using the properties of "visit", parse out the time that the state 
        // change was recorded, the device's location when the change was recorded,
        // and the type of state change.
    }

    // Note: depending on the intent of the app, you many wish to store the
    // reports in the app's local storage so they can be retrieved the next time 
    // the app is opened in the foreground.
}

Successivamente, nel progetto principale dell'app, si dovrà eseguire la registrazione di questa attività in background. Creare un metodo di registrazione che può essere chiamato da un'azione dell'utente o viene chiamato ogni volta che la classe viene attivata.

// a reference to this registration should be declared at the class level
private IBackgroundTaskRegistration visitTask = null;

// The app must call this method at some point to allow future use of 
// the background task. 
private async void RegisterBackgroundTask(object sender, RoutedEventArgs e) {
    
    string taskName = "MyVisitTask";
    string taskEntryPoint = "Tasks.VisitBackgroundTask";

    // First check whether the task in question is already registered
    foreach (var task in BackgroundTaskRegistration.AllTasks) {
        if (task.Value.Name == taskName) {
            // if a task is found with the name of this app's background task, then
            // return and do not attempt to register this task
            return;
        }
    }
    
    // Attempt to register the background task.
    try {
        // Get permission for a background task from the user. If the user has 
        // already responded once, this does nothing and the user must manually 
        // update their preference via Settings.
        BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();

        switch (backgroundAccessStatus) {
            case BackgroundAccessStatus.AlwaysAllowed:
            case BackgroundAccessStatus.AllowedSubjectToSystemPolicy:
                // BackgroundTask is allowed
                break;

            default:
                // notify user that background tasks are disabled for this app
                //...
                break;
        }

        // Create a new background task builder
        BackgroundTaskBuilder visitTaskBuilder = new BackgroundTaskBuilder();

        visitTaskBuilder.Name = exampleTaskName;
        visitTaskBuilder.TaskEntryPoint = taskEntryPoint;

        // Create a new Visit trigger
        var trigger = new GeovisitTrigger();

        // Set the desired monitoring scope.
        // For higher granularity such as venue/building level changes, choose Venue.
        // For lower granularity in the range of zipcode level changes, choose City. 
        trigger.MonitoringScope = VisitMonitoringScope.Venue; 

        // Associate the trigger with the background task builder
        visitTaskBuilder.SetTrigger(trigger);

        // Register the background task
        visitTask = visitTaskBuilder.Register();      
    }
    catch (Exception ex) {
        // notify user that the task failed to register, using ex.ToString()
    }
}

Ciò stabilisce che una classe di attività in background chiamata VisitBackgroundTask nello spazio dei nomi Tasks eseguirà un'operazione con il tipo di trigger location.

L'app dovrebbe ora essere in grado di registrare l'attività in background di gestione delle visite e questa attività deve essere attivata ogni volta che il dispositivo registra una modifica dello stato correlato alla visita. Sarà necessario compilare la logica nella classe di attività in background per determinare le operazioni da eseguire con queste informazioni sulla modifica dello stato.