{31 день с Mango} День 22: Контракт поиска

Это День 22 в серии статей 31 день с Mango (перевод оригинальной серии 31 Days of Mango), и был написан приглашенным автором Мэт Эланд (Matt Eland). Вы можете найти Мэта в твиттере @integerman.
Windows Phone Mango представляет множество фантастических улучшений в операционной системе Windows Phone. Среди этих усовершенствований ряд улучшений в поисковом движке Bing на телефоне. Хотя многие из этих функций, таких как визуальный поиск и построение маршрута от поворота к повороту предназначены для пользователей, Microsoft также представила несколько функций, направленных на возможность разработчикам интегрировать приложения в результы поиска либо через Мгновенные ответы (Instant Answers), способ выделения приложений, имеющих отношение к конкретному поисковому запросу, или с помощью новой функции в Mango под названием Быстрые карточки (Quick Cards).
Быстрые карточки являются элементами, которые появляются в некоторых результатах поисковых запросов, которые позволяют пользователям больше узнать о некоторых продуктах, местах, или фильмах в Bing. На изображении ниже приведен пример результатов поиска, которые включают в себя Быстрые карточки нескольких книг соответствующих пользовательскому поисковому запросу:

Нажимая на один из этих элементов, вы перейдете на соотвествующую этому продукту Быструю карточку,  которая позволяет вам найти более подробную информацию о продукте в централизованном месте как показано на изображении ниже:

Контракт поиска (App Connect) является ещё одной новой функцией в Windows Phone Mango, которая позволяет приложениям быть в списке Быстрых карточек, релевантных к теме приложения. Там пользователь может нажать и запустить приложение и встретиться с опытом запуска приложения, которое может быть специально адаптировано, с учётом того, что пользователь вошёл в него используя Быстрые карточки.
Важно отметить, что в настоящее время Быстрые карточки для продуктов и фильмов поддерживаются только в США, хотя Быстрые карточки для местоположения доступны повсеместно. Несмотря на это ограничение, мы также коснёмся локализации текста в результатах поиска.
Прочтите http://msdn.microsoft.com/en-us/library/hh202957(v=VS.92).aspx#BKMK_AppConnect , чтобы узнать более подробно о списке типов Быстрых карточек, которые поддерживаются.
Как и с Быстрыми карточками, разработчики также могут иметь в своих приложениях сценарии, в которых они запускаются из Мгновенных ответов Bing — это другое усовершенствование поиска Bing  в Mango. Мгновенные ответы Bing позволяют Bing’у отображать определенные приложения, которые он считает высоко релевантными для конкретного поискового запроса.
В этой статье мы будем создавать приложение, которое позволяет быстро найти книгу на сайте онлайн-магазина, воспользовавшись интеграцией поискового расширения Быстрые карточки для книг и журналов и обеспечим индивидуализированное представление приложения, если оно было запущено из Мгновенных ответов Bing.
Настроить приложение, чтобы воспользоваться контрактом поиска сравнительно легко, хотя существует целый ряд шагов, которые вы должны будете выполнить, чтобы все заработало.
Мы начнем с создания нового проекта Windows Phone приложения в Visual Studio, ориентированного на Windows Phone 7.1.

Регистрация расширения поиска

Для того, чтобы Windows Phone знал, что ваше приложение поддерживает контракт поиска, вам нужно добавить запись в файл манифеста о том, что приложение поддерживает расширение для поиска по телефону.
Разверните узел свойств проекта (Properties) и перейдите в WMAppManifest.xml. Это манифест приложения для магазина приложений и определяет всю необходимую информацию о вашем приложении. Вам нужно добавить новый дочерний элемент в элементе App, как показано в нижеприведённом файле:

<Deploymentxmlns=«http://schemas.microsoft.com/windowsphone/2009/deployment«AppPlatformVersion=«7.1«>
<App=«» >
<IconPathIsRelative=«true«IsResource=«false«>ApplicationIcon.jpg</IconPath>
<Capabilities></Capabilities>
<Tasks>
<DefaultTaskName =«_default«NavigationPage=«MainPage.xaml«/>
</Tasks>
<Tokens></Tokens>
<Extensions>
<!— Beta extension, for development and testing only —>
<ExtensionExtensionName=«Products»
ConsumerID=«{5B04B775-356B-4AA0-AAF8-6491FFEA5661}»
TaskID=«_default»
ExtraFile=«Extensions/Extras.xml« />
<!— Production extensions, for submission to Marketplace —>
<ExtensionExtensionName=«Bing_Products_Books_and_Magazines»
ConsumerID=«{5B04B775-356B-4AA0-AAF8-6491FFEA5661}»
TaskID=«_default»
ExtraFile=«Extensions/Extras.xml« />
</Extensions>
</App>
</Deployment>

