Архив рубрики ‘Windows Phone’
Хоть и в ИТ, но те же «Новости»
Опять не смог сдержаться.
Недавно, в некоторых онлайн ресурсах, опубликовали табличку, где показаны продажи устройств на различных платформах за третий квартал 2010 и 2011 года. Такие себе Майкрософт ненавистники развели тут же дебаты на тему, мол продажи WP 7 падают, все, настал конец, Андроид рулит и т. д. Еще рассказывают, что в Андроиде какой-то там версии возможностей больше, но конкретику не приводят![]()
Я бы этому не придал значения, если бы на это все не повелись и наши разработчики.
Ребята, Вы сначала посмотрите, что на рынке происходит, а потом делайте выводы. Кто-то из Вас пытался купить WP 7 в третьем квартале? Я – пытался. Хотел подарить три телефона студентам партнерам. Оказалось, что последний телефон в Украине купили еще в июне. Агентство смогло найти только одно устройство, и то, на черном рынке
Причина простая: все производители ждали Манго. Киевляне в этом сейчас могут убедиться, так как весь Киев заклеен бигбордами с рекламой Титана, а 7-го декабря в Россию официально поступит в продажу Нокиа (я уже жду на hotline
).
В третьем квартале WP 7 телефонов элементарно не было в продаже, поэтому не читайте советскую прессу
А вот что будет уже перед Рождеством и в первом квартале 2012 – очень интересно. Но у меня уже такое чувство, что дадим мы кому-то ногой под (черт, я же сотрудник Майкрософт и не могу ругаться даже в личном блоге
)….
WP 7.5: Расширение Pictures Hub
Продолжу тему, связанную с расширениями функциональности встроенных в WP 7 приложений. В прошлой статье мы говорили о расширении функциональности поиска, а в этой поговорим и расширении стандартного приложения по работе с изображениями – Pictures Hub.
Итак, начнем с того, что можно расширять. Тут существуют три возможности:
1). Расширение списка приложений на вкладке Apps, которая доступна при загрузке Pictures Hub.
Данная вкладка появляется только тогда, когда у Вас есть хотя бы одно приложение (установленное, в отличие от поиска), декларирующее поддержку фото-приложения. Если таких приложений не установлено, то и вкладки нет.
При расширении основного приложения Pictures Hub нет никаких специальных возможностей, лишь вызов приложения, которое якобы должно уметь работать с изображениями.
2, 3). Следующая возможность появляется уже на уровне работы с конкретной фотографией и позволяет Вашему приложению получить доступ к самой фотографии из меню Application Bar приложения Picture Viewer, вызываемого из Pictures Hub для просмотра отдельной фотографии.
Как видно, при работе с отдельной фотографией доступны такие пункты меню, как apps… и share….
Первый позволяет вызвать приложение из списка, передав ему уникальный идентификатор изображения, по которому последнее можно загрузить.
Второй – использовать одно из приложений из списка, чтобы передать изображение по сети какой-либо веб-службе (например, опубликовать в facebook). Тут также можно получить идентификатор изображения, которое потом загрузить внутри приложения.
Давайте рассмотрим, как эти механизмы реализуются на практике.
На первом этапе необходимо в WMAppManifest.xml описать расширения. Для каждого из трех перечисленных случаев существует свое расширение. Ниже приведены примеры декларации поддержки всех трех расширений:
1: <Extensions>
2: <Extension ExtensionName="Photos_Extra_Viewer"
ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" />
3: <Extension ExtensionName="Photos_Extra_Hub"
ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" />
4: <Extension ExtensionName="Photos_Extra_Share"
ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" />
5: </Extensions>
При работе с расширениями нет ничего нового по сравнению с расширением поисковой функциональности. В элементе Extension прописывается фиксированный (характерный для расширения приложения по работе с изображениями) ConsumerID, имя расширения позволяет указать, какую часть приложения мы будем расширять, а TaskID ссылается на запись в разделе Tasks.
Если Вы планируете расширять Puctures Hub (основное его окно), то кода выше полностью достаточно. Ведь приложение просто вызывается из галереи, не получая специальных параметров.
Если речь идет о расширении Picture Viewer, то тут необходимо еще реализовать и код логики, обрабатывающей изображение. Для этого нужно получить идентификатор из QueryString, загрузить фотографию и отобразить пользователю соответствующий интерфейс. Обычно первая часть этих действий выполняется в перегруженном методе OnNavigatedTo, который инициализируется при переходе на страницу. Вот пример кода, который может быть реализован внутри метода:
1: IDictionary<string, string> queryStrings =
2: this.NavigationContext.QueryString;
3:
4: if (queryStrings.ContainsKey("token"))
5: {
6: MediaLibrary library = new MediaLibrary();
7:
8: Picture picture =
9: library.GetPictureFromToken(queryStrings["token"]);
10:
11: BitmapImage bitmap = new BitmapImage();
12: bitmap.CreateOptions = BitmapCreateOptions.None;
13: bitmap.SetSource(picture.GetImage());
14: WriteableBitmap picLibraryImage = new WriteableBitmap(bitmap);
15: . . . . .
16: }
17:
В данном коде мы обрабатываем ключ token, который присутствует, если мы расширяем пункт apps… В случае с share… пунктом следует обрабатывать ключ FileId.
Таким образом, расширить Pictures Hub – простая задача. Проблема только в отсутствии возможности протестировать все это на эмуляторе, так как в последнем Pictures Hub не активирован.
WP 7.5: Расширение функциональности поиска
Первая функциональность, с которой мне захотелось познакомиться в Windows Phone 7.5 – расширение возможностей стандартного поиска, результатами, которыми обладает Ваше собственное приложение. Решил это сделать, увидев подобную функциональность в Windows 8, ожидая увидеть что-то аналогичное. Скажу сразу, реализация в Windows Phone 7.5 меня разочаровала. Несмотря на это, механизм существует, поэтому я решил описать его возможности.
Начнем с того, что стандартный поиск в Bing теперь интегрирован с Windows Phone Marketplace. Иными словами, если пользователь выполняет поиск и вводит запрос, соответствующий названию приложения из Marketplace (или похожим критериям), то ссылка на приложение выдается в топе результатов поиска. При этом пользователь может установить приложение, используя результаты поиска, или запустить его на устройстве, если оно уже установлено. Ниже небольшой пример, который легко воспроизвести и в эмуляторе:
К сожалению, это поведение работает само собой и не оставляет разработчику возможность что-то поменять. Хотя приложение и может получить информацию о том запросе, который привел в Bing к его запуску. Для этого достаточно воспользоваться командой, похожей на эту:
string searchTerms = NavigationContext.QueryString["bing_query"];
Естественно, данные нужно выбирать на основной странице приложения сразу же после его загрузки. Другой вопрос, что с ними делать. По крайней мере информацию о том, что Ваше приложение кто-то устанавливает через поисковый запрос – Вы получите.
Если Вы все же решили попробовать получать запрос из Bing, положившись на Вашу удачу, то можете попробовать протестировать поведение приложения, эмулируя его запуск с поисковым запросом. Для этого в WMAppManifest.xml достаточно прописать следующий код, заменив элемент DefaultTask на следующий:
<DefaultTask Name ="_default" NavigationPage="MainPage.xaml?bing_query=Пятнашки"/>
В этом случае, приложение получит параметры и сможет обработать их так, будто бы запущено из окна поиска Bing.
Вторая возможность, напротив, предоставляет разработчику механизмы для перехода из результатов поиска прямо в приложение, с возможностью обработки поискового запроса. Давайте посмотрим, как это делается.
Возможность базируется на так называемых «Быстрых карточках». Так, обратите внимание на изображение ниже:
Тут, перед результатами поиска из Web (и после ссылки на приложение в Marketplace) появляется специальный раздел Products. Его появление объясняется тем, что Bing нашел несколько продуктов, соответствующих нашему запросу. Нажав на один из представленных продуктов, мы можем перейти к его описанию, состоящему из нескольких вкладок (это и есть быстрая карточка продукта):
Тут Вы сможете увидеть несколько вкладок, включая обзоры, цены и, самое интересное, список приложений:
Причем, обратите внимание, в списке приложений есть и те, которые уже установлены, а также те, которые можно загрузить. Идея состоит в том, чтобы пользователю показать именно те приложения, которые помогут ему работать с «Быстрыми карточками». Иными словами, если продукт продается на eBay, то пользователю было бы здорово загрузить приложение-клиент для eBay (кстати, он есть в списке) или выбрать приложение другого магазина.
А теперь то, что необходимо сделать разработчику, чтобы его приложение попало в такой же список:
1). Необходимо понимать, что существует всего (пока) три типа таких карточек: Продукты, Местоположения (отображающиеся на вкладке Local) и Фильмы (которые демонстрируются в кинотеатрах, недалеко от Вашего местоположения).
2). Каждый тип карточки поддерживает несколько расширений (категорий). Иными словами, если пользователь ищет новый лаптоп, а Вы продаете ювелирные украшения, то не имеет смысла показывать пользователю Ваше приложение. Список доступных расширений можно посмотреть тут: http://msdn.microsoft.com/en-us/library/hh202958(v=VS.92).aspx.
3). Чтобы приложение попало в список, ассоциированный с одной из карточек (в одну или несколько категорий), достаточно прописать набор параметров в его манифесте и обработать (хотя и не обязательно) возможный поисковый запрос. Как только Вы это делаете, то пользователь получает возможность видеть и Ваше приложение.
Давайте рассмотрим детальную реализацию третьего пункта.
Начнем с изменения WMAppManifest.xml, где в раздел App (в самый конец) записывают следующий блок:
1: <Extensions>
2: <Extension ExtensionName="Bing_Products_Arts_and_Crafts"
3: ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}"
4: TaskID="_default" ExtraFile="Extensions\\Extras.xml" />
5: . . . . .
6: <Extensions>
Тут основным атрибутом является ExtensionName, описывающим с помощью элементов Extention категории, в ответ на которые Ваше приложение будет появляться в списке. Атрибут CunsumerID Вы просто копируете с его значением, так как значение этого атрибута является стандартным для данного типа расширений. Атрибут TaskID указывает на ту задачу, которая будет выполняться при запуске приложения (обычно это _default – запуск MainPage.xaml), наконец ExtraFile указывает путь к файлу, где записываются дополнительные детали к расширению (обычно он один для всех расширений).
На следующем этапе Вы можете создать файл, указанный в атрибуте ExtraFile. Тут может быть код, похож на этот:
1: <ExtrasInfo>
2: <AppTitle>
3: <default>Quick Card Sample</default>
4: </AppTitle>
5:
6: <Consumer ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5661}">
7: <ExtensionInfo>
8: <Extensions>
9: <ExtensionName>Bing_Products_Arts_and_Crafts</ExtensionName>
10: <ExtensionName>Bing_Products_Baby_and_Nursery</ExtensionName>
11: </Extensions>
12:
13: <CaptionString>
14: <default>Product URI Details</default>
15: <fr-FR> . . . </fr-FR>
16: </CaptionString>
17:
18: </ExtensionInfo>
19:
20: . . . . .
21:
22: </Consumer>
23: </ExtrasInfo>
Так, в этом файле поддерживаемые Вашим приложением расширения разбиваются на группы. Для каждой из групп задается заголовок, который будет отображаться вместе с Вашим приложением (причем для всех поддерживаемых Вами культур).
Последнее, что необходимо сделать, это обработать запрос, который отправляется Вашему приложению из Bing. Проблема в том, что несмотря на явное использование TaskID, Bing перенаправляет запрос приложению в следующем виде:
app://<AppID>/_default#/SearchExtras?ProductName=<product_name>&Category=<extension_names>
Тут параметры могут меняться, в зависимости от типа Быстрой карточки.
Так вот, чтобы это работало, нужно настроить mapping внутри Вашего приложения. Это можно сделать, прописав в ресурсах объекта App вот такой код (при этом запрос перенаправляется на другую страницу приложения):
1: <Application.Resources>
2: <nav:UriMapper x:Key="UriMapper">
3: <nav:UriMapper.UriMappings>
4: <nav:UriMapping Uri="/SearchExtras" MappedUri="/ItemPage.xaml"/>
5: </nav:UriMapper.UriMappings>
6: </nav:UriMapper>
7: </Application.Resources>
Далее, подключаем данный mapping внутри App.xaml.cs, при загрузке приложения:
RootFrame.UriMapper = Resources["UriMapper"] as UriMapper;
Вот и все. Теперь обрабатываем параметры запроса с помощью QueryString и реализуем нужную нам бизнес-логику.
Таким образом, добавить Ваше приложение в список, ассоциированный с одной или несколькими категориями в Быстрых карточках не так и сложно. Другое дело, что пользователю весьма нетривиально попасть на предлагаемый список, чтобы увидеть Ваше приложение. И самое интересное (возможно, с этого стоило начать), быстрые карточки работаю пока не везде. Точнее работают они всего в 4-х странах: США, Франция, Австралия и Англия. Причем в последних трех, работают только Продукты. Проверить работу карточек Вы можете, установив Browser&Search language в язык, соответствующей одной из стран.
Windows Phone Marketplace Test Kit
Решил написать несколько статей, посвященных Windows Phone 7.5. А поскольку мы сейчас реализуем несколько программ, позволяющих студентам и разработчикам опубликовать свои приложений я Marketplace (вот пример: ссылка), то первую статью я решил посвятить публикации приложений. Даже не столько публикации, как подготовке к публикации приложений.
Итак, Ваше приложение полностью готово и Вы хотите его опубликовать в Windows Phone Marketplace. Проблема в том, что для удачной публикации Вам понадобиться пройти сертификацию на выполнение требований Marketplace, а также подготовить дополнительные материалы (иконки, описание и т. д.), которые понадобятся при публикации. Чтобы понять, что Вам понадобиться для публикации и готов ли Ваш пакет, существует два пути:
1). Прочитать все, что касается Marketplace в MSDN (http://msdn.microsoft.com/en-us/library/hh202930(v=VS.92).aspx), включая различные требования к сертификации (http://msdn.microsoft.com/en-us/library/hh184843(v=VS.92).aspx). При этом Вы не застрахованы от ошибок.
2). Использовать Windows Phone Marketplace Test Kit – специального пакета для разработчика, являющегося частью Windows Phone SDK 7.1. Пакет интегрируется с Visual Studio в виде расширения и позволяет выполнить все необходимые проверки на готовность пакета, не выходя из оболочки.
Внимание! Если Вы установили WP 7.1 SDK, а приложение продолжаете разрабатывать в режиме WP 7.0, то пакет активен не будет, и Вы не сможете увидеть соответствующие пункты меню в Visual Studio.
Поскольку я не могу помочь Вам с чтением технической документации, то перейду к рассмотрению второго пункта, это использование Windows Phone Marketplace Test Kit. Особенность данного подхода состоит в том, что задание по проверки готовности к сертификации можно поручить и тестеру в Вашей команде.
Итак, если у Вас установлен Windows Phone 7.1 SDK и Вы ведете разработку приложения в Visual Studio, то Вы без труда сможете найти пункт меню Project->Open Marketplace Test Kit. Открыв соответствующее окно, Вы сможете увидеть следующее окно, содержащее 4 закладки (я уже загрузил свои рисунки):
Обратите внимание, что внизу окна присутствует надпись, которая предлагает обновить входящий в состав Test Kit набор Test Cases. Если Вы увидели такую надпись, то нажмите Update, чтобы Ваше приложение удовлетворяло самым последним требованиям Marketplace.
Итак, открывшееся окно содержит 4 закладки:
Замечание. Чтобы работать с Test Kit, Вам необходимо создать Release версию Вашего приложения. Причем, исправляя ошибки по ходу прохождения тестов, выполняйте команду Build после каждого изменения.
Application Details – тут Вы вносите необходимые ресурсы для публикации Вашего приложения. Это три иконки различного размера. Эти иконки будут отображаться при выборе приложения в Marketplace, при установке приложения в обще меню и на основной экран. Также необходимо приложить скриншоты Вашего приложения. По требованиям необходимо приложить минимум один скриншот, но можно и больше (чтобы дать пользователю больше деталей во время знакомства с приложением). Если иконки (обычные изображения в формате png) помочь создать Вам сможет лишь дизайнер, то скриншоты приложения можно получить, используя стандартный эмулятор. Для этого запустите приложение в эмуляторе и откройте расширенную панель управления:
Как видите, тут не только можно снимать скрины, но и эмулировать работу GPS и акселерометра.
Подготовив все необходимые ресурсы, перейдем к следующей вкладке.
Automated Tests – тут проверяется корректность структуры xap-файла, и соответствие Вашего приложения заявленным в манифесте возможностям.
Если все иконки и скрины заданы верно, а размер пакета не превосходит требуемого, то приложение успешно пройдет все тесты. Просто нажмите Run Tests и посмотрите на результат. Особое внимание следует уделить тесту Capability Validation. С помощью этого теста Вы сможете однозначно определить, какие возможности необходимы Вашему приложению и отредактировать WMAppManifest, указав корректные значения.
Monitored Tests – следующий набор тестов позволяет проверить Ваше приложение на производительность и корректность работы. К сожалению подобные тесты можно выполнить только на реальном устройстве. Поэтому, если Вы являетесь счастливым обладателем Windows Phone устройства, то подключите его через USB, выберите вариант развертывания Windows Phone Device и запустите приложение с помощью Start Application. Поиграйтесь с Вашим приложением, стараясь воспроизвести все ситуации, а затем выйдите из приложения, нажав кнопку Back на устройстве (находясь в основном окне приложения) или нажав Close Application в окне Visual Studio. В результате Вы получите набор данных, связанных со временем запуска приложения, используемой памятью, исключениями и реакцией на Back кнопку:
Manual Tests – не все тесты можно пройти в автоматическом режиме, поэтому последняя вкладка предлагает Вам несколько десятков тест-кейсов, которые следует пройти в «ручном» режиме, чтобы убедиться в том, что приложение работает хорошо.
Если у Вас и тут все хорошо, то смело приступайте к публикации приложения.
Публикуем приложения через APPA Mundi: публикация
Итак, зарегистрировавшись в APPA Mundi, начинаем публикацию своего приложения. Это можно делать, как только статус перешел в состояние Active, а на балансе появилось 36 фунтов.
Итак, нажимаем большую кнопку сверху Submit Application и переходим к первой странице мастера:
Несмотря на то, что тут нужно поставить всего одну галочку, рекомендую ознакомиться с документами, на которые ведут ссылки. Это ускорит процесс публикации, так как обо всех проблемах Вы будете знать заранее.
Теперь выбираем язык нашего приложения и загружаем XAP файл (последний откомпилируйте в Release версию).
Внимание! Если Ваше приложение поддерживает несколько языков (русский и английский), то Вам понадобиться подготовить отдельные скриншоты и описания для каждого из языков. На этом этапе загружайте только скриншоты для выбранного языка. Остальные сможете загрузить потом.
Внимание! Очень часто приложение не проходит сертификацию, так как имеет иконки, установленные по умолчанию. Проверьте, что приложение имеет уникальную иконку как в общем меню, так и при размещении на основной странице (иконка хаба) телефона.
На следующем этапе введите название и описание Вашего приложения, а также выберите категорию и подкатегорию. О рейтингах можете сейчас не думать. Это специальные параметры, необходимые для распространения приложения в таких странах как Бразилия. И чтобы заполнить эти поля, Вам также понадобиться сертификат.
Наконец, Вы загружаете иконки и скриншоты своего приложения. Необходимо заранее подготовить три иконки и хотя бы один скриншот.
На последнем этапе Вы выбираете стоимость приложения. Подозреваю, что на первом этапе это Ваши приложения будут распространятся бесплатно.
Просмотрите всю загруженную информацию и установите галочку, разрешающую опубликовать Ваше приложение в Marketplace сразу же после прохождения сертификации. Если не поставить эту галочку, то придётся вернуться и выполнить публикацию вручную.
В последнем окне Вас предупреждают о том, что с Вашего счета снимают 30 фунтов. Но поскольку эти деньги достались Вам даром, то смело жмем Next.
Внимание! Если с первого раза Ваше приложение не проходит сертификацию, Вы можете повторить процедуру любое количество раз – бесплатно. За оставшиеся 6 фунтов можно отправить апдейт для Вашего приложения.
Вернувшись в свою панель управления, Вы можете смотреть на статус Вашего приложения. Тут же Вы можете опубликовать скрины и описания на других языках, нажав Submit another language.
Вот и все. Остается только ждать результат. 3-5 дней и Ваше приложение станет доступно пользователям (если его не вернут на доработку).
Удачи Вам с публикацией!
Публикуем приложения через APPA Mundi: регистрация
Многие уже слышали, что с 1-го ноября Майкрософт Украина предоставляет студентам любых учебных заведений возможность опубликовать бесплатно свои приложения на Windows Phone Marketplace. Публикация осуществляется через специальную компанию APPA Mundi и не требует существенных временных затрат. Сейчас я покажу, как это сделать.
Итак,
Шаг 0.
Чтобы пройти процедуру регистрации, Вы должны иметь Live ID. Он необходим при активации Вашего аккаунта в программе DreamSpark. Если у Вас еще нет LiveID, то рекомендую пойти на http://mail.live.com, где и создать оный, включая чистый почтовый ящик для коммуникации по вопросам Marketplace.
Шаг 1.
Пишем мне письмо с просьбой выслать специальный промо-код для публикации своего приложения. Для этого нужно переслать любое подтверждение того, что Вы студент и иметь готовое к публикации приложение. Запрос прошу отправлять на адрес Sergiy.Baydachnyy@microsoft.com.
В ответ на просьбу я вышлю сразу два кода (не пугайтесь), один из которых предоставит Вам бесплатную возможность для публикации, а с помощью другого Вы пройдете верификацию на то, что являетесь студентом.
Шаг 2.
Получив се коды, регистрируемся на APPA Mundi портале, по адресу http://www.appamarket.com.
Для этого достаточно нажать Register for APPA Market account.
Нажав ссылку, Вы тут же попадете на форму, где обязательно необходимо выбрать, что Вы Студент и из Украины.
Тут же можно проверить Ваш LiveID (создайте какой-нибудь) на принадлежность студенту. Рекомендую с этого и начать. Вот тут и понадобиться второй код (конечно, если у Вас есть ISIC карточка, то можно обойтись и без кода).
Если Вы не выполнили проверку на этом шаге, то это можно будет сделать позже.
Далее переходим к заполнению детальной информации о себе и в самое последнее поле вводим промо-код. Именно он позволит активировать на Вашем балансе некоторую начальную сумму, достаточную для публикации приложения.
Подтверждаете все свои данные на последнем этапе регистрации.
Наконец, Вы оказались на странице, с которой можно произвести публикацию. Но не стоит торопиться. Так как коды проверяются в «ручном» режиме, то необходимо подождать до 24-х часов, пока на Ваш счет будут зачислены деньги. В моем случае это заняло 1 час.
Лишь после того, как Ваш аккаунт перейдет в состояние Active (из Not Activated), то можете приступать к публикации.
О том, как произвести публикацию под созданным аккаунтом, я расскажу в следующем посте.
Windows Phone 7: Разрабатываем приложение с использованием Push Notification (часть 1, веб-роль)
Этим постом я начинаю серию из 4-х статей, посвященных разработке решения для Windows Phone 7 с использованием Push Notification. Описанное тут решение мы разрабатывали для Украинского Медиа Холдинга. Между тем оно является типовым, хотя информацию по некоторым шагам найти достаточно сложно.
Начнем с описания задачи: партнер реализовал специальную службу, которая позволяет пользователям мобильных телефонов получать нотификацию о ходе прохождения футбольных игр, а также получать расписание ближайших игр, интересных для украинского зрителя. Доступ к службе осуществляется на основе платной подписки. Оплата взымается, в основном, за использование гейтов мобильных операторов для рассылки СМС сообщений.
Поскольку Windows Phone 7 обладает такой замечательной вещью, как Push Notification, то было принято решение, реализовать аналогичный функционал для устройств WP 7 на бесплатной основе. Ведь для использования Push Notification мобильный оператор не используется, а уведомления доставляются с помощью специальной Push Notification службы, которой управляет Microsoft.
Идея очень простая: клиент, используя приложение партнера, подписывается на службу доставки мгновенных сообщений. При этом клиент передает партнеру уникальный URL, позволяющий партнеру связаться с Notification службой и передать сообщение на конкретный телефон. Партнер, генерируя новое сообщение, опрашивает свою базу адресов, и по каждому из адресов отправляет сообщение в Push Notification службу, которая на основании уникального адреса нотифицирует конкретный телефон, передавая ему сообщение.
Таким образом, при разработке этого решения, нам необходимо следующие три компонента:
· Служба, которая позволяет получить новое сообщение от оператора и поставить его в очередь;
· Модуль (служба), который обрабатывает сообщения в очереди;
· Клиент для Windows Phone 7, позволяющий пользователю подписаться на службу и настроить параметры уведомлений;
Проблема состоит в том, что если Вы планируете отправлять множество сообщений и ожидаете большое количество подписчиков, то второй компонент будет достаточно сильно нагружен и должен предусматривать возможность масштабирования. Также механизм очереди должен поддерживать работу нескольких экземпляров службы по обработки элементов. Ведь при масштабировании проблема доступа нескольких служб к одному элементу обязательно возникнет.
Учитывая проблемы выше и список основных компонентов, было принято решение использовать технологию Windows Azure для создания подобного решения. В случае использования Windows Azure, первый компонент можно было бы реализовать в виде обычных WCF служб, для реализации очереди использовать соответствующий тип хранилища в Storage службе, а для компонента обработки элементов очереди можно использовать Рабочую роль. Последняя предназначена для работы в фоне и может регулярно опрашивать очередь на наличие новых элементов. Кроме того, Рабочая роль очень хорошо масштабируется.
Таким образом, 3 из 4 статей будут иметь достаточно опосредованное отношение к Windows Phone, а скорее относятся к Windows AzureJ
Начнем работу. На первом шаге создадим проект в Visual Studio на базе шаблона Windows Azure
В создаваемое решение добавим две роли, это WCF Service Web Role и Worker Role. Тут Вашим ролям можно дать более осмысленные названия (я не буду).
Про Рабочую роль сейчас забудем и сосредоточимся на реализации WCF службы.
Опишем интерфейс нашей службы следующим образом:
1: [ServiceContract]
2: public interface INotification
3: {
4: [OperationContract]
5: void SubscribePhoneToService(Guid guid, string pushServiceUri);
6:
7: [OperationContract]
8: SMSMessage[] RefreshData();
9:
10: [OperationContract]
11: void NewSMSMessage(string sms, string login, string password);
12: }
13:
14:
15: [DataContract]
16: public class SMSMessage
17: {
18: string date;
19: string message;
20:
21: [DataMember]
22: public string DateTimeValue
23: {
24: get { return date; }
25: set { date = value; }
26: }
27:
28: [DataMember]
29: public string MessageValue
30: {
31: get { return message; }
32: set { message = value; }
33: }
34: }
Тут описан класс SMSMessage, с помощью которого мы будем передавать данные между службой и телефонами, а также интерфейс INotification, описывающий три метода интерфейса службы. Тут определены следующие методы:
· SubscribePhoneToService – этот метод позволяет подписать телефон на сообщения, принимая уникальный ID телефона и адрес службы уведомлений для отправки сообщений данному устройству. Обратите внимание, что сообщения высылаются каждому подписанному телефону отдельно. Это дает возможность кастомизировать текст сообщения и фильтры, в зависимости от настроек. В данном случае какой-то специальной настройки для конкретного телефона мы не поддерживаем, поэтому метод принимает всего два параметра;
· RefreshData – этот метод необходим, если пользователь запустил приложение и хочет посмотреть последние сообщения;
· NewSMSMessage – этот метод инициируется оператором и служит для передачи сообщения в очередь. Поскольку мы не хотим, чтобы все желающие отправляли сообщение в очередь, метод кроме сообщения принимает логин и пароль оператора, используя примитивный способ аутентификации.
Данный интерфейс можно модифицировать, позволив пользователю кешировать часть сообщений на телефоне и передавать дату последнего доступного у него сообщения, чтобы обновлять интерфейс только новыми сообщениями. Сюда можно добавить языковую поддержку и другие параметры. Но сейчас это не столь важно.
Следующим шагом мы должны перейти к реализации интерфейса. Но это делать еще рано, так как нам необходимо еще хранилище для наших подписок и сообщений, а также где-то определить параметры приложения, такие как строка соединения с базой, логин и пароль оператора и т. д.
Первым делом создадим хранилище сообщений и подписок. Я решил использовать SQL Azure, так как меня больше устраивало реляционное хранилище. Данных тут не много, зато можно делать сложные выборки.
Для этого воспользуемся панелью управления Windows Azure и создадим новую базу
Тут же, в панели, можно увидеть строку подключения к базе, которую мы будем использовать из приложения. Вот пример такой строки:
Server=tcp:imc39784zf.database.windows.net,1433;Database=UkraineTest;User ID=sbaidachni@imc39784zf;Password=myPassword;Trusted_Connection=False;Encrypt=True;
Далее нажмите кнопку Manage и создайте две таблицы, позволяющие хранить подписки и сообщения.
Помните, чтобы тестировать подключения к базам в SQL Azure, вы должны через панель управления выполнить настройки firewall, которые позволят подключаться с Вашей девелоперской машины к базе.
Поскольку нам нужен также и Storage Service, то создадим и его. Для этого также воспользуемся панелью управления.
Подготовительная работа завершена.
Теперь вернемся в Visual Studio и приступим к написанию кода. Первым делом внесем изменения в конфигурацию решения.
Обратите внимание, что параметры приложения (строка соединения, логин, доступ к Storage аккаунту) нужно прописывать в csdef и cscfg файлах. Если Вы внесете настройки в Web.Config (как Вы привыкли делать в обычных веб-приложениях), то менять их, в процессе работы, у Вас не выйдет.
Поэтому перейдите к настройкам нашей веб-роли и введите необходимые параметры именно там.
Тут мы ввели Логин, Пароль, строку соединения к базе, а также строку соединения к Storage Account. Последняя может быть описана с помощью специальной панели:
Тут Вы указываете имя созданного Storage аккаунта и ключ, который можно взять в панели управления Windows Azure. Не забудьте поменять HTTPS на HTTP. Наши сообщения не представляют особого интереса, поэтому лишняя безопасность тут не требуется.
Последний параметры NRecords определяет, сколько сообщений мы хотим возвращать на телефон. Мы могли бы отдать эту настройку и пользователю, но я все равно хочу ограничить их количество сверху.
А теперь приступаем к реализации кода.
Первый метод, позволяющий подписаться на сообщения, будет выглядеть следующим образом:
1: public void SubscribePhoneToService(Guid guid, string pushServiceUri)
2: {
3: SqlConnection conn = new SqlConnection(RoleEnvironment.GetConfigurationSettingValue("DatabaseConnection"));
4: SqlCommand comm = new SqlCommand("select count(*) from PhoneTable where PhoneID=@par1", conn);
5:
6: comm.Parameters.Add(new SqlParameter("par1", guid.ToString()));
7:
8: conn.Open();
9:
10: int res = (int)comm.ExecuteScalar();
11:
12: if (res > 0)
13: {
14: SqlCommand comm1 = new SqlCommand("update phonetable set PhoneUrl=@par2 where PhoneID=@par1", conn);
15: comm1.Parameters.Add(new SqlParameter("par1", guid.ToString()));
16: comm1.Parameters.Add(new SqlParameter("par2", pushServiceUri));
17: comm1.ExecuteNonQuery();
18: }
19: else
20: {
21: SqlCommand comm1 = new SqlCommand("insert phonetable (PhoneID, PhoneUrl) values (@par1, @par2)", conn);
22: comm1.Parameters.Add(new SqlParameter("par1", guid.ToString()));
23: comm1.Parameters.Add(new SqlParameter("par2", pushServiceUri));
24: comm1.ExecuteNonQuery();
25: }
26:
27: conn.Close();
28: conn.Dispose();
29: }
Фактически, мы связываемся с базой, чтобы проверить наличие устройства. Если устройства нет, то мы вносим его URL в базу, если оно есть, то обновляем URL (он может измениться). Интерес представляет класс RoleEnvironment, позволяющий получить доступ к настройкам роли.
Второй метод, RefreshData, возвращает последние N сообщений из базы. Тут лучше использовать LINQ, чтобы уменьшить количество строк кода, но я сейчас не буду усложнять код технологиями.
1: SqlConnection conn = new SqlConnection(RoleEnvironment.GetConfigurationSettingValue("DatabaseConnection"));
2: string n = RoleEnvironment.GetConfigurationSettingValue("NRecords");
3:
4: SqlCommand comm = new SqlCommand("select TOP (" + n + ") * from messagetable order by messagedate desc", conn);
5:
6: conn.Open();
7:
8: SqlDataReader res = comm.ExecuteReader();
9:
10: List<SMSMessage> SMSMessages = new List<SMSMessage>();
11:
12: while (res.Read())
13: {
14: SMSMessages.Add(new SMSMessage() { MessageValue = res["MessageText"].ToString(), DateTimeValue = res["MessageDate"].ToString() });
15: }
16:
17: conn.Close();
18: conn.Dispose();
19:
20: return SMSMessages.ToArray();
А вот последний метод представляет наибольший интерес, так как именно тут идет работа с очередью.
1: if ((login.Equals(RoleEnvironment.GetConfigurationSettingValue("Login"))) && (password.Equals(RoleEnvironment.GetConfigurationSettingValue("Password"))))
2: {
3:
4: SqlConnection conn = new SqlConnection(RoleEnvironment.GetConfigurationSettingValue("DatabaseConnection"));
5: SqlCommand comm = new SqlCommand("insert messagetable (MessageText, MessageDate) values (@par1, @par2)", conn);
6: comm.Parameters.Add(new SqlParameter("par2", DateTime.Now.ToUniversalTime().ToString()));
7: comm.Parameters.Add(new SqlParameter("par1", sms));
8:
9: conn.Open();
10:
11: comm.ExecuteNonQuery();
12:
13: conn.Close();
14: conn.Dispose();
15:
16: CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
17: {
18: configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
19:
20: RoleEnvironment.Changed += (sender, arg) =>
21: {
22: if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
23: .Any((change) => (change.ConfigurationSettingName == configName)))
24: {
25: if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
26: {
27: RoleEnvironment.RequestRecycle();
28: }
29: }
30: };
31: });
32:
33: CloudStorageAccount acc = CloudStorageAccount.FromConfigurationSetting("StorageConnection");
34: CloudQueueClient queueClient = acc.CreateCloudQueueClient();
35:
36: CloudQueue queue = queueClient.GetQueueReference("smsqueue");
37: queue.CreateIfNotExist();
38:
39: queue.AddMessage(new CloudQueueMessage(sms));
40: }
Тут мы вставляем новое сообщение в нашу таблицу, а также размещаем его в очереди. Для работы очереди мы использовали управляемую библиотеку Microsoft.WindowsAzure.StorageClient.dll, которая облегчает нам работу с REST API. Итак, тут мы создаем объект типа CloudStorageAccount, который будет ассоциироваться с нашим Storage аккаунтом в Azure. После чего создаем объект типа CloudQueue, который будет ассоциироваться с нашей очередью. И с помощью метода CreateIfNotExist создает новую очередь или получаем ссылку на существующую. После этого можно добавлять элементы.
Теперь необходимо реализовать рабочую роль, добавить поддержку https и написать клиента. Но об этом в следующей статье.
Windows Phone 7: Application Bar
Глупая привычка, пришедшая с опытом создания Windows и Web приложений – создание всех интерфейсных элементов в окне приложения. Я сам на это купился, создавая свое первое приложение для Windows Phone 7 – Пятнашки. В основном окне этого приложения есть две кнопки: Refresh и About. Выглядят они странно (особенно About) и явно лишними. И все хорошо, пока в Вашем приложении нет полей редактирования, инициирующих вызов клавиатуры, закрывающей часть необходимых кнопок. Представьте приложение, имеющее поле редактирования на весь экран, а внизу экрана кнопку Send, позволяющую отправить сообщение. При вводе текста, кнопка Send будет перекрыта клавиатурой, а начинающий пользователь будет ломать голову, что с этим делать и как добраться до кнопки. Именно поэтому, Windows Phone 7 приложения имеют возможность использовать специальную панель для элементов управления Application Bar.
Application Bar представляет собой всплывающую панель внизу окна приложения, которая может содержать от одной до четырех кнопок, позволяющих выполнить какие-то действия. Кроме того, тут может присутствовать не иерархическое текстовое меню. Меню может быть привязано к одной из кнопок панели и в основном используется для выбора одной из опций приложения.
Application Bar не может быть перекрыт клавиатурой или другими элементами, а при вызове «сдвигает» весь интерфейс. Правда это происходит в том случае, если прозрачность установлена в 1. Если прозрачность установлена в значение меньшее 1, то Application Bar начинает перекрывать экран, используя эффект прозрачности.
Итак, попробуем создать простой Application Bar. Первое, что необходимо сделать, это определиться с иконками. Некоторые иконки доступны в папке C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Icons\dark, а остальные нужно нарисовать самостоятельно. При создании иконки есть несколько рекомендаций: 1). Иконку рисуют белым цветом на прозрачном фоне. При изменении темы, такая практика позволяет сделать иконку видимой для пользователя; 2). Размер иконки должен быть 48 на 48 пикселей, но все, что Вы нарисовали, нужно уместить в прямоугольник 26 на 26 пикселей и расположить изображение по центру. Все от того, что любое изображение будет заключено в окружность радиусом 14. Если Ваше изображение будет больше, то возникнут пересечения.
Итак, чтобы добавить кнопку Refresh и About в Application Bar приложения, достаточно в MainPage.xaml добавить следующий код:
1: <phone:PhoneApplicationPage.ApplicationBar>
2: <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
3: <shell:ApplicationBarIconButton
IconUri="/Images/appbar.refresh.rest.png"
Text="Refresh" Click="ClickRefresh"/>
4: <shell:ApplicationBarIconButton
IconUri="/Images/appbar.questionmark.rest.png"
Text="About" Click="ClickAbout"/>
5: </shell:ApplicationBar>
6: </phone:PhoneApplicationPage.ApplicationBar>
Иконки я выбрал из SDK, установив Build Action в Content и Copy to Output Directory в Copy Always.
Вот такая панель у нас получилась:
Естественно, чтобы панель работала, необходимо реализовать обработчики событий ClickAbout и ClickRefresh.
Добавим к этой панели возможность выбора языка интерфейса. Для этого расширим Application Bar двумя пунктами меню:
1: <phone:PhoneApplicationPage.ApplicationBar>
2: <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
3: <shell:ApplicationBarIconButton
IconUri="/Images/appbar.refresh.rest.png" Text="Refresh" Click="ClickRefresh"/>
4: <shell:ApplicationBarIconButton
IconUri="/Images/appbar.questionmark.rest.png" Text="About" Click="ClickAbout"/>
5: <shell:ApplicationBar.MenuItems>
6: <shell:ApplicationBarMenuItem Text="Russian"
Click="SetLanguageClick"></shell:ApplicationBarMenuItem>
7: <shell:ApplicationBarMenuItem Text="English"
Click="SetLanguageClick"></shell:ApplicationBarMenuItem>
8: </shell:ApplicationBar.MenuItems>
9: </shell:ApplicationBar>
10: </phone:PhoneApplicationPage.ApplicationBar>
В результате мы увидим следующую панель:
Нужно сказать, что меню в Application Bar очень часто не оправдывают себя. С таким же успехом я мог бы разместить кнопку Language и переводить пользователя на отдельную страницу, по выбору языка.
Проблема в Application Bar состоит в том, что это элемент управления Windows Phone 7, и он не поддерживает возможности Silverlight-элементов управления, например, связывание с данными. Несмотря на это, элемент управления поддерживает возможность динамического заполнения из языка программирования C#.
Так, класс ApplicationBar находится в пространстве имен Microsoft.Phone.Shell. Доступ к ApplicationBar осуществляется через соответствующее свойство класса PhoneApplicationPage.
В общем штука хорошая, поэтому пользуйтесь.
Windows Phone 7: Публикация приложений
Поскольку украинские разработчики могут пробовать публиковать свои приложения (распространяемые бесплатно) прямо сейчас, то мне бы хотелось остановиться на вопросе публикации приложений, разобрав процесс и остановившись на основных ошибках.
Итак, первое, что необходимо сделать при публикации в Marketplace, это убедиться, что приложение обладает иконкой, отличной от той, которая используется по умолчанию. Таких иконок две: 62 на 62, используемая при отображении приложения в общем списке; 173 на 173, используемая при привязке приложения к основному окну.
Таким образом, если при тестировании Вы увидели иконку, аналогичную иконке ниже, то Ваше приложение не примут. Не совершайте этой ошибки.
Чтобы изменить иконку, в проекте Visual Studio достаточно заменить файлы ApplicationIcon.png и Background.png.
Если Вы добавили файлы со своими именами, то они должны находиться в корневой директории и иметь свойство Build Action установленным в Content. Далее можно отредактировать манифест приложения, используя дизайнер Visual Studio, перейдя в окно свойств проекта:
Имея готовый пакет для публикации, переходим к публикации приложения. Для этого нам нужны следующие компоненты:
· Сам пакет xap, содержащий приложение
· Иконки в формате png 173 на 173, 200 на 200, 99 на 99
· Минимум один скрин приложения 480 на 800
· Короткое описание приложения
Это тот минимум, который необходим для публикации приложений.
Вторая ошибка, которая возникает при публикации – неправильные скрины вашего приложения. Поскольку Вы будете снимать скрины используя эмулятор, ни в коем случае нельзя захватывать фрейм эмулятора. Нужно захватывать только окно приложения. Если Вы захватили фрейм, то приложение не примут.
Третья ошибка связана с языком приложения. Естественно, создавая приложение для украинского рынка, нет никакого желания использовать английский язык. Вы с легкостью можете использовать русский или украинский, но при описании приложения, Вы должны включить два описания подряд, на английском и сразу же на русском:
Если Вы сделали это, то приложение примут.
Последняя, четвертая ошибка – приложение должно иметь окно типа About, содержащее информацию об авторе приложения, контактах для поддержки. Данное окно должно быть легко доступно. Если этого окна (даже примитивного MessageBox) нет, то приложение не примут.
Вот и все. Это основные ошибки, с которыми мы столкнулись при публикации приложений. Присылайте Ваши приложения для публикации.
Начинаем разрабатывать для Windows Phone 7: Настройка клавиатуры
Чтобы почувствовать дух Windows Phone 7 и посмотреть на различия в подходах построения обычных Silverlight- и Windows Phone приложений, рассмотрим несколько небольших примеров.
Пример 1. Управление клавиатурой
Начнем с простого элемента управления TextBox, который позволяет вводить текст. В обычной реализации этот элемент ничем особым не выделяется. Но если говорить о Windows Phone 7, то вопрос ввода очень существенен. Так, двигаясь со скоростью 130-160 км/ч, мне очень затруднительно делать ввод данных на наших дорогах. Поэтому моим простым желанием является то, чтобы клавиатура содержала только тот набор элементов, который нужен мне в данном контексте. То есть, если я ввожу телефонный номер, то я должен видеть только цифры, а если я переписываюсь в месенджере, то мне необходимы не только буквы, но и специальные символы. В идеале я бы хотел иметь и проверку орфографии. Все эти возможности в Windows Phone 7 присутствуют. И если проверка орфографии выполняется автоматически, то управлять клавиатурой при вводе текста можно с помощью простого свойства InputScope элемента TextBox.
Ниже показан простой пример, «настраивающий» элемент TextBox для ввода электронного адреса:
<TextBox>
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="EmailUserName"></InputScopeName>
</InputScope>
</TextBox.InputScope>
</TextBox>
В результате на экране будет появляться следующая клавиатура:
@17.4 Ввод электронного адреса
Подобный код можно реализовать и программно, настраивая элементы TextBox динамически:
txtBox.InputScope = new InputScope()
{
Names =
{
new InputScopeName()
{
NameValue = InputScopeNameValue.EmailUserName
}
}
};
