Упражнение 1. Сопоставление файлов и протоколов

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

Задание 1. Настройка сопоставлений имен схем URI

Каждое приложение, использующее сопоставления URI, объявляет имя схемы URI, которое оно может обработать. Приложение ContosoCookbook отображает рецепты и, следовательно, обрабатывает имя схемы URI «recipe». Для обработки имени схемы URI приложение ContosoCookbook использует схему URI «recipe://».

  1. Перейдите в установочную папку практического занятия Source\EX1\Begin и откройте файл запуска решения ContosoCookbook.sln в Visual Studio 2012.

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

    Выбрав этническую группу, пользователь переходит на следующую страницу — GroupDetailPage.xaml. Здесь используется элемент управления Pivot для отображения двух элементов: сведений о группе (включая число доступных рецептов) и рецептов группы, имеющихся в приложении или приобретаемых пользователем через встроенные механизмы покупки (они подробно рассматриваются в другом практическом занятии).

    Наконец, на странице RecipeDetailPage.xaml отображается выбранный рецепт. Именно эта страница с рецептом открывается после запуска приложения с использованием сопоставления имен схем URI.

  2. Чтобы создать сопоставление имен схем URI, необходимо изменить манифест приложения. В обозревателе решений разверните папку Properties (Свойства) и найдите файл WMAppManifest.xml. Щелкните правой кнопкой файлWMAppManifest.xml и выберите в контекстном меню Open with (Открыть с помощью).

    Рис. 1.
    Элемент меню Open With (Открыть с помощью)

  3. В диалоговом окне Open With выберите XML (text) Editor (Редактор XML (текстовый)) и нажмите кнопку ОК.

    Рис. 2.
    Открыть в редакторе XML (текстовом)

  4. Найдите XML-элемент Tokens (Маркеры) и добавьте следующий код сразу после закрывающего тега </Tokens>:
<Extensions> <Protocol Name="recipe" TaskID="_default" NavUriFragment="encodedLaunchUri=%s" /> </Extensions>

Данный код регистрирует приложение ContosoCookbook в качестве обработчика имени схемы URI «recipe».

Примечание. Элемент Extensions нужно добавить после элемента Tokens.

Примечание. Приложение не может зарегистрировать произвольное имя схемы URI; некоторые сопоставления файлов и имен схем URI зарезервированы. Если приложение регистрирует зарезервированное сопоставление, то регистрация игнорируется. Полный список зарезервированных имен схем URI доступен в документации MSDN.

Задание 2. Настройка сопоставления URI

В предыдущем задании мы настроили приложение для обработки запросов на запуск с использованием схемы URI «recipe://». В процессе выполнения приложение должно обрабатывать любой запуск URI и проверять, использует ли URI соответствующую схему URI. Если приложение не может обработать URI, то оставляет его неизменным. Запросы перенаправляются на внутреннюю страницу, отображающую подробные сведения о рецепте.

  1. Найдите в обозревателе решений папку Common.
  2. Правой кнопкой мыши щелкните папку Common, выберите Add (Добавить) и щелкните Class (Класс).

    Рис. 3.
    Добавление нового класса

  3. Измените имя класса на CookbookUriMapper.cs и нажмите кнопку ОК.

    Рис. 4.
    Присвоение имени новому классу в диалоговом окне Add New Item (Добавление нового элемента)

  4. Добавьте в файл оператор using для объявления пространств используемых имен:
using System.Windows.Navigation; using System.Net;

5. Новый класс будет зарегистрирован в качестве средства сопоставления URI для приложения; это означает, что он наследуется от базового класса UriMapperBase.

class CookbookUriMapper : UriMapperBase { }

6. Добавьте элементы данных, которые впоследствии будут использоваться методами класса:

private static string TargetPageName = "RecipeDetailPage.xaml"; private static string ProtocolTemplate = "/Protocol?encodedLaunchUri="; private static int ProtocolTemplateLength = ProtocolTemplate.Length; private string tempUri;

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

