Блог Сергея Байдачного

Мой блог о технологиях

Archive for the ‘Windows Phone’ Category

Зачем участвовать в конкурсе, если в Украине нет магазина для Windows Phone

2 комментария

Заранее извинюсь перед аудиторией. Обычно я сдержан, но иногда накапливается много негатива и срывает крышу. Вот, кажется, сейчас именно такой случай. В чем же дело?

Совсем недавно мы объявили о конкурсе Windows Phone для украинских разработчиков и студентов http://wp8.promorc.com. Чтобы принимать участие в конкурсе, нужно быть гражданином Украины и опубликовать приложение с украинского аккаунта.

Сразу же после этого, на меня посыпался град писем о том, что смысла в этом нет, так как украинцы все еще не могут зарабатывать деньги в Windows Phone Store.

Коллеги, давайте разберемся, кто, зачем и почему:

1. Вы являетесь украинским мега разработчиком для Windows Phone и пишите классные приложения? Тогда Вам немедленно нужно написать мне и мы подумаем о том, как делать совместные промо Ваших приложений. У нас есть некоторые возможности и мы очень хотим, чтобы Вы заработали много денег, неважно под каким аккаунтом. Ведь это самый хороший PR платформе. Подозреваю, что на этом этапе у Вас и телефон есть и Вы уже думаете о том, как заработать первый миллион.

2. Вы только думаете разрабатывать для платформы Windows Phone, являясь разработчиком на других платформах или студентом? Тут я могу рассмотреть свой пример. Последние несколько месяцев я хватался за несколько пилотов на Windows 8, преследуя одну цель «Получить хороший опыт в разработке Windows 8 приложений». Причем в этих приложениях нет и упоминания обо мне, но, глядя на свое первое приложение для Windows 8 я прихожу в ужас и тайно мечтаю его переписатьJ Вы же не думаете, что полистав книгу о Windows Phone тут же заработаете миллион? Нужен опыт и дополнительный пинок, чтобы ускорить процесс. Ведь если писать что-то для себя и без временных целей, то можно и за жизнь не успеть Hello World написать. Вот конкурс и является тем волшебным пинком, который позволит Вам собраться и что-то начать делать.

3. Вы хотите узнать roadmap платформы для украинских разработчиков? Коллеги, когда у меня будет информация о доступности платного стора для телефонов, то я ее не буду скрывать перед Вами. Но не думайте, что я в комментариях раскрою Вам какой-то волшебный секрет.

4. Вы просто хотите попиз… (то есть, Вам скучно и одиноко и очень нужно с кем-то поговорить)? Тепаете на itc.ua открываете любую новость об устройствах и начинаете рассказывать, почему Windows Phone лучшая в мире платформа. Там живет такое количество троллей, что скучно Вам не будет! А у меня и без этого голова забита разной фигней.

Written by Sergiy Baydachnyy

25.12.2012 at 09:35

Опубликовано в Windows Phone

Tagged with

Бесплатные курсы по Windows Phone и Windows 8 для студентов

with one comment

Чтобы стимулировать украинских студентов создавать больше приложений и принимать участие в Imagine Cup 2013, мы решили запустить серию онлайн курсов по самым последним технологиям. Лично я буду читать Windows Phone и Windows 8.

Вот ссылки на регистрационную форму для первых лекций:

Разработка приложений для Windows Phone (8 января)

Разработка приложения для Windows 8 (10 января)

Для организации лекций будем использовать Lync.

Written by Sergiy Baydachnyy

24.12.2012 at 18:36

Опубликовано в Windows 8, Windows Phone

Tagged with ,

Распознавание и обработка речи (часть 2)

leave a comment »

Преобразование текста в речь

Еще одна, не менее интересная задача, это преобразование текста в человеческую речь. Чтобы реализовать подобный функционал в приложении первым делом нужно определить возможность ID_CAP_SPEECH_RECOGNITION в манифесте приложения:

<Capabilities>
  <Capability Name="ID_CAP_SPEECH_RECOGNITION" />
</Capabilities>

 

Теперь можно переходить к синтезу голоса. Для этого воспользуемся пространством имен Windows.Phone.Speech.Synthesis, которое содержит всего несколько полезных классов:

· InstalledVoices – этот класс содержит всего два свойства (All и Default) и позволяет предоставить информацию об установленных языках на телефоне пользователя. Тут программист может проверить, есть ли требуемый язык и подобрать тот, который подходит для данной ситуации, в противном случае система возьмет язык по умолчанию;

· VoiceInformation – этот класс содержит информацию о голосе. Тут содержится язык, пол синтезатора (как ни странно звучит). Используется совместно с InstalledVoices при обращении к свойству Default или переборе всей коллекции доступных языков в All. Сам по себе объект класса создать нельзя;

· SpeechSynthesizer – вот это и есть самый интересный класс, который выполняет преобразование текста в речь.

Фактически, чтобы преобразовать текст в речь, достаточно создать объект класса SpeechSynthesizer и вызвать метод SpeakTextAsync. Как видно из названия метода, он является асинхронным и поддерживает подход вызова через async/await. Естественно, чтобы вызвать метод, желательно проверить наличие нужного Вам языка, а еще лучше, установить его в качестве текущего с помощью метода SetVoice. Код ниже проверяет наличие русского языка, а в случае его присутствия, произносит фразу фразу «Привет», используя женский и мужской голос последовательно:

if ((from a in InstalledVoices.All 
     where a.Language.Contains("ru") 
     select a).Count() > 0)
{
    SpeechSynthesizer sr = new SpeechSynthesizer();
    sr.SetVoice((from a in InstalledVoices.All 
                 where a.Language.Contains("ru") 
                 select a).First());
    await sr.SpeakTextAsync("Привет");
    sr.SetVoice((from a in InstalledVoices.All 
                 where a.Language.Contains("ru") 
                 select a).Last());
    await sr.SpeakTextAsync("Привет");
}

 

Естественно, что преобразование текста в речь на основе простого текста не очень интересно, так как часто нужно использовать женский и мужской голос в одном абзаце, использовать разные языки, отправлять приложению событие при завершении произнесения части фразы и др. Все это можно делать, если использовать не простой текст, а набор инструкций, описанных с помощью специального языка Speech Synthesis Markup Language (SSML). Традиционно SSML базируется на XML и поддерживается в классе SpeechSynthesizer двумя методами: SpeakSsmlAsync и SpeakSsmlFromUriAsync. Первый метод принимает в качестве параметров строку, содержащую SSML, а второй – путь к файлу с соответствующими инструкциями.

