共用方式為


關於使用行止動線追蹤功能的指導方針

Visits 功能可簡化位置追蹤的程式,使其針對許多應用程式的實際用途更有效率。 Visit 定義為使用者進入和離開的重要地理區域。 Visits 類似於地理柵欄 ,因為它們只允許使用者進入或離開特定感興趣的區域時通知應用程式,而不需要持續的位置追蹤,這可能會耗盡電池使用時間。 不過,與地理柵欄不同,Visit 區域會在平台層級動態識別,不需要由個別應用程式明確定義。 此外,應用程式將追蹤哪些 Visits 是透過單一的粒度設定處理的,而不是透過訂閱個別的地點來處理。

預備設定

在繼續進行之前,請確定您的應用程式能夠存取裝置的位置。 您必須在資訊清單中宣告 Location 功能,並呼叫 Geolocator.RequestAccessAsync 方法,以確保使用者授與應用程式位置權限。 如需如何執行這項操作的詳細資訊,請參閱取得使用者的位置

請記得將 Geolocation 命名空間新增至您的類別。 本指南中的所有程式碼片段都必須完成此動作才能運作。

using Windows.Devices.Geolocation;

檢查最新的 Visit

使用 Visits 追蹤功能最簡單的方式是擷取上次已知的 Visit 相關狀態變更。 狀態變更是平台記錄的事件,其中使用者進入/離開重要位置、上次報告之後有明顯移動,或使用者的位置遺失 (請參閱 VisitStateChange 列舉)。 狀態變更是由 Geovisit 執行個體表示。 若要擷取上次記錄狀態變更的 Geovisit 執行個體,只需在 GeovisitMonitor 類別中使用指定的方法即可。

注意

檢查上次記錄的 Visit 並不保證系統目前正在追蹤 Visits。 若要在發生時追蹤 Visits ,您必須在前景監視它們,或註冊背景追蹤 (請參閱以下各節)。

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 執行個體中的所有資訊轉換成容易讀取的字串。 它可以在本指南中的任何案例中使用,以協助提供有關回報的 Visits 的反應。

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

監視前景中的 Visits

上一節中使用的 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.
}

當應用程式完成對 Visit 相關狀態變更的監視時,應該停止監視並取消註冊事件處理常式。 每當應用程式暫停或關閉時,也應該這麼做。

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

監視背景中的 Visits

您也可以在背景工作中實作 Visit 監視,以便即使應用程式未開啟,也能在裝置上處理 Visit 相關活動。 這是建議的方法,因為這樣會更多功能並且節能。

本指南將使用建立及註冊跨處理序的背景工作中的模型,其中主要應用程式檔案位於專案中,背景工作檔案位於相同方案中的個別專案中。 如果您不熟悉背景工作的實作,建議您主要遵循該指引,然後在下面進行必要的替換,以建立處理 Visit 的背景工作。

注意

在下列程式碼片段中,為了簡單起見,錯誤處理和本機儲存裝置等一些重要功能不存在。 如需強大的背景 Visits 處理實作,請參閱範例應用程式

首先,請確定您的應用程式已宣告背景工作權限。 在 Package.appxmanifest 檔案的 Application/Extensions 元素中,新增下列延伸模組 (如果項目不存在,請新增 Extensions 項目)。

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

接下來,在背景工作類別的定義中,貼上下列程式碼。 這個背景工作的 Run 方法只會將觸發程序詳細資料 (其中包含 Visits 資訊) 傳遞至個別的方法。

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

這確定了 Tasks 命名空間中的 VisitBackgroundTask 背景工作類別將對 location 觸發類型執行某些操作。

您的應用程式現在應該能夠註冊 Visits 處理背景工作,而且每當裝置記錄 Visit 相關狀態變更時,應該啟動此工作。 您必須在背景工作類別中填入邏輯,以判斷此狀態變更資訊要怎麼做。