Опубликован: 12.02.2013 | Уровень: для всех | Доступ: платный
Лекция 9:

Использование системных функций в приложениях

22.4. Фоновые задачи

Обычно в Windows Phone одновременно может быть активным только одно приложение. Однако, в некоторых случаях необходимо, чтобы неактивное приложение выполняло какие-то действия. Операционная система Windows Phone поддерживает возможность фоновой обработки, что позволяет разработчику создать код, который будет выполняться, когда приложение будет неактивным.

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

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

Фоновые и запланированные задачи

Существует множество различных типов фоновых процессов, среди которых часто используются два типа фоновых задач общего назначения: периодические и ресурсоёмкие задачи. Эти задачи создаются одинаково, однако они используются в различных ситуациях:

  • периодические задачи выполняются в течение небольшого промежутка времени (до 15 секунд) и запускаются с одинаковыми временными интервалами — обычно каждые полчаса;
  • ресурсоёмкие задачи выполняются в течение более длительного времени (до 10 минут), когда телефон заблокирован (то есть пользователь не выполняет никаких действий), подключён к источнику энергии и высокоскоростному подключению к сети.

Периодические задачи удобно использовать, например, для обновления прогноза погоды, информации о состоянии или отслеживания местоположения. Ресурсоёмкие задачи можно использовать для загрузки обновлений в базах данных, выполнения обработку или сжатия данных.

При обсуждении фоновой обработки задач необходимо разобраться в значениях некоторых терминов. Задача — это контейнер, которым управляет операционная система, и который запускается при выполнении определённых условий. Агент — это программный код, который выполняет работу задачи. При создании агента создаётся элемент, который будет работать либо в периодическом, либо в ресурсоёмком режиме. Когда агент получает управление, он может определить, в каком режиме он работает.

В качестве примера добавим в программу Журнал заметок возможность отслеживания местоположения. Отслеживание местоположения будет выполнять задача, которая периодически получает информацию о местоположении с устройства GPS в телефоне и сохраняет её со штампом времени в журнале заметок. Фоновая задача будет сохранять информацию о местоположении, когда программа будет неактивна.

Добавление фоновой задачи

Для фоновой задачи в решении Windows Phone создаётся дополнительный проект на основе шаблона Агент запланированных заданий Windows Phone. Этот шаблон позволяет создавать периодические и ресурсоёмкие задачи. При построении решения проект, содержащий код для запланированной задачи, добавляется к другим частям приложения.

Запланированная задача программы использует код в проекте агента. Необходимо, чтобы код агента мог использоваться в главном проекте. Для этого в Visual Studio необходимо добавить в главный проект ссылку на проект агента. Это делается так же, как и добавление ссылки на любую библиотеку.

При создании фоновой задачи Visual Studio создаёт пустой шаблон, в который можно добавить код агента.

namespace LocationTaskAgent
{
    public class ScheduledAgent : ScheduledTaskAgent
    {
        protected override void OnInvoke(ScheduledTask task)
        {
            // здесь должен быть код для выполнения задачи

            NotifyComplete();
        }
    }
}

Код задачи должен находиться в методе OnInvoke. При завершении метода он должен вызвать метод NotifyComplete, чтобы остановить выполнение задачи. При этом, нет возможности узнать, когда будет выполняться задача, и будет ли она вообще выполняться — это зависит от того, разрешил ли пользователь выполнение фоновых задач для приложения, и когда наступит время выполнения задачи.

Агент может определить тип выполняемой задачи, определяя тип параметра task, переданного в метод OnInvoke:

if (task is PeriodicTask)
{
    // выполняется периодическая задача
}

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

protected override void OnInvoke(ScheduledTask task)
{
    string message = "";

    string logString = "";

    if (loadTextFromIsolatedStorage("Log", out logString))
    {
        message = "Загружено";
    }
    else
    {
        message = "Инициализировано";
    }

    // если строка загружена, к ней добавляется информация о местоположении
    ...

    NotifyComplete();
}

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

Далее необходимо определить местоположение телефона и добавить эту информацию в журнал.

protected override void OnInvoke(ScheduledTask task)
{
    ...

    GeoCoordinateWatcher watcher = new GeoCoordinateWatcher();
    GeoPosition<GeoCoordinate> position = null;

    watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>
        (delegate(object sender, GeoPositionStatusChangedEventArgs e)
        {
            if (e.Status == GeoPositionStatus.Ready)
            {
                position = watcher.Position;
                GPSDoneFlag.Set();
            }
        });

    GPSDoneFlag.Reset();

    watcher.Start();

    // ожидание получения координат, но не дольше 10 секунд
    GPSDoneFlag.WaitOne(10000);

    // через 10 секунд будет получена строка или произойдёт тайм-аут
    ...
}