Рассмотрим все элементы, из которых может состоять SSML документ:

· audio – позволяет вставить заранее подготовленный аудио файл. Это позволяет снабдить монолог дополнительными аудио эффектами. В качестве атрибута используется src – путь к файлу;

· break – позволяет задавать паузу. Для этого используется атрибут duration, который задает паузу в секундах или миллисекундах или атрибут strength, принимающий одно из предопределенных значений;

· emphasis – теоретически этот элемент должен позволять произносить текст с разным уровнем интонации, но это в Windows Phone 8 пока не реализовано;

· lexicon – этот элемент позволяет задать разработчику собственный лексикон, базируясь на специально созданной для этого спецификации Pronunciation Lexicon Specification (PLS). Это необходимо для сложных приложений, где необходимо четко задать набор слов и правильное их произношение;

· mark – позволяет задать метку, используя атрибут name. При достижении метки в приложении генерируется событие BookmarkReached. Это позволяет легко синхронизировать речь с происходящим на экране.

· p и s – позволяют задать параграф или высказывание. Элементы не обязательные, но имеют важный атрибут xml:lang, который позволяет переустановить язык;

· phoneme – с помощью этого элемента можно задать специальное произношение для заданной группы символов. Очень часто это касается имен;

· prosody – содержит много атрибутов, но пока поддерживается только volume, который позволяет задать громкость от 0 до 100;

· sayas – позволяет задать произношения для дат, времени, числительных и др. Очень полезный элемент, учитывая то, что те же даты пишутся по разному;

· speak – задает коневой элемент для всего SSML документа;

· sub – позволяет задать развернутое написание для аббревиатур;

· voice – позволяет задать голос, указав мужской или женский, язык и другие параметры.

Если Вы создаете файл с расширением ssml, то Visual Studio автоматически включает систему IntelliSense, что очень удобно. Пример простого ssml файла:

<speak version="1.0" 
       xmlns="http://www.w3.org/2001/10/synthesis" 
       xml:lang="ru-RU">
  <s xml:lang="ru">Чтобы сказать добрый день по английски, произнесите</s>
  <s xml:lang="en">Good morning</s>
</speak>

 

Код, который может открыть этот файл может выглядеть вот так:

SpeechSynthesizer sr = new SpeechSynthesizer();
string path = Package.Current.InstalledLocation.Path + "\\text.ssml";
Uri url = new Uri(path, UriKind.Absolute);
await sr.SpeakSsmlFromUriAsync(url);

 

Не забудьте проверить, что в свойствах файла указано Build Action = Content. По умолчанию это не происходит и Вы получите исключение о том, что файл не найден.

Written by Sergiy Baydachnyy

20.12.2012 at 22:03

Опубликовано в Windows Phone

Tagged with

Конкурс для Windows Phone разработчиков в Украине

2 комментария

Вспомнил, что не писал о таком замечательном конкурсе: http://wp8.promorc.com, который мы сейчас проводим для всех разработчиков и студентов в Украине.

На конкурсе 4 номинации:

· Лучшее приложение (тут все, что угодно – бизнес, социалка и др.)

· Лучшая игра

· Лучшее студенческое приложение (чтобы дать возможность студентам получить приз с хорошим приложением, если их вытеснят разработчики из первых двух номинаций.)

· Лучшее приложение для Windows Phone 8 (тут речь идет о приложениях, которые утилизируют новые возможности платформы. Чем лучше и полезней эта утилизация, тем лучше для конкурса)

Ограничения: только жители Украины, приложение должно быть опубликовано с украинского аккаунта (смысл делать метрики другой стране?) и приложение должно быть опубликовано в ходе конкурса (нас интересует что-то новенькое).

До конца конкурса осталось еще 54 дня. Поэтому время еще есть.

Written by Sergiy Baydachnyy

20.12.2012 at 12:54

Опубликовано в Windows Phone

Tagged with ,

Распознавание и обработка речи (часть 1)

2 комментария

 

Я всегда скептически относился к голосовым возможностям устройств. Я просто не верил в том, что они могут достаточно хорошо работать, чтобы удовлетворить мои потребности. При этом, проводя много времени за рулем мне всегда не хватало возможности быстрого набора номера из моей адресной книги в несколько сотен контактов или быстрого запуска каких-то приложений. Ведь вход в меню, поиск по нескольким символам и выбор действия, требуют многих нажатий на экране и крайне нежелательны во время движения. Сейчас я понимаю, что излишний скептицизм мне успел здорово навредить, ведь функционал, позволяющий выполнять голосовой набор номера или запустить отдельное приложение был еще в Windows Phone 7. Нужно было только попробовать. А вот попробовав, мне уже сложно отказаться от этой возможности, ведь несмотря на то, что контакты и приложения в моем устройстве используют как латиницу, так и кириллицу, все работает просто замечательно.

Если Вы еще не пробовали голосовые возможности, то сделайте это, но прежде проверьте настройки Вашего устройства. Для этого перейдите в раздел Settings (Настройки) -> Speech (Голосовые функции) и выберите язык голосовых функций и другие параметры:

image

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

Параметр Play audio confirmation позволяет включить или выключить оповещения о действие, которое сейчас выполняется. Так, после отправки голосовой команды у пользователя есть пару секунд перед тем, как действие будет выполнено. За это время можно успеть отменить операцию, нажав кнопку Cancel.

image

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

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

Последний параметр Enable Speech Recognition Service позволяет включить возможности распознавания голоса в приложениях. Тут ситуация, аналогичная определению местоположения – пользователь может запретить функции распознавания голоса в приложениях. Включая эту функциональность пользователь соглашается с тем, что Microsoft может собирать информацию о запросах пользователя для улучшения словаря и других функций распознавания.

Наконец, когда все настройки сделаны, можно попытаться отправить команду устройству. Для этого на пару секунд следует зажать аппаратную кнопку Start на лицевой панели телефона, что приведет к вызову диалогового окна, позволяющего слушать пользователя и распознавать команды:

image

Тут можно сказать одну из стандартных команд, таких как «Позвонить….», «Запустить…» или вызвать одну из команд, которые декларируют другие приложения. Чтобы увидеть все команды нажмите на вопросительный знак в вернем правом углу окна или произнесите «Что я могу сказать».

