Push-уведомления и Windows Push Notification Service
Необработанные уведомления (Сервис)
Если вы, в качестве типа push-уведомления используете wns/raw, полезные данные, включенные в уведомление могут быть чем угодно, а не только XML, но их размер не может превышать 5 Кб.
Конечно, Windows не может непосредственно что-либо сделать с этими данными, таким образом приложение должно предоставить обработчик для приёма этих уведомлений, как рассказано в следующем разделе.
Приём уведомлений (приложение)
Выполняющееся приложение принимает push-уведомление посредством PushNotificationChannel.onpushnotificationreceived. Это, опять же, нужно для обработки полезной информации из wns/raw уведомлений, но может использоваться и для других видов уведомлений. Если приложение не исполняется, то, конечно, оно не может принять это событие. Вместо этого, приложение должно присуствовать на экране блокировки с фоновой задачей PushNotificationTrigger, предназначенной для этой цели (смотрите "Задачи, зависимые от экрана блокировки и триггеры" ниже в этой лекции). Этот код затем принимает полезные данные XML, обрабатывает их и отправляет, при необходимости, либо обновления плиток, либо индикаторов событий, либо всплывающие уведомления. Помимо сохранения некоторых данных в папки данных приложения, это, на самом деле, всё, что могут делать фоновые задачи, но этого достаточно для сохранения ощущения динамичности приложений и для приглашения пользователей к запуску приложений.
В выполняющемся приложения вызывается событие pushnotificationreceived так же для других типов уведомлений. Сценарий 3 примера показывает это в его обработчике событий – я, для упрощения, слегка изменил этот код:
function startListening() { // Предполагаем, что канал получен и проверен channel.addEventListener("pushnotificationreceived", pushNotificationReceivedHandler); } function pushNotificationReceivedHandler(e) { // Извлекаем полезные данные уведомления для каждого типа уведомлений var notificationPayload; switch (e.notificationType) { case pushNotifications.PushNotificationType.toast: notificationPayload = e.toastNotification.content.getXml(); break; case pushNotifications.PushNotificationType.tile: notificationPayload = e.tileNotification.content.getXml(); break; case pushNotifications.PushNotificationType.badge: notificationPayload = e.badgeNotification.content.getXml(); break; case pushNotifications.PushNotificationType.raw: notificationPayload = e.rawNotification.content; break; } // Обработка уведомления: установите e.cancel в true для подавления автоматической обработки. }
Последняя часть в вышеприведенных комментариях важна. Когда вы принимаете событие в исполняющемся приложении, не нужно показывать всплывающее уведомление, только если оно не имеет отношения к какой-то части приложения, которая сейчас невидима. Например, если у вас есть приложение, которое работает и с электронной почтой и с календарём, вам захочется сделать видимыми всплывающие уведомления об электронной почте, когда пользователь видит календарь, и уведомления о событиях календаря, когда он работает с электронной почтой. В данном случаае установка e.cancel в true не позволит отобразиться всплывающему уведомлению.
В событии pushnotificationreceived, исполняющееся приложение получает право обработать необработанное (raw) уведомление первым. Если приложение его не обрабатывает, уведомление будет отправлено любой фоновой задаче экрана блокировки, настроенной для PushNotificationTrigger. В любом случае, посмотрите пример "Необработанные уведомления" (http://watwindows8.codeplex.com/wikipage?title=Raw%20Notifications%20Sample) для того, чтобы узнать подробности об этом.
Советы по отладке
При использовании push-уведомлений, практика показывает, что если уведомления не доставляются на устройство, обычно это не из-за проблемы с WNS. Вот списко того, что надо проверить (Спасибо Гансу Андерсену за этот список):
- Проверьте статус возврата ваших запросов HTTP POST к WNS. Если возвращается ответ HTTP 200, проверьте X-WNS-NotificationStatus и другие полученные заголовки. В частности, ищите статус "Received", который показывает, что уведомление доставлено клиенту.
- Не обнаружив ничего убедительного в заголовках, запустите Просмотр журналов событий (Event Viewer) и проверьте события в разделе Журналы приложений и служб > Microsoft > Windows > Push Notifications Platform > Operational ( Application And Services Logs > Microsoft > Windows > Push Notifications Platform > Operational) для того, чтобы посмотреть на деятельность по приему уведомлений.
- Кроме того, посмотрите в разделе Журналы приложений и служб > Microsoft > Windows > Immersive-Shell > Microsoft-Windows-TWinUI > Operational (Application And Services Logs > Microsoft > Windows > Immersive-Shell > Microsoft-Windows-TWinUI > Operational) для того, чтобы увидеть, есть ли здесь сообщения об ошибках, связанные с обработкой XML, примерно в то время, когда вы ожидаете поступление уведомления.
- Если даже с XML всё в порядке, обновление может не отобразиться, если изображение, указанное в нём, либо слишком большое (в пискелях, или по размеру файла), если оно имеет неподходящий формат (например, TIF), если изображение повреждено, если сервер, обрабатывающий запрос на получение изображения, не может обработать параметры запроса для плитки (масштабирование, контрастность, язык), или если сервер столкнулся с другой ошибкой, которую можно обнаружить в его собственных журналах.
- Если обновление появляется, но после значительной задержки, это может означать либо внутренние задержки или другие задержки в сети, связанные с инфраструктурой плиток и уведомлений. Если это происходит, просто примите к сведению, что мир не всегда совершенен и операции иногда приходится повторять!
Windows Azure Toolkit и Windows Azure Mobile Services
Очевидно, много работы нужно для создания службы, которая может принимать URI канала и отправлять уведомления через WNS. Признавая это, Windows Azure Toolkit (http://watwindows8.codeplex.com/) снова предлагает некоторые решения. Рассмотрение всех подробностей выходит за рамки этого курса, но ссылки ниже помогут вам начать с этим разрибаться. В частности, "Пример уведомлений Azure" (http://watwindows8.codeplex.com/wikipage?title=Notifications%20Sample%20%E2%80%93%20C%23%20and%20JavaScript) и "Пример о необработанных уведомлениях" (http://watwindows8.codeplex.com/wikipage?title=Raw%20Notifications%20Sample), так же "Пример рабочего процесса push-уведомлений" (http://watwindows8.codeplex.com/wikipage?title=Push%20Notification%20Worker%20Sample&referringTitle=Documentation). Вот полезное видео на сайте Channel 9: "Эпизод 73 – Ник Харрис о push-уведомлениях для Windows 8" (http://channel9.msdn.com/Shows/Cloud+Cover/Episode-73-Nick-Harris-on-Push-Notifications-for-Windows-8). Дополнительные ресурсы, весьма вероятно, будут опубликованы после того, как была написана эта лекция, поэтому поиск в Интернете позволит вам найти больше материалов.
Кроме того, посмотрите на "Мобильные сервисы Windows Azure" (http://www.windowsazure.com/en-us/develop/mobile/?fb=ru-ru), которые помогут вам создать масштабируемую серверную часть приложения, в том числе – структурированные облачные данные, проверку подлинности, и push-уведомления. Этот новые сервисы, на момент написания, поэтому у меня нет ссылок на другие ресурсы, но, совершенно очевидно, их стоит изучить.
Фоновые задачи и приложения экрана блокировки
В конце введения к этой лекции я рассказывал, как все, о чём мы говорили до сих пор помогает "создать динамичную, интерактивную среду в то время, как приложения часто не исполняются или могут запускать лишь небольшие фрагменты кода". Сейчас наша тема будет посвящена этой последней фразе – запуску небольших фрагментов кода с помощью фоновых задач. Как описано выше, фоновые задачи связаны с экраном блокировки, так как приложения, которым разрешено работать на экране блокировки должны так же задействовать определенные фоновые задачи.
Позвольте мне повторить здесь, что мы уже видели ряд сценариев, где пользователь может ожидать некоторой деятельности, связанной с приложением без необходимости запуска приложения. Периодические обновления плиток, push-уведомления, запланированные всплывающие уведомления и даже передача данных через контракт Общий доступ производят полезную деятельность , когда приложение приостановлено или не исполняется. Приложения так же могут настраивать фоновую передачу данных, которая выполняется, когда приложение не запущено, как мы увидим в Главе 3. А возможность фонового воспроизведения музыки предоставлена для специального класса приложений, которым нужно выполняться для поддержки сеансов связи VoIP, воспроизведения аудио, онлайновых бесед и так далее.
Что нам осталось рассмотреть – так это те самые небольшие фрагменты кода приложения, которые Windows может запускать в ответ на различные триггеры. Триггеры, в некоторых случаях, могут подвергнуться дальнейшей настройке в соответствии с дополнительными условиями, в итоге фоновая задача исполняется только тогда, когда в этом есть реальная необходимость. Всё это делается для уменьшения количества фоновой деятельности, которая истощает батареи устройства. Некоторые типы триггеров, на самом деле, требуют, чтобы пользователь поместил приложение на экран блокировки для того, чтобы преднамеренно ограничить количество приложений, которые могут реагировать на эти триггеры. Более того, Windows так же ограничивает процессорное время, которое могут потреблять подобные фоновые задачи:
- Фоновые задачи экрана блокировки: две секунды общего времени процессора за 15 минут.
- Другие фоновые задачи: одна секунда общего времени процессора каждые два часа.
Использование сетевого соединения так же ограничено в связи с затратами энергии батарей. Что это за ограничение, я не могу точно сказать, так как система анализирует использование энергии более пристально, нежели количество переданной информации. Средства оценки предела можно найти в материале "Поддержка приложения с помощью фоновых задач" (http://msdn.microsoft.com/library/windows/apps/hh977046.aspx). (Пока мы говорим об этом, вам, возможно, будет интересно посмотреть "Руководство и контрольный список для фоновых задач" (http://msdn.microsoft.com/library/windows/apps/Hh977043.aspx), документ "Введение в фоновые задачи" ( http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=27411), и материал "Поддержание производительности при работе приложения в фоновом режиме — фоновые задачи" (http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/06/01/10313828.aspx) в блоге для разработчиков приложений для Windows 8).
Возможно, вы подумали: "Ничего себе! Разве Windows 8 на самом деле имеет подобные ограничения?".
Коротко говоря – да, так как Windows не только стремится сэкономить энергию батарей для приложений переднего плана, с которыми работает пользователь, но так же она стремится к тому, чтобы от приложений переднего плана у пользователя остались бы наилучшие впечатления. Это подразумевает, что система не хочет столкнуться с фоновыми приложениями, которые, если им это позволить, занимают столько ресурсов, сколько смогут. (Разработчики фоновых служб всегда найдут оправдание для захвата ресурсов!).
Возможно, вы попадали в такую ситуацию, когда вы запускаете приложение, но его запуск занимает целую вечность, так как некие таинственные службы интенсивно используют жёсткий диск, передают данные по сети, нагружают процессор и так далее. Я, например, в подобной ситуации разбираюсь в чём дело, с помощью Диспетчера задач и Монитора ресурсов, после чего останавливаю любой процесс, который пожирает ресурсы моей системы – и будь что будет. Именно возникновения подобных впечатлений у пользователя и пытается избежать Windows 8.
"Хорошо", - скажете вы (при условии, что я, в некоторой степени, вас убедил), - "Означает ли это, что нет способа для выполнения некоторой фоновой работы наподобие индексирования данных, создания экскизов изображения, обработки видео и так далее?".
На самом деле, есть способы для того, чтобы это сделать. Во-первых, когда приложение находится на переднем плане, оно может делать подобные вещи в любых объёмах, так как оно, в конечно счете, отвечает за то, какие впечатления у пользователя создаст взаимодействие с ним. (Приложения, написанные на JavaScript, могут для подобных целей, использовать рабочие веб-процессы для того, чтобы убрать выполнение подобных задач из потока пользовательского интерфейса, а так же – передавать задачи компонентам WinRT, которые выполняют их дела в других потока и асинхронно возвращают результат. Мы ознакомимся с этим в Главе 5.).
Во-вторых, когда устройство подключено к сети переменного тока, а не работает от батарей, Windows позволяет фоновым задачам, запущенным для обслуживания триггеров, работать по 15 минут или дольше (в зависимости от нужд приложения). Здесь всё еще применимы ограничения ресурсов процессора, которые они могут потреблять, но задачи, которые не задействуют пользовательский интерфейс, который не разрешено использовать фоновым задачам – могут выполнить несколько миллиардов инструций за одну или две секунду на гигагерцовом процессоре!
Что мы имеем в итоге, так это то, что существует три различных класса фоновых задач и связанных с ними триггеров:
- Задачи для обслуживания триггеров, которые выполняются лишь при подключении устройства к сети переменного тока.
- Задачи, вызванные системными триггерами, которые выполняются либо при подключении устройства к электросети, либо при работе от батарей и не нуждаются в присутствии связанных с ними приложений на экране блокировки.
- Задачи для привилегированных приложений, которые пользователь добавил на экран блокировки.
В следующих разделах мы рассмотрим эти задачи подробнее, но сначала поговорим о некоторых общих их чертах: об объявлении фоновых задач в манифесте, об общем процессе работы с задачами с помощью WinRT, и о некоторых условиях
Фоновые задачи в манифесте
Все фоновые задачи для приложения объявляются в манифесте, где каждое объявление указывает на тип задачи и на код, который должен исполняться для выполнения этой задачи, как показано на рис. 6.1. Мы видели этот раздел манифеста в Главе 4 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript", где мы выбирали пункт Звук (Audio) для приложения, которое воспроизводит в фоновом режиме музыку. Что касается других параметров, то Системное событие (System Event) используется для первых двух классов вышеперечисленных задач, опции Канал управления (Control Channel), Таймер (Timer) и Push-уведомления (Push Notification) предназначены для задач, которые связаны с приложениями экрана блокировки.
![Редактор манифеста при объявлении фоновых задач. Показаны параметры для объявления Фоновые задачи (Background Tasks) из выпадающего списка Доступные объявления (Available Declarations) (слева), и типы фоновых задач (в центре), и поле Начальная страница (Start Page) для указания JavaScript-кода, который нужно исполнить для задачи (внизу). Фоновые задачи так же могут быть написаны на других языках, в подобных случаях используются поля Исполняемый файл (Executable) и Точка входа (Entry Point)](/EDI/16_08_14_2/1408137470-25747/tutorial/1166/objects/6/files/02_38.png)
Рис. 6.1. Редактор манифеста при объявлении фоновых задач. Показаны параметры для объявления Фоновые задачи (Background Tasks) из выпадающего списка Доступные объявления (Available Declarations) (слева), и типы фоновых задач (в центре), и поле Начальная страница (Start Page) для указания JavaScript-кода, который нужно исполнить для задачи (внизу). Фоновые задачи так же могут быть написаны на других языках, в подобных случаях используются поля Исполняемый файл (Executable) и Точка входа (Entry Point)
Во всех случаях, поле Начальная страница (Start Page) – это то место, где вы указываете JavaScript-файл, который будет исполняться для этой задачи независимо от приложения, передавая ему информацию лишь через папки данных приложения, вы, на самом деле, можете использовать здесь любой язык, какой хотите. Учитывая квоты на процессорное время, написание фоновых задач на языке вроде C++ или C# позволит вам выполнять некоторые задачи более эффективно, и в подобном случае вы будете использовать поле Точка входа (Point field )(если задача реализована в виде DLL, которая находится в пакете приложения), и, возможно, поле Исполняемый файл (Executable) (если задача реализована с помощью EXE-файла, который так же расположен в пакете приложения) для идентификации кода модуля и конкретной функции для вызова.
Полезно отметить, что даже хотя в поле Начальная страница (Start Page) для JavaScript ожидается указание страницы, там, на самом деле, может быть лишь код для фоновой задачи – вы получите ошибку, если попытаетесь задать в этом поле HTML-файл. (Для того, чтобы говорить точнее, фоновые задачи на JavaScript – это рабочие веб-процессы, простые и понятные). А почему фоновые задачи не могут отображать пользовательский интерфейс, так это потому, что Windows не загрузит HTML или CSS-код, лишь JavaScript! Таким образом, отправляя обновления плиток, индикаторов событий и всплывающие уведомления – это все дела, связанные с пользовательским интерфейсом, которые могут выполнять фоновые задачи. Для выполнения чего-то другого, фоновая задача должна записать некоторое значение в папку данных приложения, а это значение должно, с помощью обработчиков событий для фоновых задач, получить и обработать основное приложение, что мы скоро увидим.
Вы можете заметить, что параметр Системное событие (System Event) в редакторе манифеста не предусматривает поля, где вы можете задать триггер для задачи. Это выполняется в коде, при создании задачи, как мы увидим в ближайшее время.