В первой статье говорилось о том, как использовать новый Location API на Windows Phone 8. В нем я не говорил о фоновом отслеживании. Сегодня я изменю предыдущее решение, чтобы сделать это и регистрировать события в окне вывода, а также предотвращать обновление пользовательского интерфейса, пока приложение деактивировано.
Начнем с сообщения ОС, что это приложение может отслеживать местоположение в фоновом режиме. Прежде всего, откройте файл WMAppManifest.xml в редакторе XML, щелкнув его правой кнопкой мыши и выбрав «Открыть с помощью».
Теперь мы заменим элемент DefaultTask следующим:
<DefaultTask Name="_default" NavigationPage="MainPage.xaml"> <BackgroundExecution> <ExecutionType Name="LocationTracking" /> </BackgroundExecution> </DefaultTask>
Затем мы добавляем обработчик события RunningInBackground. В файле App.xaml обновите элемент shell: PhoneApplicationService, добавив RunningInBackground = ”Application_RunningInBackground”, чтобы он выглядел следующим образом:
<shell:PhoneApplicationService Launching="Application_Launching" Closing="Application_Closing" Activated="Application_Activated" Deactivated="Application_Deactivated" RunningInBackground="Application_RunningInBackground"/>
И добавьте пустой обработчик в App.xaml. Мы вернемся к этому обработчику чуть позже.
private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs args) { }
Нам нужен способ сообщить приложению, что оно работает в фоновом режиме. К App.xaml.cs нам нужно добавить свойство bool. Будет установлено статическое значение, поэтому к нему легко обратиться:
public static bool InBackground { get; set; }
Теперь мы добавим возможность просмотра состояния приложения в окне отладки. Для этого нам нужно добавить следующее с помощью страниц App.xaml.cs и MainPage.xaml.cs:
using System.Diagnostics;
После этого мы можем начать обновлять следующие 4 события со следующими значениями App.InBackground:
укротитель | App.InBackground |
---|---|
Application_Launching | ложный |
Application_Activated | ложный |
Application_Deactivated | правда |
Application_RunningInBackground | правда |
Когда мы их установим, мы также добавим к каждому Debug.WriteLine, чтобы мы могли видеть, когда они запускаются. После этого они должны выглядеть так:
// Code to execute when the application is launching (eg, from Start) // This code will not execute when the application is reactivated private void Application_Launching(object sender, LaunchingEventArgs e) { Debug.WriteLine("Application Launching."); App.InBackground = false; } // Code to execute when the application is activated (brought to foreground) // This code will not execute when the application is first launched private void Application_Activated(object sender, ActivatedEventArgs e) { Debug.WriteLine("Application Activated."); App.InBackground = false; } // Code to execute when the application is deactivated (sent to background) // This code will not execute when the application is closing private void Application_Deactivated(object sender, DeactivatedEventArgs e) { Debug.WriteLine("Application Deactivated."); App.InBackground = true; } private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs args) { Debug.WriteLine("Running in background."); App.InBackground = true; }
Как видите, мы просто устанавливаем флаг, чтобы указать, работает ли приложение в фоновом режиме. Это может быть запеченный способ сделать это, но я сделал это таким образом.
Теперь мы можем обновить обработчик события geolocator_PositionChanged в файле MainPage.xaml.cs, чтобы зарегистрировать местоположение в окне отладки.
Debug.WriteLine(args.Position.Coordinate.Latitude.ToString("0.00000000") + " " + args.Position.Coordinate.Longitude.ToString("0.00000000"));
Последнее обновление заключается в использовании свойства App.InBackground в операторе if для отключения обновления пользовательского интерфейса. Мы используем Debug.WriteLine, чтобы сообщить нам местоположение в окне отладки.
if (App.InBackground == false) { Dispatcher.BeginInvoke(() => { Debug.WriteLine("UI Updated."); LatitudeTextBlock.Text = args.Position.Coordinate.Latitude.ToString("0.00000000"); LongitudeTextBlock.Text = args.Position.Coordinate.Longitude.ToString("0.00000000"); }); } else { Debug.WriteLine("UI NOT Updated."); }
Теперь мы можем запустить решение и увидеть в окне отладки (в левом нижнем углу) событие запуска приложения:
Нажатие на кнопку запускает отслеживание, и пользовательский интерфейс обновляется, а местоположение записывается в окно отладки:
Нажатие на местоположение карты в эмуляторе обновит интерфейс и зарегистрирует местоположение:
Теперь, если мы нажмем кнопку «Пуск», мы увидим, что приложение переключилось на фоновую задачу и вошло в систему как «Запуск в фоновом режиме». Нажатие на местоположение карты показывает, что местоположение все еще регистрируется, но пользовательский интерфейс не обновляется:
При повторном открытии приложения отображается огонь события «Активировано приложением», и при щелчке новых местоположений на карте пользовательский интерфейс снова обновляется:
И, наконец, выход из приложения с помощью кнопки «Назад» запускает событие «Закрытие приложения» и нажатие на новые местоположения на карте больше не регистрируется, поскольку приложение больше не работает в фоновом режиме:
Существуют лучшие практики, которые необходимо использовать при реализации любых операций с интенсивным использованием батареи, и службы определения местоположения ничем не отличаются. Установка свойства DesiredAccuracy объекта Geolocator в PositionAccuracy.Default вместо PositionAccuracy.High и отключение Location Location, когда в этом нет необходимости, позволит сэкономить батарею. Увеличение свойства MovementThreshold приведет к тому, что событие PositionChanged будет запускаться реже, что также сэкономит батарею.
Еще одна вещь, которую нужно иметь в виду, планируя некоторые или все службы определения местоположения, может быть недоступна, и ваше приложение должно обрабатывать эту ситуацию, не создавая исключений.
Как видите, непрерывное отслеживание местоположения телефона в режиме реального времени с приложением в фоновом режиме просто реализовать в приложениях Windows Phone 8.