Это все конечно очень интересно, но для пользователя. Давайте посмотрим, какие же возможности доступны разработчику при работе с интерфейсом по распознаванию голоса. Итак, в Windows Phone 8 разработчик может реализовывать один из трех механизмов, это ассоциировать со своим приложение голосовые команды, преобразовывать голос в текст внутри приложения, преобразовывать текст в голос внутри приложения. Давайте рассмотрим каждую из этих возможностей детально.

Голосовые команды

Любое приложение, которое присутствует на телефоне пользователя, может быть запущено с помощью голосовой команды «Запустить <имя приложения>». Но тут есть несколько нюансов. Во-первых, имя приложения может быть плохо читаемым или слишком сложным для произношения. Во-вторых, стандартная команда позволяет запустить приложение без каких-либо параметров. Поэтому, одной из первых задач, актуальной для многих приложений, является необходимость определения команд, которые можно использовать для запуска приложения.

Итак, чтобы определить свои команды для приложения, первым делом нужно задекларировать несколько возможностей, это ID_CAP_NETWORKING, ID_CAP_MICROPHONE, ID_CAP_SPEECH_RECOGNITION:

<Capabilities>
  <Capability Name="ID_CAP_NETWORKING" />
  <Capability Name="ID_CAP_MICROPHONE" />
  <Capability Name="ID_CAP_SPEECH_RECOGNITION" />
</Capabilities>

 

Данные возможности можно задекларировать и в графическом редакторе манифеста. Первая декларация необходима для передачи данных по сети в службу Microsoft для оптимизации службы поиска (не уверен, что тут это используется, но…), вторая – для реализации доступа к микрофону и третья – для активации механизма распознавания голоса.

Включив все необходимые возможности, переходим к описанию команд. Это можно сделать в XML файле. Чтобы не искать структуру этого файла в документации, достаточно воспользоваться готовым шаблонов в Visual Studio. Просто создайте новый элемент на основе шаблона Voice Command Definition:

image

В результате будет создан вот такой файл, который мы рассмотрим сейчас детально:

<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
  <CommandSet xml:lang="en-US">
    <CommandPrefix>Contoso Rodeo</CommandPrefix>
    <Example> play a new game </Example>

    <Command Name="PlayGame">
      <Example> play a new game </Example>
      <ListenFor> [and] play [a] new game </ListenFor>
      <ListenFor> [and] start [a] new game </ListenFor>
      <Feedback> Starting a new game... </Feedback>
      <Navigate />
    </Command>

    <Command Name="PlayLevel">
      <Example> replay level two </Example>
      <ListenFor> replay level {number} </ListenFor>
      <Feedback> Going to level {number}... </Feedback>
      <Navigate />
    </Command>

    <Command Name="PlayUnknownLevel">
      <Example> replay level two </Example>
      <ListenFor> [and] replay level {*} </ListenFor>
      <Feedback> Unknown level; going to level selection... </Feedback>
      <Navigate Target="LevelSelect.xaml" />
    </Command>

    <PhraseList Label="number">
      <Item> one </Item>
      <Item> two </Item>
      <Item> three </Item>
    </PhraseList>

  </CommandSet>
</VoiceCommands>

 

Тут все команды разбиты на множества, описывающиеся с помощью элемента CommandSet. Как Вы видите, атрибутом CommandSet является xml:lang, который определяет язык данного множества команд. Если Вы пишите интернациональное приложение, то наверняка включите поддержку для нескольких языков, перечислив для каждого из них свое множество команд.

Следующий важный элемент, это CommandPrefix, который задает команду для запуска приложения. Обычно тут указывается произносимое для пользователя имя приложения, но фактически это аналог команды, которая заменяет стандартную «Запустить <имя приложения>».

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

Наконец, чтобы передать приложению параметры в XML задается набор элементов типа Command. Именно эти элементы расширяют стандартную команду, описанную в CommandPrefix и позволяют пользователю перевести приложение в нужное ему состояние. Например, если Вы пишите приложение для отображения телепрограммы, то его можно запустить по команде «Телепрограмма» или «Телепрограмма на Первом», чтобы открыть список каналов или программу для конкретного канала. Тут три основных элемента, это ListenFor, Feedback и Navigate.

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

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

Если вернуться к той же телепрограмме, то каналов, которые поддерживает приложение, может быть достаточно много. Естественно, что в данном случае логично задать какой-то шаблон. Для этого используются фигурные скобки, в которых содержится имя списка с возможным набором слов, подставляемых в шаблон. В файле по умолчанию это шаблон name, описываемый элементом PhraseList, со списком уровней. В случае с телепрограммой, это будет список каналов. В фигурных скобках можно указывать и звездочку {*}, что означает подстановку любой фразы. Обычно {*} используют в команде, которая идет следом за командой, ссылающейся на PhraseList, чтобы обеспечить реакцию приложения в ответ на команду, которая не описывается в предопределенном списке.

Элемент PhraseList еще интересен тем, что его не имеет смысл задавать заранее (если у Вас много фраз), а можно заполнить динамически.

Давайте рассмотрим пример на основе приложения для отображения Телепрограммы. Вот как может выглядеть XML файл:

<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
  <CommandSet xml:lang="ru-RU" Name="ru-RU">
    <CommandPrefix>Телепрограмма</CommandPrefix>
    <Example>Телепрограмма</Example>

    <Command Name="ChannelsComm">
      <Example>на Первый</Example>
      <ListenFor> [сегодня] [на] {channels} </ListenFor>
      <Feedback> Телепрограмма на {channels} открывается... </Feedback>
      <Navigate />
    </Command>

    <PhraseList Label="channels">
      <Item>Первый</Item>
    </PhraseList>

  </CommandSet>
</VoiceCommands>

 

Как Вы видите, тут указана поддержка русского языка, а приложению назначается более пристойное имя чем в оригинале (у меня это PhoneApp 9J). Теперь приложение можно запустить, сказав «Запустить Телепрограмма» или «Телепрограмма на Первый» и т. д. Но, прежде чем это начнет работать, необходимо инициализировать этот файл. Это можно сделать при первом запуске приложения с помощью класса VoiceCommandService, который содержит метод InstallCommandSetsFromFileAsync, позволяющем инициализировать команды из XML. Вот как может выглядеть метод, выполняющий инициализацию:

private async void InitVoiceCommands()
{
    if (VoiceCommandService.InstalledCommandSets.Count == 0)
    {
        await VoiceCommandService.InstallCommandSetsFromFileAsync(
           new Uri("ms-appx:///MyVoiceCommand.xml"));
    }
}

 