Важным аспектом является наличие двух элементов расширения. ExtensionName определяет какие Быстрые карточки будут поддерживать интеграцию. Прочтите  http://msdn.microsoft.com/en-us/library/hh202958(v=VS.92) , чтобы ознакомиться с полным списком доступных Быстрых карточек.
Эмулятор (прим. переводчика: речь об эмуляторе из SDK 7.1) обрабатывает контракт поиска несколько иначе, чем окончательная версия Mango, которая работает на телефоне.
В эмуляторе Быстрые карточки для всех продуктов имеют категорию «Products», вместо более конкретного ExtensionName.  То есть, если мы зарегистрировали наше приложение для поддержки книг и журналов с помощью ExtensionName «Bing_Products_Books_and_Magazines» , наше приложение будет поддерживать Быстрые карточки для книг на устройстве, но не на эмуляторе, и если мы зарегистрировали только поддержку категории «Products» , приложение, казалось бы, прекрасно работают в эмуляторе, но не будет работать должным образом на реальных устройствах.
Остальные поля в элементе расширения относительно просты для рассмотрения: ConsumerID определяет расширение поиска как функцию расширения карт и не должен быть изменен. TaskID указывает на задачу, которая должна быть запущена, когда расширение срабатывает. ExtraFile указывает приложению, где искать дополнительные данные, необходимые для поддержки поисковой интеграции и должен указывать на Extensions/Extras.xml или же контракт поиска не будет работать.

Конфигурирование дополнительных данных, необходимых для контракта поиска
Так как наш проект не содержит Extensions/Extras.xml, которые мы указали в двух расширениях зарегистрированных нами, то мы должны их создать. Щелкните правой кнопкой мыши на проекте в обозревателе решений и выберите пункт “Add -> New Folder”, переименуйте папку в “Extensions”, щелкните правой кнопкой мыши на эту папку и выберите пункт “Add -> New Item”. Выберите XML File из списка и назовите его Extras.xml. Путь и имя файла должны быть точным такими, в противном случае расширение поиска не будет функционировать должным образом.

Теперь у вас должен быть файл Extras.xml в папке Extensions. Мы должны добавить элемент ExtrasInfo в  XML файл, который определяет, как приложение ведет себя с расширениями, которые мы зарегистрировали.

<ExtrasInfo>
<AppTitle>
<!— Neutral language application title. —>
<default>Book Helper</default>
<!— Localized titles —>
<es-ES>Libro Helper</es-ES>
<fr-FR>Livre Helper</fr-FR>
<zh-CN></zh-CN>
</AppTitle>
<ConsumerConsumerID=«{5B04B775-356B-4AA0-AAF8-6491FFEA5661}«>
<ExtensionInfo>
<Extensions>
<!— Corresponding product extension for books —>
<ExtensionName>Bing_Products_Books_and_Magazines</ExtensionName>
<!— Beta extension, for all products. —>
<ExtensionName>Products</ExtensionName>
</Extensions>
<CaptionString>
<!— Neutral language caption —>
<default>Search vendors for books and eBooks</default>
<!— Localized captions —>
<es-ES>Bsqueda de libros y libros electrnicos de varios proveedores</es-ES>
<fr-FR>Recherche de livres et eBooks provenant de divers fournisseurs</fr-FR>
<zh-CN></zh-CN>
</CaptionString>
</ExtensionInfo>
</Consumer>
</ExtrasInfo>