Эта часть фонового агента создаёт новый экземпляр класса GeoCoordinateWatcher и запускает его. GeoCoordinateWatcher генерирует событие StatusChanged, когда изменяется состояние GPS. Код обработчика события считывает местоположение и устанавливает флаг для синхронизации потоков, если информация с устройства GPS доступна.

Считанную с GPS информацию приложение должно сохранить в качестве заметки в журнале.

protected override void OnInvoke(ScheduledTask task)
{
    ...

    string positionString;

    if (position != null)
        positionString = position.Location.ToString();
    else
        positionString = "не известно";

    DateTime timeStamp = DateTime.Now;
    string timeStampString = timeStamp.ToShortDateString() + " " +
        timeStamp.ToShortTimeString() + System.Environment.NewLine;

    logString = logString + timeStampString + positionString;

    saveTextToIsolatedStorage("Log", logString);

    ...
}

Этот код создаёт текстовое сообщение, которое содержит значение местоположения или строку "не известно", если значение недоступно, добавляет его к строке журнала и сохраняет журнал в изолированном хранилище.

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

Для вывода на экран всплывающего сообщения используется класс ShellToast. Необходимо создать его экземпляр, указать заголовок и текст, который должен отображаться в окне сообщения, и вызвать метод Show.

protected override void OnInvoke(ScheduledTask task)
{
    ...
  
    ShellToast toast = new ShellToast();
    toast.Title = "Журнал заметок";
    toast.Content = message + positionString;
    toast.Show();

    ...
}

Для отладки фонового агента в Visual Studio можно использовать контрольные точки и пошаговое выполнение кода, как и в любой другой программе.

Во время отладки неудобно ждать по 30 минут, пока фоновая задача запустится. При отладке приложения в Visual Studio доступен метод, при вызове которого фоновая задача запускается для тестирования. Можно использовать условную компиляцию, чтобы метод для запуска фонового агента вызывался только при отладке программы. Для этого в начало файла нужно добавить следующую строку:

#define DEBUG_AGENT

Определив этот символ, можно указать компилятору обрабатывать код для запуска агента.

protected override void OnInvoke(ScheduledTask task)
{
    ...

#if DEBUG_AGENT
    ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));
#endif

    NotifyComplete();
}

Этот код запускает код фонового агента запускается в фоновом режиме с задержкой 60 секунд.

При вызове метода NotifyComplete агент фоновой задачи сообщает система Windows Phone о завершении работы.

Операционная система Windows Phone содержит класс ScheduledActionService, который управляет всеми запланированными задачами. Можно вызывать методы этого класса для поиска активных задач, их запуска и останова. У активной задачи есть имя, по которому можно найти задачу. При этом, можно управлять только теми задачами, которые приложение запустило, и нельзя увидеть задачи, запущенные другими приложениями.

PeriodicTask periodicTask = null;
string periodicTaskName = "CaptainTracker";

private void StartTracking()
{
    periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;

    // если задача существует и IsEnabled = false,
    // фоновый агент отключён пользователем
    if (periodicTask != null && !periodicTask.IsEnabled)
    {
        MessageBox.Show("Пользователь отключил фоновые агенты");
        return;
    }

    // если задача существует, и приложению разрешено запускать фоновые агенты,
    // необходимо удалить задачу и создать её заново
    if (periodicTask != null && periodicTask.IsEnabled)
    {
        RemoveAgent(periodicTaskName);
    }

    periodicTask = new PeriodicTask(periodicTaskName);

    // описание необходимо указать для периодических агентов,
    // чтобы пользователь мог идентифицировать агента на странице "Настройки"
    periodicTask.Description = "Отслеживание журнала";
    ScheduledActionService.Add(periodicTask);

    // если включена отладка, использовать метод LaunchForTest
    // для запуска агента через 60 секунд
#if(DEBUG_AGENT)
    ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(60));
#endif
}

Этот код запустит агента как периодическую задачу, и если выполняется отладка, запустит его через 60 секунд. Обратите внимание, что у задачи должно быть определённое имя, и что пользователь может отключить фоновые агенты для определённых приложений. Можно запустить ресурсоёмкую задачу, создав экземпляр класса ResourceIntensiveTask вместо PeriodicTask. Если нужно создать задачу, которая работает в обеих ситуациях, можно использовать класс ScheduledTask.

Задачи передачи файлов

Можно создать фоновую задачу передачи файлов из области или в область изолированного хранилища приложения. Передача файлов будет выполняться, если приложение не запущено, и когда приложение запускается, оно может контролировать состояние любых активных загрузок и выводить на экран их состояние. Файлы могут загружаться с узлов HTTP и HTTPs, но на текущий момент протокол FTP не поддерживается системой.