Тут я также проверил, не были ли инициализированы команды ранее, чтобы не выполнять лишнюю работу во время второго и последующих запусков приложения. Метод можно вызвать из InitializePhoneApplication, который в свою очередь вызывается из конструктора класса App в файле App.xaml.cs.

Остается еще две задачи, а именно заполнить коллекцию фраз (каналов), а также обработать параметры, которые получает приложение.

Чтобы заполнить коллекцию фраз можно воспользоваться следующим куском кода:

await VoiceCommandService.InstalledCommandSets["ru-RU"].UpdatePhraseListAsync(
      "channels", new List<string>() { "Первый", "Новый", "Интер" });

 

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

Наконец, подготовительная работа закончена, осталось дождаться команды пользователя и верно ее обработать. Но тут уже все просто. Достаточно описать метод OnNavigatedTo на тех страницах, куда ведут Ваши команды и использовать класс NavigationService для получения строки запроса (QueryString).

image

Как видно из рисунка выше (я поставил точку останова при отладке в методе OnNavigatedTo), в случае запуска приложения с помощью одной из команд, QueryString содержит несколько параметров. Обязательным является voiceCommandName, который содержит имя команды. Параметр reco содержит текст, который был распознан при отправке команды пользователю на основе заданного шаблона, а параметр channels содержит фразу. Этих данных вполне хватит, чтобы принять решение о дальнейшем поведении приложения.

Written by Sergiy Baydachnyy

18.12.2012 at 17:57

Опубликовано в Windows Phone

Tagged with

Windows Phone 8: Интеграция с экраном блокировки

with one comment

Если Вы уже исследовали настройки телефона на реальном устройстве, то могли обнаружить отдельный раздел Экран блокировки (lock screen). Тут пользователь может задать такие параметры экрана блокировки своего устройства, как:

· изображение, которое будет являться фоном для экрана блокировки;

· приложение, которое будет иметь возможность выводить на экран блокировки короткие сообщения (по умолчанию задан Календарь);

· до пяти приложений, которые смогут отображать свой статус на экране блокировки. Тут под статусом понимается иконка приложения и счетчик (например, количество не прочитанных сообщений)

Вот как выглядят настройки экрана блокировки по умолчанию:

 

image

 

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

Фон для экрана блокировки

Когда я наблюдаю за тем, как пользователь Windows Phone купив новый чехол для своего устройства тут же спешит поменять цвет плиток под цвет своего чехла, я начинаю осознавать важность различных «рюшечек», одной из которых есть возможность установки новой заставки на экран блокировки пользователя. Тут не только можно порадовать пользователя, но и заработать деньги, предоставляя коллекции красивых заставок.

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

 

<Extensions>
    <Extension ExtensionName="LockScreen_Background" 
               ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" 
               TaskID="_default" />
</Extensions>

 

Элемент Extensions располагается сразу после элемента Tokens и не содержит никакой изменяемой информации. Иными словами его нужно просто скопировать. Но, если данный элемент отсутствует, то любые попытки установить фон экрана блокировки из кода будут вызывать исключение.

Итак, первый способ сделать Ваше приложение провайдером заставок, это понадеяться на пользователя. Если приложение декларирует расширение LockScreen_Background, то оно появляется в списке приложений, доступных при настройке фона в разделе настроек телефона «Экран блокировки». Тут пользователь может выбрать Ваше приложение и тут же открыть его.

 

image

 

Предположим пользователь выбрал Ваше приложение, но решил не открывать его, не дав Вам возможность провести инициализацию экрана блокировки своими данными. Независимо от этого, заставка на экране блокировки должна поменяться, чтобы не разочаровывать пользователя. Именно поэтому, приложение должно предоставлять изображение для экрана блокировки по умолчанию. Это файл с фиксированным именем DefaultLockScreen.jpg, который должен находиться в корневой директории пакета приложения. Не забудьте добавить этот файл в пакет!

Если пользователь все же открыл Ваше приложение из настроек, то самое время провести инициализацию экрана и запросить настройки у пользователя. Чтобы определить, откуда было запущено приложение (окно настроек, либо другим способом), достаточно обработать параметры, которые передаются на главную страницу приложения. Если среди параметров есть WallpaperSettings равный единице, то приложение было запущено из окна настроек экрана блокировки. Вот пример обработки этого параметра:

 

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if ((e.NavigationMode==NavigationMode.New)&&
        (NavigationContext.QueryString.Keys.Contains("WallpaperSettings"))&&
        (NavigationContext.QueryString["WallpaperSettings"].Equals("1")))
    {
        NavigationService.Navigate(new Uri("/Settings.xaml"));
    }

    base.OnNavigatedTo(e);
}

 

Тут нам нужно проверить, что страница действительно была только что создана, что параметр WallpaperSettings был передан и равен единице (если был передан). Если это так, то мы перенаправляем пользователя на страницу настроек, связанных с экраном блокировки, или сразу переходим к установке каких-то изображений.

Второй способ сделать Ваше приложение провайдером изображений на экран блокировки, то явно запросить разрешение на это у пользователя. Для этого следует воспользоваться пространством имен Windows.Phone.System.UserProfile, где есть два нужных нам класса, это LockScreen и LockScreenManager. С помощью LockScreenManager можно определить, является ли наше приложение провайдером изображений в данным момент времени. Для этого используется свойство IsProvidedByCurrentApplication. Если свойство возвращает значение true, то все в порядке и можно приступать к установке изображений. В противном случае, можно запросить право стать провайдером прямо из приложения. Для этого можно воспользоваться методом RequestAccessAsync. Этот метод возвращает значение перечислимого типа LockScreenRequestResult, способное принимать значение Granted или Denied. Это позволяет избежать дополнительных объяснений пользователю и не перебрасывать его на страницу настроек, а решить все на месте. При вызове метода RequestAccessAsync пользователь увидит на экране всплывающее сообщение подобного типа:

 

image

 

Наконец, когда разрешения получены и все проверки сделаны, можно установить новое изображение на экран блокировки. Для этого используется класс LockScreen из того же пространства имен. Тут используется всего два метода, это GetImageUri и SetImageUri, которые позволяют получить имя файла с текущим изображением, а также установить новое изображение. Изображение может находится как внутри пакета, так и в изолированном хранилище. В зависимости от этого при формировании Uri используйте префикс msappx:/// или msappdata:///local/ соответственно. Если изображение находится в сети, то его нужно предварительно скопировать в изолированное хранилище. При этом следите, чтобы имя файла не повторялось при копировании. В противном случае платформа решит, что изображение не поменялось и не произведет обновление.