Элемент AppTitle и его дочерние элементы сообщают для Windows Phone как называть наше приложение (и предоставляют локализованные строки для разных языков). Элемент по-умолчанию используется, если строка на конкретном языке не может быть найдена и должна представлять собой название приложения на нейтральном языке сборки. Дополнительные элементы могут быть добавлены, их имена должны соответствовать коду языковой культуры для соответствующих локализованных строк. Например, es-ES в этом примере указывает на строку, используемую в испанских языковых настроек.
Элемент Consumer имеет ConsumerID, он соответствует ConsumerID, который мы зарегистрировали в файле WMAppManifest.xml ранее. Внутри этого элемента есть элемент ExtensionInfo, содержащий элемент Extensions, который в свою очередь содержит элементы ExtensionName, которые определяют те расширения мы указываем, что они должны поддерживаться.
Элемент CaptionString определяет сообщение, которое выводится рядом с плиткой расширения поиска и локализуется также как и элемент AppTitle. Пример такого приложения, показывающий работу расширения поиска на рисунке ниже:

Обратите внимание на то, что для этого изображения используется иконка приложения и фон может быть светлым или темным в зависимости от выбранной темы. Следовательно, у иконки приложения не должны быть использована прозрачность при наличии интеграции приложения с помощью контракта поиска. Кроме того, список элементов для контракта поиска в Быстрых карточках а эмуляторе называется «extras», а в реальных устройствах Mango этот список называется «apps» (примечание переводчика: речь об эмуляторе из SDK 7.1).
Если вам необходимо указать различные заголовки для различных видов продукции, вы можете сделать это путем объявления несколько элементов ExtensionInfo и использования некоторых элементов ExtensionName в одном элементе ExtensionInfo, а других в других, пока все ExtensionNames которые должны поддерживаться и которые вы сообщаете приложению не будут представлены в ExtensionInfo.

Настройка перенаправления URI
Когда пользователь входит в приложение, с помощью контракта поиска, приложение будет пытаться перейти к URI «/SearchExtras». В целях поддержки этой отправной точки, мы должны установить перенаправлени URI для перенаправления на соответствующую страницу. Для этого мы определим ресурс UriMapper в коллекции ресурсов приложения, перейдя в App.xaml и добавив следующие ресурсы Application.Resources:

<Application.Resources>
<nav:UriMapperx:Key=«UriMapper«xmlns:nav=«clr-namespace:System.Windows.Navigation;assembly=Microsoft.Phone«>
<nav:UriMapper.UriMappings>
<nav:UriMappingUri=«/SearchExtras«MappedUri=«/MainPage.xaml« />
</nav:UriMapper.UriMappings>
</nav:UriMapper>
</Application.Resources>

 

Определения этих ресурсов недостаточно.
Нам нужно указать приложению, чтобы найти и использовать этот UriMapper для разрешения запросов. Мы делаем это, добавив следующий код в конструктор в App.xaml.cs:

// Enable URI mapping for Search Extras deep link URIs
RootFrame.UriMapper = Resources[«UriMapper»] as UriMapper;

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

Использование преимущества интеграции с помощью контракта поиска
На данный момент, если вы запускаете приложение в эмуляторе, и затем переходите к поиску Bing на устройстве, с использованием ключа поиска, вы должны увидеть ваше приложение в списке «extra» сводной таблицы для Быстрой карточки продукта — если вы зарегистрировали ваше приложение, как поддерживающее категорию Products — отображение по видам продуктов не работает на эмуляторе, но будет работать на реальном устройстве (и наоборот — регистрация в качестве поддержки широкой категории продуктов не работает на реальных устройствах).
К сожалению, наше приложение ещё ничего не делает с контрактом поиска. Чтобы исправить это, давайте начнем с создания нашего пользовательского интерфейса. Перейдем в MainPage.xaml и заменим Grid с именем LayoutRoot и все его дочерние элементы следующим кодом:

<Grid Background=»Transparent»>
<Grid.RowDefinitions>
<RowDefinition Height=»Auto» />
<RowDefinition Height=»*» />
</Grid.RowDefinitions>
<StackPanel Margin=»12,17,0,28″>
<TextBlock Text=»BOOK HELPER» Style=»{StaticResource PhoneTextNormalStyle}» />
<TextBlock Text=»Welcome» x:Name=»lblPageTitle» Margin=»9,-7,0,0″ Style=»{StaticResource PhoneTextTitle1Style}» />
</StackPanel>
<ScrollViewer Margin=»12,0,12,0″ Grid.Row=»1″>
<StackPanel>
<TextBlock TextWrapping=»Wrap» x:Name=»lblBookTitle» Visibility=»Collapsed» Style=»{StaticResource PhoneTextLargeStyle}« Text=»Book title goes here» />
<TextBlock TextWrapping=»Wrap» x:Name=»lblNoSearch» Text=»To use this product, use your device’s search functions to look for a book and then select this app from the apps section.» Style=»{StaticResource PhoneTextNormalStyle}» />
<HyperlinkButton HorizontalContentAlignment=»Left» Foreground=»{StaticResource PhoneAccentBrush}« Margin=»{StaticResource PhoneVerticalMargin}« Content=»Search Amazon» Click=»HandleSearchAmazonBooks» />
<HyperlinkButton HorizontalContentAlignment=»Left» Foreground=»{StaticResource PhoneAccentBrush}« Margin=»{StaticResource PhoneVerticalMargin}« Content=»Search Barnes and Noble» Click=»HandleSearchBarnesAndNoble» />
</StackPanel>
</ScrollViewer>
</Grid>

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

Обработка параметров запроса
Очевидно, что мы хотели бы иметь возможность сделать что-то особенное, если мы запустили приложение из Быстрой карточки, используя контракт поиска. К счастью, при входе в страницу с помощью контракта поиска, контекст навигации страницы содержит две строки параметров запроса, которые могут помочь нам определить основную информацию о Быстрой карточке, которая запустила приложение. Аргумент строки запроса ProductName будет содержать название продукта, связанное Быстрой карточкой, которое пользователь только просматривает, и аргумент Category, который будет являться ExtensionName, связаным с Быстрой карточкой.
Важно дождаться загрузки страницы до проверки параметров строки запроса поскольку NavigationContext не будет доступен до завершения загрузки.
Хотя это базовая информация, она все еще полезна для приложений, в которых необходимо предварительно заполнить поля и элементы управления названиями продуктов или для страниц, которые должны быть достаточно гибкими, чтобы работать с несколькими видами продуктов. Имейте в виду, что при отладке в эмуляторе категория всегда будет «Products», но будет иметь правильные значения при работе на реально работающем устройстве.
В нашем примере приложения мы будем иметь страницу, отображающую название продукта на странице, если мы вошли в приложение через контракт поиска, но будем оставлять существующий интерфейс приложения при стандартном запуске. Так как приложение запускается через точку входа и точка входа расширения поиска использует ту же страницу входа для нашей демонстрации, важно проверить существование аргументов строки запросов, прежде чем пытаться их использовать.
Вот измененная MainPage.xaml.cs, которая включает логику для разбора параметров строки запроса и обработки кликов по гиперссылке:

public partial class MainPage : PhoneApplicationPage
{
private string _book;
// Constructor
public MainPage()
{
InitializeComponent();
// We need to wait until loaded before checking NavigationContext
Loaded += HandleLoaded;
}

private void HandleLoaded(object sender, RoutedEventArgs e)
{
// Determine what the context of the app launch is
if (NavigationContext.QueryString.ContainsKey(«ProductName»))
{
_book = NavigationContext.QueryString[«ProductName»];
lblPageTitle.Text = «Book Details»;
}
else
{
_book = null;
}

// In a «real» application we’d want to use binding and converters
if (!string.IsNullOrWhiteSpace(_book))
{
lblBookTitle.Text = _book;
lblNoSearch.Visibility = Visibility.Collapsed;
lblBookTitle.Visibility = Visibility.Visible;
}
else
{
lblNoSearch.Visibility = Visibility.Visible;
lblBookTitle.Visibility = Visibility.Collapsed;
}
}

private void HandleSearchBarnesAndNoble(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(_book))
{
BrowseTo(«http://www.barnesandnoble.com/ebooks/index.asp»);
}
else
{
BrowseTo(«http://productsearch.barnesandnoble.com/search/results.aspx?store=BOOK&keyword=»» + _book.Replace(» «, «+») + «»»);
}
}

private void HandleSearchAmazonBooks(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(_book))
{
BrowseTo(«http://www.amazon.com/gp/aw/sb.html/sn=Books»);
}
else
{
BrowseTo(«http://www.amazon.com/gp/aw/s/?k=» + _book.Replace(» «, «+»));
}
}

private static void BrowseTo(string address)
{
var webTask = new Microsoft.Phone.Tasks.WebBrowserTask { Uri = new Uri(address) };
webTask.Show();
}
}

Теперь, когда мы запустим наше приложение через контракт поиска, мы увидим следующее:

Поддержка Мгновенных ответов приложения
Ещё одна связанная функция, появившаяся в Windows Phone Mango — это Мгновенные ответы приложения. Это автоматическая функция поиска Bing, в которой приложение Bing решает о наличии отношения к конкретным признакам поиска в топе результатов поиска. Вам не нужно ничего делать, чтобы поддержать запуск из Мгновенных ответов, но вы можете воспользоваться информацией, передаваемой через эту функциональность, если вы выберете. Эта информация предоставляется через параметр строки запроса именуемый «bing_query» и доступна по аналогии с параметрами строки запроса ProductName и Category.
Изменить наш пример приложения для использования Мгновенных ответов очень просто, как это показано в верхней части метода HandleLoaded:

// Determine what the context of the app launch is
if (NavigationContext.QueryString.ContainsKey(«ProductName»))
{
_book = NavigationContext.QueryString[«ProductName»];
lblPageTitle.Text = «Book Details»;
}
else if (NavigationContext.QueryString.ContainsKey(«bing_query»))
{
_book = NavigationContext.QueryString[«bing_query»];
lblPageTitle.Text = «Related Search»;
}

Эта модификация позволяет приложению захватить название книги из названия продукта в Быстрой карточке, если таковая имеется или из запроса Bing, который сформировал результат Мгновенного ответа. На рисунке ниже показан вход в приложение через результат Мгновенного ответа для поисковой строки «Sphere by Michael Crichton»

Тестирование контракта поиска
Вы можете быть озадачены как протестировать Мгновенные ответы или как подключиться с помощью отладчика при работе с расширениями поиска. Это важный момент, так как в настоящее время нет хорошего пути влияния на результаты поиска Bing с помощью эмулятора, а при работе с поисковыми расширениями атрибут Category не регистрируется так же, как это было бы на  устройстве. Он такж еможет затратить много времени чтобы перейти на Bing, выполняя конкретный поисковый запрос,  а затем запустить приложение, с помощью контракта поиска. К счастью, есть простой способ для имитации запуска вашего приложения или через поисковые расширения, или через Мгновенные ответы.
Так как мы можем предсказать, параметры строки запроса, которые будут генерировать Быстрые карточки при входе в наше приложение, можно жестко задать эти значения в точке входа приложения для тестирования. Windows Phone приложения хранят адрес страницы по умолчанию внутри файла WMAppManifest.xml в элементе свойств проекта. Откройте этот файл и найдите элемент DefaultTask в коллекции Tasks. Это должно выглядеть примерно так:

<DefaultTask Name =»_default» NavigationPage=»MainPage.xaml»/>

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

<DefaultTask Name =»_default» NavigationPage=»MainPage.xaml?bing_query=Sphere by Michael Crichton»/>

Модификации для имитации точки входа расширений поиска для аналогичного продукта очень похожи. Обратите внимание, что поскольку мы указали несколько параметров строки запроса, использование &amp; для избежания знака амперсанд (&) является важным, как показано в следующем примере:

<DefaultTask Name =»_default» NavigationPage=»MainPage.xaml?Category=Bing_Products_Books_and_Magazines&amp;ProductName=Sphere»/>

Конечно, как только вы закончите тестирование и готовы для развертывания приложения, убедитесь, что удалили все жестко закодированные параметры строки запроса из задачи по умолчанию так, чтобы приложение работало так, как было задумано.
Иногда можно столкнуться с ошибкой развертывания при принятии изменений в файле WMAppManifest.xml и при попытке запуска приложения в эмуляторе.  Если развертывание завершается сообщением: “Installation of the application failed. Run time error has occurred. Fix the Capabilities in WMAppManifest.xml file.” («Установка приложения не удалась. Произошла ошибка во время выполнения. Исправьте возможности в файле WMAppManifest.xml«), а раздел возможностей (capabilities) выглядит нормально, то просто пересоберите (rebuild) приложение и попробуйте снова.

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

Перевод: Сергей Урусов

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *