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

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

Задание 1. Регистрация сопоставлений файлов

Аналогично предыдущему упражнению, необходимо объявить поддерживаемое расширение файла. На этом практическом занятии мы сопоставим приложение ContosoCookbook с расширениями файлов .recipe и .rcp. Сначала, и это самое главное, необходимо соответствующим образом изменить манифест приложения.

  1. Откройте решение из папки Solution/EX2/Begin для данного практического занятия или из папки предыдущего упражнения.
  2. Зайдите в папку Properties (Свойства) и откройте файл WMAppManifest.xml в редакторе XML.
  3. Найдите элемент Extensions XML и добавьте следующий код перед элементом Protocol:
<FileTypeAssociation Name="RecipeLaunch" TaskID="_default" NavUriFragment="fileToken=%s"> <SupportedFileTypes> <FileType>.rcp</FileType> <FileType>.recipe</FileType> </SupportedFileTypes> </FileTypeAssociation>

Примечание. В Windows Phone 8 можно открывать файлы из разных местоположений. Если приложение должно открывать файлы из внешнего хранилища (например, с карты SD), необходимо зарегистрировать тип содержимого (ContentType) и сопоставить его с типом файлов (FileType), например: 
<FileType ContentType="application/recipe">.recipe</FileType>.

Корневой элемент новой конфигурации — сопоставление типа файла FileTypeAssociation, оно должно быть прямым дочерним элементом элемента Extensions (здесь не показано). Этот элемент содержит сопоставления типов файлов приложения. В элементе SupportedFileTypes можно объявить до 20 расширений файлов и назначить элемент FileType для каждого расширения. Элемент FileTypeAssociation описывает набор файловых расширений с одним типом содержимого и значком логотипа.

Кроме того, манифест можно использовать для объявления логотипов типов файлов, хотя это и не обязательно. Чтобы задать изображения логотипов, добавьте объявления для трех размеров логотипов:

  • мелкий: 33 х 33, используется во вложениях в электронную почту;
  • средний: 69 х 69, используется в представлениях списка концентраторов Office;
  • крупный: 176 х 176, используется в загрузках веб-браузера.
  1. В приведенном ниже определении используются изображения логотипа и обязательные расширения файлов, описанные в предыдущем примере.

<FileTypeAssociation Name="RecipeLaunch" TaskID="_default" NavUriFragment="fileToken=%s"> <Logos> <Logo Size="small">SmallFileIcon.png</Logo> <Logo Size="medium">MediumFileIcon.png</Logo> <Logo Size="large">LargeFileIcon.png</Logo> </Logos> <SupportedFileTypes> <FileType>.rcp</FileType> <FileType ContentType="application/recipe">.recipe</FileType> </SupportedFileTypes> </FileTypeAssociation>

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

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

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

  1. В обозревателе решений разверните папку Common (Общие) и откройте файл CookbookUriMapper.cs.
  2. Добавьте следующие члены данных в класс CookbookUriMapper:
private static string FileTemplate = "/FileTypeAssociation?fileToken=";

Этот шаблон определяет, является ли URI запросом на сопоставление типов файлов.

3. Найдите метод MapUri и добавьте следующий код после оператора «tempUri = uri.ToString()»:
if (tempUri.Contains("/FileTypeAssociation")) { tempUri = HttpUtility.UrlDecode(tempUri); if (tempUri.Contains("fileToken")) { return GetFileMappedUri(tempUri); } }

Код проверяет, представляет ли данный URI запрос на сопоставление файлов, и вызывает метод GetFileMappedUri для перенаправления на соответствующую страницу приложения.