Сообщения и статус для экрана блокировки

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

Итак, чтобы задекларировать возможность приложения отображать сообщения и статус на экране блокировки, достаточно в манифест добавить следующие расширения:

 

<Extensions>
  <Extension ExtensionName="LockScreen_Notification_IconCount" 
             ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" 
             TaskID="_default" />
  <Extension ExtensionName="LockScreen_Notification_TextField" 
             ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" 
             TaskID="_default" />
</Extensions>

 

Тут, первое расширение декларирует возможность отображать счетчик приложения, а второе – текстовое сообщение. Естественно, что можно вместо двух расширений указать только одно из них. Тут все зависит от функциональности и потребностей приложения.

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

Еще один шаг, который необходимо сделать, это предоставить иконку для отображения статуса. Это специальная иконка приложения, которая отображается рядом со счетчиком и имеет размер 38 на 38 пикселей в формате png. При этом для создания иконки можно использовать только белый цвет, размещенный на прозрачном фоне. Любая другая иконка не пройдет сертификацию. Как только иконка у Вас готова, ее необходимо описать в манифесте, используя элемент DeviceLockImageURI внутри элемента, описывающего основную плитку приложения (например, TemplateFlip):

 

<DeviceLockImageURI IsRelative="true" 
                 IsResource="false">Assets\LockImage.png
</DeviceLockImageURI>

 

Тут указывается месторасположение иконки и путь к ней.

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

Written by Sergiy Baydachnyy

17.12.2012 at 22:12

Опубликовано в Windows Phone

Tagged with

Windows Phone 8 Camp–Видео с события

leave a comment »

Загрузил видео с Windows Phone 8 Camp в сеть. Если кому-то будет не лень, то можете перепубликовать в другие места.

Итак,

1). Обзор новых устройств Nokia, национальный тренер Nokia (217 Mb)

2). Обзор новых возможностей в Windows Phone 8 – часть 1, Сергей Байдачный (372 Mb)

3). Модель работы приложений в Windows Phone 8, Сергей Лутай (393 Mb)

4). Обзор новых возможностей в Windows Phone 8 – часть 2, Сергей Байдачный (457 Mb)

5). Windows Phone 8: лучшие практики для разработки высококлассных приложений, Александр Краковецкий (481 Mb)

6). C++ при разработке Windows Phone 8 приложений, Сергей Байдачный (207 Mb)

 

Презентация с моего доклада тут.

Written by Sergiy Baydachnyy

16.12.2012 at 19:53

Опубликовано в Windows Phone

Tagged with

Использование карт (часть 2)

leave a comment »

Расширение возможностей по работе с картами

Очень много задач не только требуют отобразить карту и какие-то элементы на ней, но и реализовать поиск координат места по названию и наоборот, отобразить путь, посчитать расстояние до цели и др. Карты от Nokia позволяют реализовывать и все эти задачи. Для этого обратимся к пространству имен Microsoft.Phone.Maps.Services, где содержатся все утилитные классы.

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

Чтобы найти позицию по адресу, необходимо использовать класс GeocodeQuery. Этот класс содержит два свойства, которые позволяют установить начальные параметры для поиска, это SearchTerm и GeoCoordinate. Первое свойство SearchTerm позволяет задать параметры поиска. Тут не обязательно должен быть точный адрес, так как класс GeocodeQuery позволяет получить коллекцию результатов поиска. Поскольку результатов может быть несколько, то для правильной сортировки и оптимизации поиска задается свойство GeoCoodinate. Обычно это свойство задает текущую позицию устройства и позволяет не выдавать заведомо бесполезные результаты (например, адреса в США, когда Вы находитесь в Украине). При сложных сценариях GeoCoordinate можно устанавливать в любую позицию.

Создав объект типа GeocodeQuery и задав основные свойства, можно переходить к поиску. Для этого используется метод QueryAsync, который после своего завершения работы инициирует событие QueryCompleted. Поэтому, следует повесить обработчик события QueryCompleted и можно вызывать метод. Внутри обработчика события QueryCompleted следует проверить количество результатов и возможность возникновения ошибки. Вот небольшой пример кода, который выполняет поиск адреса:

 

 private async void OneShotLocation_Click()
 {
     GeocodeQuery MyGeocodeQuery = new GeocodeQuery();
     MyGeocodeQuery.SearchTerm = "Dnepropetrovsk, Marksa 101";
     MyGeocodeQuery.GeoCoordinate = new GeoCoordinate(50.4556, 30.5143);

     MyGeocodeQuery.QueryCompleted += MyGeocodeQuery_QueryCompleted;
     MyGeocodeQuery.QueryAsync();
 }

 void MyGeocodeQuery_QueryCompleted(object sender, 
          QueryCompletedEventArgs<IList<MapLocation>> e)
{
    if ((e.Error == null)&&(e.Result.Count>0))
    {
        Ellipse myCircle = new Ellipse();
        myCircle.Fill = new SolidColorBrush(Colors.Blue);
        myCircle.Height = 20;
        myCircle.Width = 20;
        myCircle.Opacity = 50;

        MapOverlay myLocationOverlay = new MapOverlay();
        myLocationOverlay.Content = myCircle;
        myLocationOverlay.PositionOrigin = new Point(0.5, 0.5);
        myLocationOverlay.GeoCoordinate =
            e.Result.First().GeoCoordinate;

        MapLayer myLocationLayer = new MapLayer();
        myLocationLayer.Add(myLocationOverlay);

        myMap.Layers.Add(myLocationLayer);
        myMap.SetView(e.Result.First().GeoCoordinate, 14);
    }
}

 

Обратите внимание на то, что QueryAsync не поддерживает возможность использовать подход await/async, а требует создания обработчика.

Используя коллекцию результатов можно предоставить пользователю выбор, а если более детально посмотреть на содержимое e.Result, то можно получить не только координаты, но и район города. Тут используются объекты классов MapLocation и MapAddress.

Если у Вас обратная задача и по GPS координатам необходимо найти адрес, то это также можно легко сделать с помощью класса ReverseGeocodeQuery:

 

ReverseGeocodeQuery MyGeocodeQuery = new ReverseGeocodeQuery();
MyGeocodeQuery.GeoCoordinate = new GeoCoordinate(50.4556, 30.5143);

MyGeocodeQuery.QueryCompleted += MyGeocodeQuery_QueryCompleted;
MyGeocodeQuery.QueryAsync();

 

Тут только один параметр для поиска – координаты места, адрес которого необходимо найти.