Существует набор политик, которые управляют объёмом данных, которые могут передавать приложения с помощью фоновых агентов передачи файлов:

  • максимальный размер исходящего файла: 5 Мб;
  • максимальный размер файла, загружаемого через подключение сотовой связи: 20 Мб;
  • максимальный размер файла, загружаемого по Wi-Fi: 100 Мб.

При необходимости можно изменять эти значения для текущей передачи с помощью перечисления TransferPreferences.

Службы фоновой передачи описаны в пространстве имён Microsoft.Phone.BackgroundTransfer. Для запуска передачи нужно создать объект BackgroundTransferRequest и добавить это к тем объектам, которыми управляет класс BackgroundTransferService. Передаче присваивается имя, чтобы при следующем запуске приложения она могла определить, где сохраняется передача и какой объём файла уже передан. Также можно обрабатывать события, которые генерируются при передаче, чтобы приложение могло выводить на экран информацию о переданной информации.

Запланированные уведомления

Приложения могут создавать запланированные уведомления, которые отображаются, если приложение запущено или не запущено. Уведомления могут вызывать всплывающие сообщения и изменение живых плиток. Обратите внимание, что само запланированное уведомление не может запустить приложение, но если пользователь нажмёт на уведомление, приложение запустится и откроется связанная с уведомлением страница. Уведомления могут быть одноразовыми или повторяться в заданном интервале.

Напоминания создаются так же, как и передачи файлов. Каждое уведомление имеет имя, по которому приложение может управлять уведомлением.

Агенты воспроизведения звука

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

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

Краткие итоги

  1. Приложение Windows Phone представляется в устройстве двумя файлами значков. Один значок используется для представления приложения в списке приложений телефона, а другой — больший значок — используется, если приложение прикреплено к меню Пуск телефона.
  2. Приложения Silverlight также используют изображение "экрана-заставки", которое выводится на экран при запуске приложения. Экран-заставка по умолчанию создаётся при создании нового проекта приложения Silverlight, и этот файл можно редактировать. В проектах XNA не реализован механизм экрана-заставки, но разработчики игр могут создать заставку, если для загрузки игры требуется, как минимум, несколько секунд.
  3. Операционная система Windows Phone предоставляет единую модель управления выполнением приложений. Приложение может быть в любое время деактивировано. Пользователь может деактивировать запущенное приложение и запустить другое, нажав на кнопку Пуск, и позже вернуться к деактивированному приложению, нажав кнопку Назад. Пользователь также может удерживать кнопку Назад, чтобы вывести на экран список деактивированных приложений и вернуться к одному из них.
  4. Деактивированное приложение может находиться в памяти (бездействовать) или может быть выгружено из памяти. При возобновлении бездействующего приложения все его объекты в памяти сохраняются. При возобновлении выгруженного приложения оно должно заново создать все объекты.
  5. Во время работы приложения в телефоне оно может находиться в одном из четырёх состояний: "запущено", "закрыто", "деактивировано" и "активировано".
  6. Windows Phone предоставляет механизм хранения данных в памяти, который может использоваться для сохранения временных данных при деактивации приложения. Эти данные могут быть считаны при возобновлении работы приложения.
  7. Программы могут использовать задачи запуска и задачи выбора для взаимодействия с подсистемами телефона. Задача запуска запускает внешнее приложение (например, приложение для отправки электронной почты), а задача выбора запускает внешнее приложение, которое возвращает результат (например, выбор изображения из библиотеки изображений). Во время работы внешнего приложения программа деактивируется.
  8. Приложение может создавать фоновые агенты, которые могут работать, если приложение неактивно. Они могут быть периодическими (выполняются в течение короткого промежутка времени каждые 30 минут) или ресурсоёмкими (выполняются, когда телефон не используется, подключён к внешнему источнику питания и использует подключение к сети). Агент — это отдельный проект, который добавляется к решению приложения.
  9. Приложение может использовать фоновую передачу файлов, которая будет выполняться, когда приложение будет неактивно.
  10. Приложение может создать запланированные уведомления, которые будут запускаться в определённом временном интервале. Они будут появляться, даже если приложение не запущено.

Вопросы

  1. Какие изображения должно содержать приложение для Windows Phone, и как эти изображения используются?
  2. Как можно создать и использовать в приложении экран-заставку?
  3. Что означает "быстрое переключение приложений"?
  4. Как происходит переключение приложений?
  5. Как можно сохранить состояние приложения при его деактивации и загрузить при возобновлении работы?
  6. Как в приложении вызвать системные функции телефона?
  7. Чем отличаются задачи запуска и задачи выбора?
  8. Как приложение может использовать фоновые задачи?
  9. В чём разница между периодическими и ресурсоёмкими задачами?
  10. Как создать и использовать в приложении агента фоновой задачи?
park mr
park mr
Таиланд, thai
An Nguyen
An Nguyen
Вьетнам, 30/9 Thong Nhat street, ward 13, Go Vap district