4. Добавьте метод GetFileMappedUri в класс следующим образом:
private Uri GetFileMappedUri(string uri) { string fileToken = ""; // Extract parameter values from URI. if (uri.IndexOf(FileTemplate) > -1) { int groupIdLen = uri.IndexOf("=", 0); fileToken = uri.Substring(groupIdLen + 1); } string NewURI = String.Format("/{0}?ID={1}&Command=HandleFile", TargetPageName, fileToken); return new Uri(NewURI, UriKind.Relative); }

Этот код перенаправляет запрос на страницу RecipeDetailPage.xaml, которая считывает содержимое файла и отображает рецепт.

5. Откройте файл RecipeDetailPage.xaml.cs и добавьте в начало файла следующие операторы using:
using Windows.Phone.Storage.SharedAccess; using Windows.Storage.Streams; using System.Xml.Linq;using Windows.Storage;

6. Затем найдите метод OnNavigatedTo: он вызывается, поскольку UriMapper перенаправил запрос на эту страницу. Замените оператор «string UniqueId = NavigationContext.QueryString["ID"];» следующим кодом:

string UniqueId = ""; if (NavigationContext.QueryString.ContainsKey("Command")) { string fileToken = NavigationContext.QueryString["ID"]; var filename = SharedStorageAccessManager. GetSharedFileName(fileToken); var file = await SharedStorageAccessManager. CopySharedFileAsync( ApplicationData.Current.LocalFolder, fileToken + ".rcp", NameCollisionOption.ReplaceExisting, fileToken); var content = await file.OpenAsync(FileAccessMode.Read); DataReader dr = new DataReader(content); await dr.LoadAsync((uint)content.Size); //Get XML from file content string xml = dr.ReadString((uint)content.Size); //Load XML document XDocument doc = XDocument.Parse(xml); XName attName = XName.Get("ID"); XAttribute att = doc.Root.Attribute(attName); //Get UniqueId from file UniqueId = att.Value; } else UniqueId = NavigationContext.QueryString["ID"];

В этом коде используется класс SharedStorageAccessManager из пространства имен Windows.Phone.Storage, чтобы извлекать имя файла из токена, получаемого приложением. Затем код копирует файл из общего местоположения в локальное хранилище приложения, откуда к нему может осуществляться доступ.

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

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

<?xml version="1.0" encoding="utf-8" ?> <Recipe ID="1003"/>

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

Приложение использует классы LINQ to XML (XDocument и XName) для извлечения идентификатора рецепта из XML-файла. Выполнив извлечение идентификатора, приложение продолжает работу, как в предыдущем упражнении.

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

Существует три способа протестировать сопоставления файлов.

  • Отправка электронного сообщения с прикрепленным файлом. Например, если к электронному сообщению прикреплен PDF-файл, то пользователь может щелкнуть маленький логотип PDF-файла: будет инициирован поиск сопоставлений файлов в системе. Затем пользователь выбирает приложение для запуска (при наличии нескольких доступных вариантов). Если имеется только одно зарегистрированное приложение, оно запускается автоматически.

Если на устройстве нет доступных зарегистрированных приложений, ОС Windows Phone представляет стандартное системное диалоговое окно (см. изображение ниже).

Рис. 7.
Системное диалоговое окно для поиска нужного приложения

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

  • Скачивание файла в веб-браузере. После скачивания файла в веб-браузере и щелчка логотипа (крупного размера) запускается поиск и осуществляется переход к сопоставлению файлов.


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

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

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

  1. Создайте новое приложение Windows Phone.
  2. Инициировать навигацию по сопоставлениям файлов можно только в том случае, если приложение имеет файл в изолированном хранилище. Добавьте в приложение новый файл. Содержимое файла, подходящее для приложения ContosoCookbook, должно выглядеть следующим образом:
<?xml version="1.0" encoding="utf-8" ?> <Recipe ID="1003"/>
  1. Убедитесь, что файл называется sample.rcp (или .recipe — в этом случае необходимо удостовериться, что в методе WriteFiles ниже используется новое название).

  2. Для включения файла в пакет приложений щелкните файл правой кнопкой мыши в обозревателе решений и выберите Properties (Свойства).
  3. Измените действие построения на Content (Содержимое).
  4. Добавьте кнопку для загрузки и запуска файла.
  5. Добавьте следующий код в обработчик события нажатия кнопки:
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder; if (local != null) { await WriteFiles(); StorageFile recipeFile = await local.GetFileAsync("sample.rcp"); if (recipeFile != null) await Windows.System.Launcher.LaunchFileAsync(recipeFile); }

Этот код вызывает метод WriteFiles, который инициализирует пример файла, а затем запускает навигацию по приложениям с помощью описанного выше метода LaunchFileAsync.

7. Добавьте метод WriteFiles:
private async Task WriteFiles() { StreamReader stream = new StreamReader(TitleContainer.OpenStream("recipe.rcp")); StorageFolder local = Windows.Storage. ApplicationData.Current.LocalFolder; var file = await local.CreateFileAsync ("sample.rcp", CreationCollisionOption.ReplaceExisting); string fileAsString = stream.ReadToEnd(); byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(fileAsString); var outputStream = await file.OpenStreamForWriteAsync(); outputStream.Write(fileBytes, 0, fileBytes.Length); stream.Close(); outputStream.Close(); }

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

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

9. На этом упражнение и практическое занятие завершено.

Краткая информация:

На этом занятии мы рассмотрели действия, которые следует выполнить для сопоставления файлов и имен схем URI в приложении Windows Phone 8.

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

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

Предыдущая | Назад