Разработка под Windows Phone: Часть 5: Жизненный цикл приложения, фоновые сервисы и многозадачность
Для того, чтобы писать хорошие приложения, которыми пользователю удобно пользоваться, необходимо понимать, что из себя представляет жизненный цикл приложения Жизненный цикл и сохранение состояния приложения В Windows Phone только одно приложение может быть активно/запущено в каждый момент времени. Когда приложение перестаёт быть активным, операционная система переводит его в спящее состояние (dormant). Если памяти устройства недостаточно для хорошей работы активного приложения, операционная система начинает завершать спящие (dormant) приложения. При этом, последними будет завершены приложения, которые запускались недавно. Платформа Windows Phone предоставляет разработчику события, методы и объекты, которые он может использовать для необходимых действий на каждом жизненном цикле приложения. Приложение позволяет разработчику обработать события Launching, Closing, Activated и Deactivated события. Поскольку пользователь покидает какую-то страницу или приходит на какую-то страницу приложения, с этими событиями связаны два доступных для переопределения метода страниц приложения: OnNavigatedTo и OnNavogatedFrom. Для того, чтобы понять, как приложение и система взаимодействуют и какие возможности есть у разработчика, рассмотрим несколько сценариев жизненных циклов приложения. Пользователь запускает приложение со стартовой страницы телефона или списка приложений, работает с приложением, затем нажимает кнопку Back телефона, находясь на стартовой странице приложения:
Пользователь запускает приложение со стартовой страницы телефона или списка приложений, работает с приложением, затем нажимает кнопку перехода к стартовой странице телефона, находясь на любой странице приложения, а потом быстро возвращается обратно (операционная система не завершает приложение), используя длинное нажатие кнопки Back и выбирая страницу приложения, с которой он ушёл.
Что произойдёт, если операционной системе потребуется больше памяти, когда приложение находится в памяти в спящем состоянии? Тогда приложение завершит свою работу, но сохранит состояние стека навигации, а также состояние словарей состояния на уровне приложения (PhoneApplicationService.State) и на уровне страницы (PhoneApplicationPage.State) – перейдёт в состояние Tombstoned. Обратите внимание, чтоы выход из которого в разрезе возникающих событий и вызываемых методов не отличается от выхода из спящего (dormant) состояния, но при этом, поскольку приложение будет выгружено из памяти, необходимо позаботиться о сохранении данных для восстановления состояния приложения. Узнать об это разработчик может, проверив свойство IsApplicationInstancePreserved у ActivatedEventArgs. В случае true – это восстановление из спящего состояния, в случае же false – из Tombstone состояния. Одновременно система сохраняет состояние Tombstoned только для пяти приложений. Если пользователь не возвращается к приложению, данные удаляются, и приложение будет запускаться с событием Launching. Подробнее о жизненом цикле приложения можно прочитать по следующей ссылке: https://msdn.microsoft.com/en-us/library/ff769557(v=VS.92).aspx Давайте теперь на практике попробуем разобраться с сохранением состояния приложения. Создадим новое приложение на базе стандартного шаблона Windows Phone Application и назовём приложение ApplicationStateExample. Исправьте код XAML страницы приложения на следующий:
Соберите приложение и запустите его (F5). Наберите что-нибудь в поле ввода, а затем перейдите на стартовую страницу, нажав среднюю кнопку на эмуляторе. Потом нажмите и удержите кнопку Back отобразится список доступных приложений, выберите наше приложение. Обратите внимание, что состояние страницы сохранилось, т.к. приложение было в спящем (dormant) состоянии без какого либо участия с нашей стороны. Завершите работу приложения, перейдите в настройки отладки и установите настройку Tombstone upon deactivation while debugging: Соберите приложение и запустите его (F5). Наберите что-нибудь в поле ввода, а затем перейдите на стартовую страницу, нажав среднюю кнопку на эмуляторе. Потом нажмите и удержите кнопку Back отобразится список доступных приложений, выберите наше приложение. Обратите внимание, что состояние страницы не сохранилось, т.к. приложение было выгружено и перешло в состояние Tombstone, так что состояние страницы и приложения было утеряно. Добавим в код страницы MainPage.xaml.cs функции OnNavigatedFrom и OnNavigatedTo, сохранив текст из поля ввода в словарь состояний:
Cоберите приложение и запустите его (F5). Наберите что-нибудь в поле ввода, а затем перейдите на стартовую страницу, нажав среднюю кнопку на эмуляторе. Потом нажмите и удержите кнопку Back отобразится список доступных приложений, выберите наше приложение. Обратите внимание, что состояние страницы сохранилось, несмотря на то, что приложение было выгружено и перешло в состояние Tombstone, т.к. мы сохранили состояние страницы в специальном словаре для сохранения состояния страницы. Это не совсем правильное поведение кода, т.к. в случае, если мы восстанавливаемся из спящего состояния, нам не стоит модифицировать состояние страниц. Давайте добавим логическую переменную, чтобы определить, вызвался конструктор (это значить, что, мы либо стартуем первый раз, либо восстанавливается из tomnstone состояния) и модифицируем код соответствующим образом:
И
Запустите приложение (F5) и проверьте, как оно работает. Снимите флажок настройки отладки Tombstone upon deactivation while debugging и проверьте, что приложение не восстанавливает состояние в случае выхода из спящего (dormant) состояния. Добавим в приложение код, чтобы попробовать сохранить состояние приложения. Добавим TextBlock и обработчик Click в XAML код страницы:
В файл App.xaml.cs добавим публичное поле AppState: public string AppState = "";
Теперь необходимо добавить код сохранения/восстановления в App.xaml.cs:
Перейдите в настройки отладки и установите флажок Tombstone upon deactivation while debugging, а затем запустите приложение (F5) и проверьте, что состояние приложения сохраняется. Обратите внимание, что когда приложение вызывает задачи выбора и запуска, также возникает события Deactivated. Многозадачность и фоновые сервисы Несмотря на то, что в Windows Phone только одно приложение может быть активным, оно может воспользоваться специальными возможностями платформы, чтобы выполнять определенные задачи, даже не являясь активным. Специальные возможности платформы включают в себя возможность создания фоновых сервисов, запускаемые по расписанию, возможность проигрывания музыки и загрузки/выгрузки файлов в фоновом режиме, а также регистрацию оповещения (Alarms) и напоминания (Reminders). Об оповещениях и напоминаниях мы поговорим позже, сейчас кратко остановимся на фоновых сервисах. Фоновые сервисы, запускаемые по расписанию Можно создавать два типа сервисов: периодический (PeriodicTask) и интенсивный (ResourceIntensiveTask). Периодический сервис запускается регулярно на небольшое время, интенсивный – запускается на относительно длительное время, но только если выполнятся определённые требования, относящиеся к состоянию телефона. API создания сервисов доступен в пространстве имён Microsoft.Phone.Scheduler. Есть определенные ограничения, связанные в целом с сервисами, запускаемыми по расписанию, и с каждым типом сервисов в отдельности:
Ниже приведена сравнительная таблица ограничений на периодический и интенсивный сервисы:
Создайте новое приложение из шаблона Windows Phone Application, назовём его BackgroundAgentExample. В Solution Explorer, щелкнув правой кнопкой мыши по решению, в отобразившемся меню выберите Add, затем Add, затем New Project. Выберите тип проекта Windows Phone Scheduled Task Agent и назовите его ToastAgent. Перейдите к проекту ToastAgent, двойным щелчком перейдите к редактированию файла ScheduledAgent.cs. Добавьте в блок using код: using Microsoft.Phone.Shell; А в процедуру OnInvoke, которая вызывается при запуске сервиса, добавьте код отображения toast сообщения:
Обратите внимание на код внутри директив условной компиляции. Он позволяет не ждать 30 минут запуска сервиса, а запустить его через 10 секунд после его последнего запуска. Вернёмся теперь к основному проекту. Сначала добавим в него ссылку на проект ToastAgent. Для этого щелкните левой кнопкой мыши по папке References, в выпадающем меню выберите Add Refernce, в отобразившемся диалоговом окне выберите слева Projects, Solution, в центральной части ToastAgent и нажмите кнопку Add, а потом Close. Перейдём к редактированию кода MainPage.xaml. Добавим кнопку, чтобы запустить наш периодический сервис и добавим обработчик события Click:
Добавим в блок using директиву: using Microsoft.Phone.Scheduler; и определим константу с именем сервиса в классе MainPage: const string ToastAgentName = "Agent-Toast";
Поле описание сервиса является обязательным, без него не удастся добавить сервис. Обратите внимание, что и здесь присутствует код, который в случае отладки вызывает сервис через 10 секунд. Запустите приложение (F5) и протестируйте его работу: запустите приложение, нажмите кнопку Start Toast, выйдите из приложения, дождитесь появления сообщения от сервиса. Перейдите в настройки приложений, в панель background tasks и проверьте, что наш сервис там действительно зарегистрирован В качестве самостоятельного упражнения, попробуйте обработать вариант, когда сервис отключен пользователем, не используя исключений. Фоновая загрузка/выгрузка файлов Для фоновой загрузки/выгрузки файлов существует отдельный API, находящийся в пространстве имён Microsoft.Phone.BackgroundTransfer. Файлы можно загружать/выгружать из/в изолированное хранилище (Isolated Storage) приложения, при этом процесс будет продолжаться, даже если приложение не запущено. Если приложение запущено, но оно может отлеживать состояние и отображать его статус фоновой загрузки файлов. Пока поддерживаются GET/POST HTTP/HTTPS запросы для скачивания файлов и POST HTTP/HTTPS запросы для загрузки файла на сервер. Также существуют ограничения на размеры файлов, которые можно скачать/загрузить на сервер. На сервер можно загрузить файл не больше 5 Мб, скачать файл размером до 20 Мб можно по сотовой связи, файлы размером до 100 Мб – по беспроводной (WiFi) (если нет подключения к источнику питания). Каждое приложение может иметь до 5 одновременных запросов на фоновую загрузку/выгрузку файлов. Обратите внимание, что при завершении загрузки/выгрузки запросы не удаляются – это необходимо сделать вручную. При этом, всего на устройстве может быть до 500 запросов на фоновую загрузку/выгрузку файлов. Теперь мы знаем достаточно, чтобы добавить в ранее созданное приложение SimpeRussianRSSReader поддержу фоновой загрузки RSS. Откройте последнюю версию приложения. Если у нас был получен RSS и сохранён в изолированное хранилище, обновление RSS автоматически не происходит. Добавим запуск запроса на фоновое скачивание нового RSS файла, если у нас уже есть ранее скачанный. Для начала в конструктор страницы добавим проверку, что в изолированном хранилище приложения присутствует специальная директория в которую можно скачивать файлы используя фоновые сервисы: /shared/transfers
Эта директория создаётся системой для приложения, но может быть им удалена. Только файлы из этой директории можно загружать на сервер и только в эту директорию их можно выгружать. В код функции LoadRSS, добавим код создания запроса на фоновую загрузку:
Мы берем URL по которому отдаётся RSS, создаём URI, указываем имя файла в директории /shared/transfers в которую мы хотим скачать RSS методом GET, создаём загрузку, регистрируем обработчик события изменения статуса загрузки и добавляем запрос на загрузку с систему. Теперь, добавим в обработчик изменения статуса код, чтобы удалить запрос на загрузку, скопировать файл в корневую директорию и обновить пользовательский интерфейс:
Чтобы протестировать приложение, добавим ещё одно закоментированное значение константы, которая используется в качестве URL для скачивания RSS:
Закройте эмулятор, чтобы удалились ранее загруженные в него данные и запустите приложение (F5) в первый раз, чтобы RSS скатался в изолированное хранилище и отобразился в интерфейсе пользователя. После того, как отобразится список заголовков RSS, завершите работу приложения в Visual Studio (не закрывайте эмулятор). Чтобы увидеть, что произошла фоновая загрузка, закомментируем оригиналньый URL и раскоментируем другой:
Запустите приложение (F5) подождите некоторое время – заголовки RSS обновятся соответствующим образом. Фоновое проигрывание музыки Также существует отдельный API для проигрывания локальной и потоковой музыки, находящийся в пространстве имён Microsoft.Phone.BackgroundAudio. Создание приложений, которые используют эту возможность аналогично созданию приложений для фоновых сервисов запускаемых по расписанию, с поправкой на специфику проигрывания аудио. В поставке средств разработки находятся два шаблона проектов Windows Audio Playback Agent и Windows Audio Streaming Agent для создания сервисов фонового проигрывания локальной и потоковой музыки соответственно. Особенностью данных сервисов является их тесная интеграция с платформой Windows Phone. Подробнее с архитектурой сервисов фонового проигрывания музыки можно познакомиться в документации MSDN: https://msdn.microsoft.com/ru-ru/library/hh394039(v=VS.92).aspx По ссылке https://msdn.microsoft.com/ru-ru/library/hh202978(v=VS.92).aspx доступно пошаговое руководство по созданию простого приложения, проигрывающего локальные аудиофайлы в фоновом режиме. Итоги и следующие шаги В этой статье мы познакомились с жизненным циклом приложения, фоновыми сервисами и многозадачностью, в следующей части мы познакомимся с уведомлениями и напоминаниями, а также с Live Tiles. Файлы для загрузки Проект ApplicationStateExample |