5. И напоследок мы добавим код для получения снимка. В упражнении 2 мы создали пустой обработчик событий для кнопки Take Picture (Сделать снимок) на панели приложения ApplicationBar. Найдите метод btnTakePicture_Click и добавьте в него следующий код:

try { camera.Show(); } catch (System.InvalidOperationException ex) { MessageBox.Show("An error occurred."); }

6. Добавьте элементы данных, которые впоследствии будут использоваться методами класса:

private static string TargetPageName = "RecipeDetailPage.xaml"; private static string ProtocolTemplate = "/Protocol?encodedLaunchUri="; private static int ProtocolTemplateLength = ProtocolTemplate.Length; private string tempUri;

7. UriMapperBase — это абстрактный класс, содержащий единственный абстрактный метод MapUri, который должен быть переопределен производными классами. Переопределите этот метод, добавив следующий код:

public override Uri MapUri(Uri uri) { tempUri = uri.ToString(); if (tempUri.Contains("/Protocol")) { tempUri = HttpUtility.UrlDecode(tempUri); if (tempUri.Contains("recipe:")) { return GetMappedUri(tempUri); } } return uri; }

Предыдущий фрагмент кода содержит два сценария для обработки запрошенного URI:

  • если приложение активировано с использованием имени схемы URI «recipe», то в этом случае URI имеет следующий формат:{имя схемы URI}:{параметры приложения}.

Примечание. Приложение ContosoCookbook использует классический формат URI для передачи параметров, схожий с форматом URL-адресов, который поддерживается веб-браузерами: ?{параметр}={значение}&{параметр}={значение}. В приложении можно использовать подход, отличный от кодирования: с помощью пар «имя–значение».

  • Если параметр URI запускается посредством сопоставления имен схем URI, то он содержит строку “/Protocol”. По ней приложение определяет, что оно запущено посредством сопоставления URI.

    После того как средство сопоставления URI удостоверится, что приложение обработает этот запрос, будет выполнено перенаправление на внутреннюю страницу приложения (см. описание в следующем шаге).

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

8. Добавьте следующий вспомогательный метод для сопоставления URI. Этот частный метод обеспечивает возможность сопоставления для приложения ContosoCookbook.