Остается еще одна задача, которую можно выполнить с помощью карт Nokia, это прокладка пути. При этом путь можно проложить как для пешехода, так и для автомобиля, получив все данные, которые дают современные GPS системы. Тут используется класс RouteQuery, который содержит три основных свойства:

· RouteOptimization – позволяет задать параметр, определяющий оптимальный для пользователя путь: экономный по расстоянию или по времени;

· TravelMode – позволяет указать, как будет передвигаться пользователь: пешком или на автомобиле;

· Waypoints – содержит коллекцию объектов типа GeoCoordinate, перечисляющую те места, где планирует побывать пользователь (в самом простом случае, это начало и конец пути).

Вот пример кода, который задает основные параметры для объекта класса RouteQuery:

 

private async void OneShotLocation_Click()
{
    RouteQuery query = new RouteQuery();
    query.RouteOptimization = RouteOptimization.MinimizeDistance;
    query.TravelMode = TravelMode.Driving;
    query.Waypoints = new List<GeoCoordinate>()
        {
            new GeoCoordinate(50.46,30.5303),
            new GeoCoordinate(50.4556,30.5143)
        };

    query.QueryCompleted += query_QueryCompleted;
    query.QueryAsync();
}

 

Обработчик события QueryCompleted содержит объект типа Route, который можно тут же добавить на карту:

 

void query_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)
{
    MapRoute MyMapRoute = new MapRoute(e.Result);
    myMap.AddRoute(MyMapRoute);
    myMap.SetView(e.Result.BoundingBox);
}

 

Исследуя объект типа Route, можно получить всю необходимую информацию. Например, коллекция Geometry содержит набор объектов типа GeoCoordinate, из которых строится путь, а свойство Legs позволяет получить время пути, расстояние и список мест, где необходимо выполнить изменение пути (инструкций). Все это можно использовать для построения системы любой сложности.

Расширение возможностей с помощью Windows Phone toolkit

Если Вы используете в своем приложении Windows Phone Toolkit, который можно найти по адресу http://phone.codeplex.com/, то можете немного расширить возможности существующего API для карт дополнительными методами и классами.

Как Вы заметили, все асинхронные методы стандартного API требуют создания обработчика события. Windows Phone Toolkit расширяет эти существующие методы аналогами, работающими через async/await. Так, метод GetRouteAsync расширяет класс RouteQuery, а методом GetMapLocationsAsync расширяются классы GeocodeQuery и ReverseGeocodeQuery. Так, предыдущий пример будет выглядеть следующим образом:

 

private async void OneShotLocation_Click()
{
    RouteQuery query = new RouteQuery();
    query.RouteOptimization = RouteOptimization.MinimizeDistance;
    query.TravelMode = TravelMode.Driving;
    query.Waypoints = new List<GeoCoordinate>()
        {
            new GeoCoordinate(50.46,30.5303),
            new GeoCoordinate(50.4556,30.5143)
        };

    query.QueryCompleted += query_QueryCompleted;
    Route r=await query.GetRouteAsync();

    MapRoute MyMapRoute = new MapRoute(r);
    myMap.AddRoute(MyMapRoute);
    myMap.SetView(r.BoundingBox);
}

 

Кроме асинхронных методов, Windows Phone Toolkit расширяет возможности класса Map. Во-первых, тут появляется класс Pushpin, который был в Bing Maps SDK и представляет собой готовую метку для карт. Данные метки можно установить с помощью расширения Children, задающего коллекцию элементов на карте. Во-вторых, тут появился MapItemsControl, который также добавляется в коллекцию Children, но при этом сам является источником для коллекции данных, позволяя реализовать механизм связывания карты и данных.

Ниже пример инициализации коллекции Children и добавления в нее элемента PushPin:

 

ObservableCollection<DependencyObject> children = 
MapExtensions.GetChildren(myMap);

children.Add(new Pushpin() 
{ 
GeoCoordinate = new GeoCoordinate(50.46, 30.5303) 
});

 

А вот этот пример показывает, как можно определить связывание карты и данных в XAML:

 

<maps:Map x:Name="Map" Grid.Row="1" Hold="OnMapHold">
    <maptk:MapExtensions.Children>
        <maptk:Pushpin x:Name="RouteDirectionsPushPin"           
                       Visibility="Collapsed"/>
        <maptk:MapItemsControl Name="StoresMapItemsControl">
            <maptk:MapItemsControl.ItemTemplate>
                <DataTemplate>
                    <maptk:Pushpin GeoCoordinate="{Binding GeoCoordinate}" 
                                   Visibility="{Binding Visibility}" 
                                   Content="{Binding Address}"/>
                </DataTemplate>
            </maptk:MapItemsControl.ItemTemplate>
        </maptk:MapItemsControl>
        <maptk:UserLocationMarker x:Name="UserLocationMarker" 
                                  Visibility="Collapsed"/>
    </maptk:MapExtensions.Children>
</maps:Map>

 

Тут также используется класс UserLocationMarker, который аналогичен Pushpin, но аналогичен большинству элементов, показывающих текущую позицию.

Как видите, если у Вас используется связывание с данными, то Toolkit очень полезен. Более того, его можно использовать для миграции Ваших приложений с WP 7 на WP 8.

Written by Sergiy Baydachnyy

16.12.2012 at 11:18

Опубликовано в Windows Phone

Tagged with

Использование карт (часть 1)

leave a comment »

 

Итак, разобравшись с определением местоположения, переходим к картам. Для многих разработчиков карты являются больной темой, так как во многих приложениях они являются желательным компонентом, но в Windows Phone 7 с ними было ряд существенных проблем. Во-первых, карты были исключительно в онлайн, что не позволяло строить приложения, подключающиеся к сети только тогда, когда это возможно сделать по Wi-Fi. Во-вторых, для прорисовки карт использовалась служба Bing Maps, которая хорошо работает в США и некоторых странах, но часто бесполезна для украинского пользователя. Все это сводило на нет реализацию многих сценариев по работе с картами.

В Windows Phone 8 ситуация с картами коренным образом изменилась. Карты теперь доступны в офлайн режиме, давай пользователю возможность загрузить карты для выбранных стран один раз, находясь в зоне подключения к Wi-Fi. Кроме того, все модели телефонов будут использовать карты от Nokia. А ведь именно Nokia является одним из крупнейших провайдеров картографической информации. Тут покупают данные и Microsoft для Bing и другие крупные компании. А если Вы пользовались навигатором на Nokia устройствах, то знаете, что карты содержат актуальные данные даже для Украины (где на картах заработать сложно). При этом пользователь не только может установить нужные карты, но и получать их обновления на регулярной основе. Если говорить о Bing Maps, то использование этих карт считается устаревшим подходом, хотя сам элемент еще и остался для совместимости.

Итак, давайте рассмотрим, как работают новые карты.

Загрузка карт

Естественно, чтобы использовать карты, пользователь должен иметь возможность загрузить их. Для этого есть два варианта, это использовать приложение Карты, где можно загрузить карты через настройки. Либо предоставить возможность загрузки карт прямо из приложения. Тут существует два готовых класса, это MapDownloaderTask и MapUpdaterTask. Оба класса позволяют запустить одну из задач в операционной системе Windows Phone 8. В первом случае, это приложение, позволяющее выбрать карты для загрузки, а во втором – другая часть того же приложения, позволяющая проверить наличие обновлений установленных карт и загрузить свежие. Оба класса находятся в пространстве имен Microsoft.Phone.Tasks и использование их довольно примитивно:

 

MapDownloaderTask mapDownloaderTask = new MapDownloaderTask();
mapDownloaderTask.Show();

 

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

Построение маршрута

Если говорить о встроенных возможностях, то тут приложениям доступно еще две задачи, представленными классами MapsTask и MapsDirectionsTasks. Первый класс позволяет запустить приложение Карты из Вашего приложения, а второй – запустить приложение Карты и построить маршрут между двумя заданными пунктами. Посмотрим на эти классы более детально.

Объект класса MapsTask имеет три свойства и может не просто отобразить карту, но и установить уровень приближения, центр карты или выполнить поиск по заданным критериям. Свойства имеют названия ZoomLevel, Center и SearchTerm соответственно. Рассмотрим вот такой код:

 

MapsTask map = new MapsTask();
map.SearchTerm = "Kyiv Zhylianskaya 75";
map.Show();

 

Чтобы заставить данный код работать в эмуляторе, необходимо загрузить карту Украины и Вы получите положение офиса Майкрософт в Киеве:

image

Использование класса MapsDirectionsTask аналогично. У него правда всего два свойства, это Start и End, которые определяют между какими точками нужно прокладывать маршрут. Если свойство Start не задано, то за начало пути будет браться текущее местоположение. Оба свойства имеют тип LabeledMapLocation, конструктор которого принимает заголовок местоположения и GPS координаты. Если координаты не заданы, то заголовок будет использоваться как текст для поиска позиции.

Вот этот кусочек кода позволяет построить путь для проезда в украинский офис Майкрософт:

 

MapsDirectionsTask map = new MapsDirectionsTask();
map.End = new LabeledMapLocation("Kyiv Zhylianskay 75", null);
map.Show();

 

Чтобы он работал в эмуляторе, нужно установить Ваше текущее положение на вкладке Location, а то путь будет строится от значения по умолчанию, а из Редмонда тяжело доехать в Киеве на машине, о чем приложение и сообщитJ

Вот как будет выглядеть экран с построенным маршрутом:

image

Использование элемента управления Map

Перейдем теперь к использованию карт непосредственно в приложении. Тут основным компонентом является класс Map, который можно разместить в виде элемента в XAML файле или добавить на страницу динамически. Правда, чтобы приступить к работе с классом Map, необходимо задекларировать соответствующую возможность в манифесте с помощью элемента с именем ID_CAP_MAP:

 

<Capabilities>
 <Capability Name="ID_CAP_NETWORKING" />
 <Capability Name="ID_CAP_LOCATION" />
 <Capability Name="ID_CAP_MAP" />
</Capabilities>

 

Подобную декларацию можно установить и в графическом редакторе манифеста.

Чтобы добавить карту на страницу приложения в XAML рекомендую воспользоваться панелью инструментов и просто перетащить элемент Map в нужное место. Тогда декларация необходимого пространства имен происходит автоматически. В любом случае, класс Map объявлен в пространстве имен и сборке, которые не декларируются по умолчанию, поэтому среди атрибутов страницы (элемент PhoneApplicationPage) должна появится следующая запись:

xmlns:Controls=
"clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"

 

Ну а сам элемент выглядит достаточно просто:

<Controls:Map Name="myMap" />
 

И чудо, карта работает. Никаких регистраций на внешних сайтах, никаких ключей и условий по количеству транзакций. Ведь все карты расположены локально у пользователя и речь не идет о продаже какой-то услуги, как это было с Bing Maps.

Естественно, тут не все так просто. Сборка Microsoft.Phone.Maps.dll содержит три пространства имен с большим количеством классов.

Первое пространство имен Microsoft.Phone.Maps включает всего два класса. Эти классы содержат внутреннюю информацию для картографической службы (когда идет к ней обращение), включая ID приложения и данные аутентификации. Видимо, данный механизм используется, чтобы убедиться, что карты отдаются «по адресу», то есть только пользователи Windows Phone получат эту уникальную возможность. Нам эти классы не пригодятся, в отличие от всех остальных.

Оставшийся набор классов был разделен на два пространства имен, это Microsoft.Phone.Maps.Controls и Microsoft.Phone.Maps.Services. В первом находятся все классы, которые связаны с построением самого элемента (карты) и его составляющих (дополнительных объектов). А во втором – утилитные классы, которые позволяют выполнить запросы для построения маршрутов, поиска данных по координатам и др. Мы рассмотрим большинством из них, но сначала закончим работать с классом Map.

Рассмотрим основные свойства, которые можно устанавливать у объекта типа Map. Тут можно выделить следующие:

· Center – позволяет отцентрировать карту по заданной позиции GPS. Свойство имеет тип System.Device.Location.GeoCoordinate, конструктор которого принимает в качестве параметров долготу и широту. Если разработчик хочет задать центр внутри XAML, то тут существует автоматический конвертер GeoCoordinateConverter, который позволяет записать долготу и широту в виде строки текста из двух значений, разделенных запятой;

· ZoomLevel – это свойство позволяет установить уровень приближения карты. По умолчанию значение равно 1 и позволяет показать на экране телефона всю карту. Максимальное значение равно 20;

· CartographicMode – карты от Nokia поддерживают четыре режима отображения, которые содержатся в перечислимом типе MapCartographicMode. Естественно, что разработчик может установить любой из них и предоставить пользователю переключать режимы в процессе работы. Вот список этих режимов: Road, Aerial, Hybrid и Terrain. Первый режим позволяет отобразить только графическую схему дорог и домов, во втором случае пользователь получает спутниковый снимок, а в третьем и четвертом случае можно увидеть дороги, наложенные на спутниковую карту или только на рельеф местности;

· ColorMode – если Вы пользовались GPS навигаторами, то знаете, что многие из них в ночное время могут автоматически или по запросу переходить в ночной режим, применяя отличную от дневного цветовую гамму. Подобная функциональность есть и у карт Nokia. Так свойство ColorMode способно принимать одно из двух значений перечислимого типа MapColorMode, это Dark и Light. Догадайтесь сами, какое значение отвечает за какой из режимовJ

· LandmarksEnabled – свойство позволяет включить отображение ориентиров, которые становятся видны при приближении 16 или больше. Самое удивительное, что включив ориентиры и просматривая карту Днепропетровска я нашел их аж две штуки, это Главпочтамт и Национальный горный университет. Это уже радует, хотя я ожидал увидеть хотя бы один памятник Владимиру Ильичу, но увы;

image

· PedestrianFeaturesEnabled – это свойство позволяет указать, нужно ли отображать специальные обозначения для пешеходов. Тут могут быть лестницы, переходы, пешеходные мостики и др. На самом деле я смог найти только немного обозначений для Киеве, а для моего любимого Днепропетровска таких обозначений не было. Может быть не очень и нужны, так как сложных развязок в «четыре этажа» у нас нет, а пешеход в основном ходит по землеJ Обозначения отображаются только при приближении карты 16 и больше.

· Pitch – данное свойство позволяет задать наклон карты в градусах (изображение выше с наклоном), придав карте эффект объемности;

· Heading – это свойство задает поворот карты в градусах вокруг центра, позволяя разработчику реагировать на смену ориентации устройства и выводить карту в наиболее удобном режиме.

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

 

private async void OneShotLocation_Click()
{
    //переменную следует выбрать откуда-то из хранилища настроек пользователя
    //и установить в реальное значение
    bool isAllow=true;

    Geolocator geolocator = new Geolocator();

    if (geolocator.LocationStatus == PositionStatus.Disabled)
    {
        if (MessageBox.Show(
            "Определение позиции заблокировано. Перейти к настройкам телефона?",
            "Ошибка настроек", MessageBoxButton.OKCancel)==MessageBoxResult.OK)
        {
            await Launcher.LaunchUriAsync(new Uri("ms-settings-location:"));
        }
        return;
    }

    geolocator.DesiredAccuracyInMeters = 50;

    if (!isAllow)
    {
        if (MessageBox.Show(
            "Разрешить определение позиции устройства для приложения?",
            "Настройки", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
        {
            //сохранить выбранное значение для дальнейшего использования
            //чтобы в следующий раз им заполнять isAllow
        }
        else
        {
            return;
        }
    }

    try
    {
        Geoposition geoposition = await geolocator.GetGeopositionAsync(
            TimeSpan.FromMinutes(5),
            TimeSpan.FromSeconds(10)
            );
                
        myMap.LandmarksEnabled = true;
        myMap.SetView(ConvertGeocoordinate(geoposition.Coordinate), 
16, 0, 45, MapAnimationKind.Parabolic);

        Ellipse myCircle = new Ellipse();
        myCircle.Fill = new SolidColorBrush(Colors.Blue);
        myCircle.Height = 20;
        myCircle.Width = 20;
        myCircle.Opacity = 50;

        MapOverlay myLocationOverlay = new MapOverlay();
        myLocationOverlay.Content = myCircle;
        myLocationOverlay.PositionOrigin = new Point(0.5, 0.5);
        myLocationOverlay.GeoCoordinate = 
            ConvertGeocoordinate(geoposition.Coordinate);

        MapLayer myLocationLayer = new MapLayer();
        myLocationLayer.Add(myLocationOverlay);

        myMap.Layers.Add(myLocationLayer);
    }
    catch (Exception ex)
    {
        MessageBox.Show("Что-то случилось странное!");
    }
}

public GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate)
{
    return new GeoCoordinate
        (
        geocoordinate.Latitude,
        geocoordinate.Longitude,
        geocoordinate.Altitude ?? Double.NaN,
        geocoordinate.Accuracy,
        geocoordinate.AltitudeAccuracy ?? Double.NaN,
        geocoordinate.Speed ?? Double.NaN,
        geocoordinate.Heading ?? Double.NaN
        );
}  

 

Несмотря на большой объем, код тут достаточно простой. Как и раньше, мы определили позицию устройства и получили объект типа Geoposition, который содержит полученную позицию внутри свойства Coordinate типа Geocoordinate. Тут проблема в том, что карты работают с более сложным объектом типа GeoCoordinate. Несмотря на схожее название (разница в одну букву), GeoCoordinate содержит больше информации, поэтому нам нужно написать специальный метод, который будет выполнять преобразование из одного типа в другой. Этот метод находится в самом конце и называется ConvertGeocoordinate.

Далее, чтобы добавить на карту любой UIElement (в нашем случае голубой кружок), необходимо его завернуть в объект типа MapOverlay, привязав последний к конкретным координатам и указав положение содержимого относительно заданной позиции (выбрав (0.5, 0.5) мы контент располагаем строго по центру.

Из объектов типа MapOverlay мы формируем слой карты, который накладываем на исходную карту. Слой карты описывается классом MapLayer и позволяет хранить любое количество объектов типа MapOverlay. Созданный слой мы добавляем в коллекцию Layers нашей карты. Ну и чтобы красиво переместить карту в нужную позицию, мы использовали метод SetView, о котором писали выше.

Written by Sergiy Baydachnyy

13.12.2012 at 20:12

Опубликовано в Windows Phone

Tagged with

Marmalade для Windows Phone 8

leave a comment »

Сегодня был сделан анонс доступности одного из популярных фреймворков для разработки игр Marmalade для Windows Phone 8. Ранняя бета стала доступна для владельцев пакетов Marmalade Professional и Marmalade Plus.

Учитывая то, что сегодня большинство игр разрабатывается с помощью фреймворков сразу на все платформы, и Marmalade один из популярных фремворков – ожидаем большое количество новых игр для платформы Windows Phone 8.

Осталось дождаться анонса для Windows 8. Но учитывая однотипность платформ (особенно для игр), ждать осталось совсем немного.

Анонс можно найти тут: http://www.madewithmarmalade.com/windows-phone-8

Written by Sergiy Baydachnyy

13.12.2012 at 17:53

Опубликовано в Windows Phone

Tagged with