Там, где я живу, я могу практиковаться в знании испанского, читая вывески и надписи на двух языках, которые есть во многих общественных местах. Загвоздка в том, что иногда я спотыкаюсь на каком-то слове и не могу понять его из контекста, а иногда от меня ускользает общий смысл всей фразы. Кроме того, без параллельного перевода на английский я не всегда уверен в том, что правильно понял написанное. Я мог бы таскать с собой испано-английский словарь, но постоянно пролистывать его в поисках нужных слов — это как-то совсем уж несовременно.
На самом деле я хотел бы иметь простой способ перевода слов на телефоне — ведь он всегда со мной. Подключение к сервису Bing с помощью телефона и использование Microsoft Translator, размещенного в облаке, — штука полезная, но, чтобы добраться до экрана перевода, нужно нажимать слишком много клавиш. Если б только был способ — простой способ — каким-либо образом разместить переводчик в моем телефоне. Что ж, с появлением Windows Phone 7 это стало возможным.
Эта статья является введением в разработку приложений Windows Phone и показывает, как связывать такие приложения с каким-либо веб-сервисом в облаке. Вы должны быть более-менее знакомы с C# и Visual Studio, и будет очень полезно, если у вас есть хотя бы минимальный опыт создания приложения с применением XAML (Extensible Application Markup Language), но это не обязательное требование. Я использовал апрельское обновление CTP-версии инструментария Windows Phone. К тому моменту, когда вы будете читать эту статью, некоторые вещи могут измениться, поэтому зайдите на developer.windowsphone.com.
Начнем с начала: получение AppID
Если вы собираетесь взаимодействовать с Translator или любым другим веб-сервисом Bing, вашим первым шагом должно стать получение AppID. Он используется API сервиса для проверки того, что запрос исходит от зарегистрированного в Bing разработчика приложений.
Отправляйтесь на bing.com/developers/createapp.aspx и зарегистрируйтесь там под своим идентификатором Windows Live ID.Затем заполните форму, в которой запрашивается название и описание вашего приложения, название вашей компании и адрес электронной почты. По этому адресу вас будут уведомлять об изменениях в API, например при развертывания новых версий или удалении старых версий. В частности, применительно к Translator API на момент написания этой статьи в документации было сказано, что старые версии будут оставаться в онлайновом режиме в течение 90 дней после выпуска новой версии.
Далее прочтите условия использования, пометьте флажок, подтверждающий, что вы принимаете эти условия, щелкните кнопку Accept, и вы будете перенаправлены на страницу с вашим новым AppID. Вы всегда сможете вернуться на эту страницу, если что-то забудете, но я обычно копирую ее содержимое и вставляю свой AppID в файл исходного кода приложения сразу после создания этого файла.
Всегда внимательно читайте условия использования любого веб-сервиса, который вы планируете применять в приложении. Серьезно, не поддавайтесь искушению пролистать его не читая, особенно если вы собираетесь распространять свое приложение через Marketplace. Вы обязаны ради своих пользователей понимать цели и другие условия уровня сервисов, определяемые партнерами, которые предоставляют эти сервисы вашему приложению. Так что обязательно прочитайте и вникните в эти условия, в частности, чтобы понять, кем предоставляется конкретный сервис — Microsoft или третьей стороной.
Теперь, когда у вас есть AppID, вы готовы приступить к работе над мобильным приложением-переводчиком.
Определение целевой аудитории приложения
Прежде чем начать работу над своим первым приложением, я посмотрел на некоторые мобильные приложения, пользующиеся успехом на рынке. Я смотрел на приложения для телефонов под управлением Windows Phone и других смартфонов, пытаясь прочувствовать, что делает мобильное приложение по-настоящему успешным. Я читал обзоры продуктов. Я опрашивал людей. Я замучил своих друзей просьбами дать мне возможность поиграть с их телефонами.
В результате такого исследования я пришел к выводу, что ключевое качество успешного мобильного приложения — его простота. Каждое популярное приложение удовлетворяет одной или двум ключевым потребностям пользователей и делает это очень хорошо. Например, я обнаружил целый класс приложений, единственной целью которых является генерация неприличных звуков. На практике они, по сути, представляют собой программную реализацию известной подушки для розыгрышей, которую подкладывают на сиденья. Люди находят такие приложения забавными — по крайней мере, они платят деньги за их загрузку в свои телефоны.
Аналогично существуют приложения, которые имитируют игру в кости, рекомендуют ресторан для обеда и даже подсчитывают его примерную стоимость. Все они рассчитаны на определенные аудитории пользователей, а также просты и интуитивны понятны. Этот подход не уникален для какого-то одного бренда смартфонов. Идея насчет того, что мы должны создавать тщательно «отполированный» и интуитивно понятный UI, нашла свое новое воплощение в руководстве «Windows Phone UI Design and Interaction Guide», опубликованном по ссылке developer.windowsphone.com/windows-phone-7.
Поэтому, когда я начал работать над приложением-переводчиком, мне было крайне важно сосредоточиться именно на том, что должно делать это приложение, и не добавлять в него ничего лишнего. Для этого я сначала составил четкую картину того, что мне нужно. И лишь тогда я мог бы сопротивляться соблазну добавить в него парочку-другую новых классных функций, которые, хоть и интересны, но не имеют никакого отношения к главной цели приложения. Я решил, что мое приложение должно обеспечивать перевод между двумя языками:английским и испанским. Нужно было сделать так, чтобы было легко переключать режимы перевода «с испанского на английский» и «с английского на испанский» и чтобы это приложение манипулировало только отдельными словами или простыми фразами. Более того, меня интересовали лишь два языка — испанский и английский, поэтому остальные языки мое приложение должно было игнорировать.
Создание приложения
Для начала откройте Visual Studio Express 2010 for Windows Phone. Выберите «New project...» и укажите «Windows Phone Application». Это приведет к созданию проекта Windows Phone по умолчанию с экраном, поделенным на две секции: Title и Content. Эти секции описываются XAML-объектом Grid, который позволяет определять серии строк и столбцов, где мы можем размещать дочерние UI-элементы вроде Button и TextBlock (рис. 1).
Рис. 1. Проект Windows Phone по умолчанию с представлениями кода и экрана
Во-первых, отредактируйте название приложения и заголовок страницы, выбрав эти UI-элементы в дизайнере. Это приведет к подсветке связанного с ними XAML-кода в окне представления исходного кода в дизайнере, показывающем, какой элемент вам нужно отредактировать. Далее откройте окно инструментария (toolbox) и перетащите кое-какие UI-элементы к нижней части сетки на странице, которая называется ContentGrid. Выберите TextBox, в который вы будете помещать слова для перевода, затем TextBlock, где будет показываться перевод. Наконец, добавьте две кнопки (рис. 2).
Рис. 2. Добавление элементов управления TextBox, TextBlock и Button UI
Одна из кнопок будет запускать перевод, а другая будет переключать направление перевода — с испанского на английский или наоборот.
XAML: современный UI
В Windows Phone 7 имеется система проектирования UI под кодовым названием Metro. А центральную роль в реализации UI, спроектированного согласно системе Metro, играет XAML. Если вы уже имели дело с Silverlight или Windows Presentation Foundation (WPF), то, вероятно, XAML уже знаком вам. А если вы не работали с ними, этот раздел послужит кратким введением.
XAML — это способ декларативного структурирования вашего UI, который обеспечивает строгое разделение между логикой приложения и его внешним видом. Вы заметите, что код, например, для основной страницы приложения содержится в Mainpage.xaml.cs, а базовая раскладка UI — в Mainpage.xaml. В отличие от традиционной разработки на основе Windows Forms здесь нет смешения кода приложения с раскладкой его UI. Каждый UI-элемент приложения моделируется как XML-элемент в XAML-файле.
Это большое преимущество, так как два разработчика могут независимо работать над внешним видом приложения и его логикой. Например, теперь, когда мы очертили базовый UI приложения-переводчика, мы могли бы отдать написание XAML эксперту по UI, а сами продолжили бы работу над кодом. Дизайнеру не нужно знать о реализации моего приложения, а мне не требуется ничего знать о цветовой палитре, которую выберет дизайнер.
Конечно, у меня нет бюджета, чтобы нанять дизайнера UI, зато есть MSPaint, и этого достаточно, чтобы продемонстрировать, насколько легко изменять графическое оформление приложения.
Смена значка для программы-переводчика
Я дважды щелкаю файл ApplicationIcon.png, который по умолчанию автоматически добавляется в проект при его создании. Это приводит к открытию графического редактора, каковым на моем компьютере для разработки является MSPaint. Я заменяю значок с надоевшей шестеренкой на значок с заглавной буквой T. Затем заменяю черный фон на монотонный розовый. Вероятно, я не получу приза за дизайн графики, но мне такой значок нравится (рис. 3).
Рис. 3. Значок нового проекта, созданного с помощью MSPaint
Чтобы увидеть изменения, я нажал кнопку запуска для развертывания приложения в эмуляторе Windows Phone 7. Если вы работали с предыдущими версиями эмуляторов Windows Phone, то сразу же заметите, насколько эта версия стала удобнее в использовании. Работа с эмулятором для Windows Phone 6.5 могла быть весьма утомительной и часто требовала множества операций конфигурирования для запуска и подключения отладчика к эмулятору. Но в среде разработки для Windows Phone 7 все работает без какой-либо специфической настройки — достаточно нажать зеленую кнопку запуска. Заодно меня приятно удивила значительно возросшая скорость загрузки и отображения основного UI приложения (рис. 4).
Рис. 4. Приложение, отображенное с помощью эмулятора Windows Phone 7
Чтобы посмотреть на значок, я вышел из основного UI и перешел в основной экран эмулятора. Графика программы-переводчика отображается там и выглядит вполне прилично (рис. 5).
Рис. 5. Проверка значка нового приложения в эмуляторе
Манифест приложения
Значок приложения определяется в файле WMAppManifest.xml, который находится в папке Properties вашего проекта. Чтобы переименовать значок приложения, измените имя файла ApplicationIcon.png в своем проекте, а потом не забудьте отразить это изменение здесь, в элементе IconPath:
<IconPath IsRelative="true"
IsResource="false">myicon.png
</IconPath>
Если ваше приложение не может найти свой значок, то в период выполнения ему будет присвоен значок по умолчанию, который выглядит примерно как белый кружок на черном фоне.
Другой элемент в этом файле, который заслуживает проверки, — Capabilities; он определяет специфические возможности, которые хочет использовать ваше приложение. Лучше всего запрашивать ровно то, что нужно вашему приложению, — и ни каплей больше. Просмотрев файл, вы заметите, что поддерживается целый ряд возможностей, которые мы не собираемся использовать в программе-переводчике.
Например, ID_CAP_GAMERSERVICES объявляет, что вашему приложению нужно взаимодействовать с игровым API в XBox. ID_CAP_LOCATION означает, что приложению требуется задействовать возможность определения местонахождения устройства, а ID_CAP_PUSH_NOTIFICATION — что необходимо взаимодействие с механизмом отсылки уведомлений в Windows Phone 7. Все это отличные функции, но нам они не нужны. Фактически нам может понадобиться только ID_CAP_NETWORKING — возможность приема и передачи данных по сети.
Microsoft Translator API
Microsoft Translator предоставляет три вида API: SOAP (обеспечивает строгую типизацию и простоту использования), AJAX (полезен в основном разработчикам веб-страниц, желающим встроить в свои UI средства перевода) и HTTP (полезен в тех случаях, когда не годятся ни SOAP, ни AJAX API).
Мы задействуем интерфейс SOAP, потому что с ним легче всего работать применительно к нашим целям. Переключитесь в Solution Explorer и щелкните правой кнопкой мыши References. Затем выберите Add a Service Reference и укажите конечную точку для интерфейса SOAP в Translator API: http://api.microsofttranslator.com/V2/Soap.svc. Присвойте конечной точке сервиса имя TranslatorService в текстовом поле Namespace и щелкните OK (см. рис. 6).
Рис. 6. Добавление ссылки на службу SOAP
Об остальном позаботится Visual Studio, самостоятельно сгенерировав клиентский код для интерфейса SOAP.
Теперь добавьте код в приложение. Вставьте AppID и ссылку на клиент TranslatorService в объявление класса MainPage вашего приложения:
string appID = <<your appID>>;
TranslationService.LanguageServiceClient client =
new TranslationService.LanguageServiceClient();
IntelliSense показывает нам, что у сервиса перевода есть ряд интересных методов. Первое, на что стоит обратить внимание, — все методы асинхронные. Это имеет смысл, поскольку веских причин блокировать клиентское приложение на время выполнения сетевой операции нет. А значит, вам понадобиться зарегистрировать делегат для каждой конкретной операции. В данном случае нас интересуют лишь метод TranslateAsync и событие TranslateAsyncComplete, предоставляемые LanguageServiceClient. Но остальные методы определенно следует хотя бы просто обсудить.
Два метода стоят особняком:GetLanguagesForTranslateAsync и GetLanguageNamesAsync. Первый метод возвращает список языковых кодов, поддерживаемых сервисом Translator. Вызвав этот метод, вы можете увидеть, что языковый код для испанского — «es». Метод GetLanguageNamesAsync возвращает список названий языков для данного набора языковых кодов, локализованных для данного региона (локализующего идентификатора) (locale). Например, если вы передаете «es» в этот метод как локализующий идентификатор и языковой код, то получаете строку «Español». Это пригодилось бы нам, если бы мы создавать многоязыковой переводчик.
Другой интересный метод — SpeakAsync. Он принимает строку и локализующий идентификатор, а возвращает URL на WAV-файл, благодаря которому вы можете услышать произношение этого слова носителем языка. Это потрясающая функция. Например, я мог бы ввести строку, получить перевод, затем передать эту строку в метод SpeakAsync, получить WAV-файл и таким способом общаться с другими на испанском. Или, если бы я не был уверен в произношении конкретного слова, я мог бы использовать метод SpeakAsync, чтобы послушать, как произносится это слово.
Все это настолько замечательно, что очень трудно не поддаться соблазну напихать эти функции в приложение просто потому, что они такие классные. Однако на этот раз мы проявим твердость и сосредоточимся исключительно на той задаче, которая была поставлена в начале. Имя четкое представление о том, что должно получиться в итоге, гораздо легче сопротивляться искушению добавить «ну хотя бы еще одну функцию». Уверен, что рано или поздно все дело кончится тем, что я затолкаю в программу все функции, предлагаемые Translator API, но точно не сейчас.
Подключение кода, образующего само приложение-переводчик, осуществляется весьма легко. Сначала мы регистрируем делегаты для события TranslateCompleted:
client.TranslateCompleted += new
EventHandler<TranslationService.TranslateCompletedEventArgs>
(client_TranslateCompleted);
Затем реализуем обработчик события TranslateCompleted, который записывает в TextBlock переведенный текст:
void client_TranslateCompleted(object sender,
TranslationService.TranslateCompletedEventArgs e)
{
TranslatedTextBlock.Text = e.Result;
}
We wire up the button to submit the text we’ve entered for translation:
private void TranslateButton_Click(object sender,
RoutedEventArgs e)
{
client.TranslateAsync(appID, TranslateTextBox.Text, fromLanguage,
toLanguage);
}
Затем мы добавляем немного простого кода для второй кнопки, которая переключает режимы перевода с «Spanish to English» на «English to Spanish» и наоборот. Эта кнопка управляет переменной глобального состояния и изменяет надпись на кнопке перевода, сообщая тем самым о текущем режиме.
Наконец, мы развертываем приложение в эмуляторе для тестирования. Теперь у нас есть полностью работающее приложение-переводчик, потребовавшее написать десяток-другой строк кода и чуть больше часа времени.
Расширение программы-переводчика
Простая программа-переводчик — это хорошо, но мы могли бы развить ее, расширив сферу ее применения. Было бы замечательно связать побольше языков из числа поддерживаемых Translator API, не нарушая принципов проектирования, изложенных в руководстве по Metro. И было бы еще лучше, если бы нам удалось избавиться от кнопки, управляющей направлением перевода, заменив ее на нечто более простое и интуитивно понятное. Что бы мы ни делали, это должно быть дружественным к человеку, который будет тыкать пальцами в экран своего устройства, и при этом у него должно быть ощущения, что программа подтормаживает или что она не слишком понятна в управлении.
Так что же делать? Мы создадим приложение, использующее проект списка по умолчанию. Откройте новый проект и выберите Windows Phone List Application. В итоге мы получаем экран по умолчанию с элементом управления ListBox в ContentGrid. Этот ListBox будет содержать список из шести языков, на которые мы хотим переводить свой текст, и этот список заменит содержимое, предлагаемое по умолчанию (рис. 7).
Рис. 7. Приложение списка Windows Phone по умолчанию
Мы отредактируем файл MainViewModelSampleData.xaml, который находится в папке SampleData нашего проекта. Вы увидите в нем, в частности, XML, который выглядит так:
<local:ItemViewModel LineOne="design one" LineTwo="Maecenas praesent accumsan bibendum" LineThree="Maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus habitant inceptos interdum lobortis nascetur"/>
Редактируя этот XML, мы может изменить представление ListBox на этапе разработки, чтобы включить в него все нужные нам языки: испанский, немецкий, английский, португальский, итальянский и французский. Заметьте, что после сохранения этого файла представление этапа разработки отразит внесенные изменения. Так происходит потому, что элемент управления ListBox связан через механизм привязки данных с элементом Items, определенным в MainViewModelSampleData.xaml. Контроль обеспечивается атрибутом ItemsSource, которым помечен элемент управления ListBox.
Кроме того, вы можете обновлять содержимое ListBox в период выполнения. Если вы заглянете в файл, сгенерированный Visual Studio, то увидите ObservableCollection<ItemViewCollection> заполненный подстановочными данными (placeholder data), аналогичными тем, которые содержатся в файле MainViewModelSampleData.xaml. Например, если бы я хотел динамически генерировать список языков в UI на основе языков, возвращаемых методом GetLanguageNamesAsync, я отредактировал бы файл MainViewModel.cs для заполнения набора Items. Но пока я предпочитаю указывать статический список языков и напрямую редактировать набор объектов ItemViewModel. После запуска приложения-списка мы должны увидеть примерно такой UI (рис. 8).
Рис. 8. Пользовательский интерфейс приложения-списка
Когда пользователь касается одной из этих кнопок, он переходит на страницу подробностей, которая в целом выглядит так же, как и UI нашего SimpleTranslator. На этой странице есть TextBox для ввода слова, подлежащих переводу, TextBlock, содержащий переведенный текст, и кнопку для запуска перевода. Однако вместо добавления еще одной кнопки, которая управляет направлением перевода, мы полагаемся на Translator API. Двухсторонний перевод в нашем приложении SimpleTranslator не имеет смысла из-за использования более двух языков, а введение дополнительных уровней UI уже создало бы впечатление некоторой громоздкости. К счастью, Translator API позволяет автоматически распознавать язык.
Мы добавим код в первый вызов метода DetectAsync клиентской программы-переводчика, чтобы передавать текст для перевода, а затем будем вызывать TranslateAsync из обработчика события DetectAsyncComplete. Этот обработчик теперь выглядит так:
void client_DetectCompleted(object sender,
TranslationService.DetectCompletedEventArgs e)
{
string languageCode = e.Result;
client.TranslateAsync(appID, TranslateTextBox.Text, fromLanguage, tolanguage);
}
Мы знаем язык, на который нужно перевести текст, просто по кнопке, выбранной пользователем. Мы знаем язык, с которого нужно осуществить перевод, так как Translator API автоматически распознает его. Благодаря этому мы в состоянии создать простой многоязыковый переводчик, в котором для перевода достаточно сделать два касания пальцем (не считая набора самого текста).А на кодирование этой программы ушло менее часа.
Простота
Простота — самое главное в разработке для Windows Phone 7. Приложение должно фокусироваться на одной сфере применения и хорошо делать свою работу в этой области. Инструментарий, поставляемый с Windows Phone 7 SDK CTP, не только позволяет создавать такие простые и эффективные приложения, но и облегчает весь процесс их разработки. Мы также убедились, что взаимодействие с облаком не требует особых усилий и что веб-сервис Microsoft Translator можно подключить к приложению Windows Phone, затратив совсем немного времени. За счет применения привычных инструментов вроде Visual Studio и четкого руководства, такого как Metro, Windows Phone и облако удалось сблизить друг с другом, открыв массу новых возможностей и разработчикам, и пользователям.