Отслеживание местоположения Windows Phone 8.1

Я хочу реализовать приложение, которое постоянно отправляет позицию устройства в веб-службу. В документации я нашел класс Geolocation и некоторые статьи, где обсуждалось отслеживание местоположения:

Реализация обоих примерных проектов, обсуждаемых в этих статьях, я заметил, что событие geolocator_PositionChanged() не запускается при каждом обновлении позиции. Задержка (около 10/15 минут) между двумя исполнением события. Странно, что это происходит даже тогда, когда приложение выполняется на переднем плане (не только в фоновом режиме). Я использую эмулятор Windows Phone.

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

1) Как я могу отслеживать (без задержек) позицию устройства с использованием класса Geolocator?

Поиск по сети, я нашел класс GeoCoordinateWatcher, который обеспечивает непрерывное отслеживание местоположения устройства. Это код:

public MainPage()
{
    InitializeComponent();
    this.GetCoordinate();
}

private void GetCoordinate()
{
    var watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High)
    {
        MovementThreshold = 1
    };
    watcher.PositionChanged += this.watcher_PositionChanged;
    watcher.Start();
}

private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    //Get position data
    var pos = e.Position.Location;
    //Update mypos object
    mypos.update(pos.Latitude, pos.Longitude);
    //Update data on the main interface
    MainMap.SetView(mypos.getCoordinate(), MainMap.ZoomLevel, MapAnimationKind.Parabolic);
}

Он работает: событие watcher_PositionChanged() запускается без задержек.

2) Почему у GeoCoordinateWatcher нет задержек? В чем разница между классом GeoCoordinateWatcher и классом Geolocator?

Наконец, приложение должно отправить позицию устройства в веб-службу, даже если она не активна. Итак, мне нужна фоновая задача. Как предложил здесь Romasz, я могу использовать класс Geolocator с некоторыми ограничениями.

3) Могу ли я использовать GeoCoordinateWhatcher в фоновом режиме? Если да, то как?

Моя цель - реализовать приложение отслеживания местоположений без задержек, которое даже работает в фоновом режиме. Каков наилучший способ сделать это? Приложение должно отслеживать позицию устройства и постоянно обновлять веб-службу (даже в фоновом режиме). Как я могу это сделать? Каков наилучший подход? Я знаю о жизненном цикле Windows Phone Apps, и я могу принять некоторые ограничения для выполнения фона. Каковы пределы фона?

Ответ 1

К сожалению, Windows Phone 8.1 не поддерживает непрерывное отслеживание в фоновом режиме. Если вам нужна эта функция, вам придется разрабатывать приложение для Windows Phone 8. Надеюсь, они исправит это для 8.2, 9 или что-нибудь еще!

Ответ 2

Существует способ, которым вы можете добиться отслеживания местоположения, но он имеет свои ограничения. Этого не будет достаточно для спортивного приложения, но для многих других случаев использования он подойдет. Используйте Geofence и BackgroundTask с помощью LocationTrigger

Вот пример:

BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();

Geolocator locator = new Geolocator();
locator.DesiredAccuracyInMeters = 10;
locator.DesiredAccuracy = PositionAccuracy.High;

Geoposition currentPosition = await locator.GetGeopositionAsync(TimeSpan.FromMinutes(1),TimeSpan.FromSeconds(30));
Geocircle fenceCircle = new Geocircle(currentPosition.Coordinate.Point.Position,25);
Geofence newFence = new Geofence(GEOFENCE_NAME, fenceCircle, MonitoredGeofenceStates.Exited, false, TimeSpan.FromSeconds(1), DateTimeOffset.Now, TimeSpan.FromDays(30));
GeofenceMonitor.Current.Geofences.Add(newFence);

BackgroundTaskBuilder observerTaskBuilder = new BackgroundTaskBuilder();
observerTaskBuilder.Name = OBSERVER_TASK_NAME;
observerTaskBuilder.SetTrigger(new LocationTrigger(LocationTriggerType.Geofence));
observerTaskBuilder.TaskEntryPoint = OBSERVER_TASK_ENTRY_POINT;
observerTaskBuilder.Register();

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

Но имейте в виду, что BackgroundTask не нужно запускать, как только вы покидаете границы забора. Это может затянуться на несколько минут (я не заметил задержки более чем через минуту после того, как покинул круг). Как я сказал: недостаточно для спортивного приложения, но оно может удовлетворить ваши потребности.

Для получения более подробной информации смотрите здесь: http://msdn.microsoft.com/en-us/library/windows.devices.geolocation.geofencing.aspx

Для примера проекта смотрите здесь: https://code.msdn.microsoft.com/windowsapps/Geofencing-and-geolocation-d7ea0ef8

Примечание: Я читал, что настоятельно рекомендуется не использовать радиус меньше 50. Но в моих тестах 25 работал хорошо, поэтому вам лучше проверить, что вы сами.

Ответ 3

Я сделал то же самое, что и @christoph... Я просто добавил событие Entered... Мои обновления происходят каждые 2 минуты, ВСЕГДА.

    Geoposition currentPosition = await locator.GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(30));
        Geocircle fenceCircle = new Geocircle(currentPosition.Coordinate.Point.Position, 25);
        Geofence newFence = new Geofence("CURRENT_LOC" + Guid.NewGuid(), fenceCircle, MonitoredGeofenceStates.Exited | MonitoredGeofenceStates.Entered, false, TimeSpan.FromSeconds(1), DateTimeOffset.Now, TimeSpan.FromMinutes(10));