private Uri GetMappedUri(string uri) { string operation = ""; string groupUID = ""; // Extract parameter values from URI. if (uri.IndexOf(ProtocolTemplate) > -1) { int operationLen = uri.IndexOf("?", ProtocolTemplateLength); int groupIdLen = uri.IndexOf("=", operationLen + 1); operation = uri.Substring(ProtocolTemplateLength, operationLen - ProtocolTemplateLength); groupUID = uri.Substring(groupIdLen + 1); } string NewURI = String.Format("/{0}?ID={1}", TargetPageName, groupUID); return new Uri(NewURI, UriKind.Relative); }

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

9. Реализации средства сопоставления URI не достаточно; следует отправить системе инструкцию о необходимости использовать данное средство сопоставления URI в составе приложения.

Чтобы зарегистрировать средство сопоставления URI, откройте файл App.xaml.cs, найдите метод InitializePhoneApplication и добавьте следующий код между строкой, выполняющей регистрацию события RootFrame.Navigated, и строкой, выполняющей регистрацию события RootFrame.NavigationFailed:

RootFrame.UriMapper = new CookbookUriMapper();
10. Наконец, нужно инициализировать данное приложение на случай, если оно запускается посредством сопоставления имен схем URI. Откройте файл RecipeDetailPage.xaml.cs и найдите метод OnNavigatedTo. Измените подпись метода, добавив ключевое слово async:
protected async override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) {

11. Вставьте следующий код перед вызовом метода NavigateToRecipe(UniqueId):

if (!App.Recipes.IsLoaded) await App.Recipes.LoadLocalDataAsync(); NavigateToRecipe(UniqueId);

Это позволяет загрузить данные рецепта, если приложение запускается посредством сопоставления имен схем URI. Убедившись, что инициализация выполнена, приложение продолжает работать как обычно, вызвав методNavigateToRecipe(UniqueId).

Примечание. В предыдущем фрагменте кода использовано два новых ключевых слова C# 5.0 — async и await. Описание указанных языковых функций, имеющих важнейшее значение для реализации асинхронных приложений в C#, не входит в круг тем этого практического занятия. Дополнительные сведения о C# 5.0, новых ключевых словах этого языка и асинхронном программировании в целом см. в статье 
https://msdn.microsoft.com/en-us/library/hh191443.aspx.

12. Приложение объявлено как обработчик имен схем URI рецепта и готово к тестированию; мы сделаем это в следующем задании.

Задание 3. Тестирование приложения

После настройки кода для обработки запросов на сопоставление имен схем URI мы смоделируем эти запросы извне. Существует три способа моделирования запросов на запуск:

  • Изменение навигации запуска проекта. По умолчанию приложение переходит на страницу MainPage.xaml. Изменение этой настройки для перехода к сопоставлению имен схем URI обеспечит корректную настройку сопоставления URI. Эту стратегию тестирования очень легко реализовать, однако она не позволяет протестировать сопоставление имен схем URI, настроенное в манифесте приложения, и убедиться, что операционная система будет вызывать приложение при наличии правильно отформатированного имени схемы URI.
  • Создание другого приложения для запуска URI со схемой «recipe://». При использовании этого подхода тестируется весь поток — от приложений сторонних разработчиков до операционной системы и самого приложения ContosoCookbook. Недостаток данного подхода — отладка решения: чтобы отладить приложение ContosoCookbook, необходимо запустить его, а затем открыть другое приложение, чтобы инициировать запуск имени схемы URI «recipe://».
  • Использование браузера в качестве инициатора запросов. Этот подход требует создания веб-страницы и размещения ее в Интернете, а также последующего перехода на эту страницу в браузере Internet Explorer. Такой подход тестирует поток полностью, однако требует тщательной подготовки.

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

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

  1. Найдите XML-элемент Tasks (Задачи) и перейдите к элементу DefaultTask.
  2. Измените элемент DefaultTask следующим образом:
<DefaultTask Name="_default" NavigationPage="/Protocol?encodedLaunchUri= recipe://ShowRecipe?ID=1003" />

3. Запустите приложение. Должна отобразиться следующая страница.

Рис. 5.
Страница рецепта, запущенная посредством сопоставления имени схемы URI

Используя указанный подход, мы изменили конфигурацию запуска приложения. Теперь система настроена так, что запуск приложения происходит посредством отправки запроса протокола в средство сопоставления URI. Однако мы не протестировали сопоставление имен схем URI приложения на системном уровне. Это будет сделано с помощью других методов тестирования.

Примечание. Не забудьте отменить изменения, сделанные в узле DefaultTask.

Вторая методика тестирования позволяет смоделировать запросы на запуск путем создания дополнительного приложения Windows Phone 8:

  1. Создайте новое приложение Windows Phone.
  2. Добавьте одну кнопку на его главную страницу.
  3. Подпишитесь на событие нажатия новой кнопки, используя обработчик события в файле с выделенным кодом.
  4. Новое приложение может автоматически запускать исходное приложение, предоставляя операционной системе пользовательский URI. Для этого вызовите статический метод LaunchUriAsync(Uri) класса Launcher, расположенный в пространстве имен Windows.System, следующим образом:
Uri navigationUri = new Uri("recipe://ShowRecipe?ID=1003"); Windows.System.Launcher.LaunchUriAsync(navigationUri);

5. Запустите новое приложение, а затем нажмите кнопку. Должно запуститься приложение ContosoCookbook и отобразиться страница с рецептом из рисунка 3.

Используя указанный подход, мы убедились, что приложение зарегистрировано в качестве обработчика имени схемы URI «recipe» на уровне ОС. Теперь именно операционная система запускает приложение, когда имя схемы URI вызывается из другого приложения.

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

Рис. 6.
Выбор из списка приложений, связанных с одним именем схемы URI

6. Это действие завершает упражнение.

Предыдущая | Следующая