Рекомендации по использованию функции отслеживания посещений

Функция "Визиты" упрощает процесс отслеживания расположения, чтобы сделать его более эффективным для практических целей многих приложений. Визит определяется как важная географическая область, в которую пользователь входит и выходит. Посещения аналогичны геозонам , что они позволяют приложению получать уведомления только при входе или выходе из определенных областей интереса, устраняя необходимость постоянного отслеживания расположения, которое может быть утечкой батареи. Однако в отличие от геозон, области посещения динамически определяются на уровне платформы и не должны быть явно определены отдельными приложениями. Кроме того, выбор того, какие посещения приложения будут отслеживаться, обрабатывается одним параметром детализации, а не путем подписки на отдельные места.

Предварительная настройка

Прежде чем идти дальше, убедитесь, что ваше приложение может получить доступ к расположению устройства. Необходимо объявить Location возможность в манифесте и вызвать метод Geolocator.RequestAccessAsync , чтобы убедиться, что пользователи предоставляют разрешения на расположение приложения. Дополнительные сведения о том, как это сделать, см. в разделе "Получение расположения пользователя".

Не забудьте добавить Geolocation пространство имен в класс. Это потребуется для всех фрагментов кода, приведенных в этом руководстве для работы.

using Windows.Devices.Geolocation;

Проверьте последнюю версию визита

Самый простой способ использовать функцию отслеживания посещений — получить последнее известное изменение состояния, связанного с посещением. Изменение состояния — это событие, зарегистрированное на платформе, в котором пользователь вводит или выходит из расположения значения, имеет значительное перемещение с момента последнего отчета, или расположение пользователя потеряно (см. перечисление VisitStateChange). Изменения состояния представлены экземплярами Geovisit . Чтобы получить экземпляр Geovisit для последнего записанного изменения состояния, просто используйте указанный метод в классе GeovisitMonitor.

Примечание.

Проверка последнего зарегистрированного визита не гарантирует, что посещения в настоящее время отслеживаются системой. Чтобы отслеживать посещения по мере их выполнения, необходимо либо отслеживать их на переднем плане, либо регистрировать для фонового отслеживания (см. разделы ниже).

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

Анализ экземпляра Geovisit (необязательно)

Следующий метод преобразует все сведения, хранящиеся в экземпляре Geovisit , в легко читаемую строку. Его можно использовать в любом из сценариев, приведенных в этом руководстве, для предоставления отзывов о передаваемых посещениях.

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

Мониторинг посещений на переднем плане

Класс GeovisitMonitor , используемый в предыдущем разделе, также обрабатывает сценарий прослушивания изменений состояния за период времени. Для этого можно создать экземпляр этого класса, зарегистрировать метод обработчика для его события и вызвать 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);
}

В этом примере OnVisitStateChanged метод будет обрабатывать входящие отчеты Visit. Соответствующий экземпляр Geovisit передается через параметр события.

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

Когда приложение завершит мониторинг изменений состояния, связанных с посещением, оно должно остановить монитор и отменить регистрацию обработчиков событий. Это также необходимо сделать всякий раз, когда приложение приостановлено или закрыто.

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

Мониторинг посещений в фоновом режиме

Вы также можете реализовать мониторинг посещений в фоновой задаче, чтобы действие, связанное с посещением, можно обрабатывать на устройстве, даже если приложение не открыто. Это рекомендуемый метод, так как он более универсальный и энергоэффективный.

В этом руководстве будет использоваться модель в разделе "Создание и регистрация фоновой задачи вне процесса", в которой основные файлы приложений живут в одном проекте, а файл фоновой задачи находится в отдельном проекте в одном решении. Если вы не знакомы с реализацией фоновых задач, рекомендуется в первую очередь следовать этому руководству, что делает необходимые подстановки ниже, чтобы создать фоновую задачу для обработки визитов.

Примечание.

В следующих фрагментах некоторые важные функции, такие как обработка ошибок и локальное хранилище, отсутствуют для простоты. Надежная реализация фоновой обработки посещений см. в примере приложения.

Сначала убедитесь, что приложение объявило разрешения фоновой задачи. В элементе Application/Extensions файла Package.appxmanifest добавьте следующее расширение (добавьте Extensions элемент, если он еще не существует).

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

Затем в определении фонового класса задач вставьте следующий код. Метод Run этой фоновой задачи просто передает сведения о триггере (которые содержат сведения о посещениях) в отдельный метод.

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

Определите GetVisitReports метод где-то в этом же классе.

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

Затем в основном проекте приложения необходимо выполнить регистрацию этой фоновой задачи. Создайте метод регистрации, который может вызываться некоторыми действиями пользователя или вызывается каждый раз при активации класса.

// 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()
    }
}

Это устанавливает, что класс фоновой задачи, вызываемой VisitBackgroundTask в пространстве Tasks имен, будет выполнять что-то с типом триггера location .

Теперь приложение должно быть способно зарегистрировать фоновую задачу для обработки посещений, и эта задача должна быть активирована всякий раз, когда устройство регистрирует изменение состояния, связанного с посещением. Вам потребуется заполнить логику в фоновом классе задач, чтобы определить, что делать с данными об изменении состояния.