Опубликован: 02.08.2013 | Доступ: свободный | Студентов: 464 / 16 | Длительность: 18:38:00
Специальности: Программист
Самостоятельная работа 22:

Работа с SD-картой, сопоставление типов файлов

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

  1. Объявление сопоставления типов файлов в манифесте
  2. Наличие класса, унаследованного от UriMapperBase, который принимает управление после запуска приложения, анализирует URI, с которым оно запущено, и, если этот URI соответствует запуску приложения для открытия внешнего файла, передаёт данные файла соответствующей странице приложения.
  3. Установка экземпляра класса, анализирующего строку запуска, в свойство UriMapper рамки приложения (это выполняется в коде файла App.xaml.cs.
  4. Наличие страницы, которая может обработать вызов её для открытия внешнего файла

Первый пункт этого списка мы уже рассмотрели, что касается второго, класса, который выполняет анализ данных при запуске приложения, то он описан в файле CustomUriMapper.cs, Листинг 30.2.

using System;
using System.Windows.Navigation;
namespace P22_1
{
    class CustomURIMapper : UriMapperBase
    {
        private string tempUri;

        public override Uri MapUri(Uri uri)
        {
            tempUri = uri.ToString();

            // Запуск приложения по сопоставлению с типом файла, для открытия внешнего файла
            // Адрес запуска может выглядеть так: /FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19
            if (tempUri.Contains("/FileTypeAssociation"))
            {
                // Получаем ID файла (то, что после "fileToken=").
                int fileIDIndex = tempUri.IndexOf("fileToken=") + 10;
                string fileID = tempUri.Substring(fileIDIndex);

                // Вызываем страницу просмотра файла с полученным идентификатором.
                return new Uri("/FileViewPage.xaml?fileToken=" + fileID, UriKind.Relative);
            }

            // В противном случае производится обычный запуск приложения.
            return uri;
        }
    }
}
Листинг 59.2. Код файла CustomUriMapper.cs

Здесь мы проверяем, запущено ли приложение для обработки внешнего файла, если это так – вызываем страницу FileViewPage.xaml и передаём ей идентификатор файла. Если это не так – на выходе из метода класса MapUri оказывается исходный адрес запуска, то есть, приложение запускается обычным образом.

Что касается файла App.xaml.cs, здесь, Листинг 30.3, нам нужно назначить свойству UriMapper рамки приложения объект типа CustomUriMapper (наследник UriMapperBase). Это делается в методе InitializePhoneApplication, код, добавленный в этот метод, выделен.

        private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;

            // Создайте кадр, но не задавайте для него значение RootVisual; это позволит
            // экрану-заставке оставаться активным, пока приложение не будет готово для визуализации.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;

            //------------------

            // Назначаем объект, сопоставляющий URI, свойству рамки приложения.
            RootFrame.UriMapper = new CustomURIMapper();

            //------------------

            // Обработка сбоев навигации
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;

            // Обработка запросов на сброс для очистки стека переходов назад
            RootFrame.Navigated += CheckForResetNavigation;

            // Убедитесь, что инициализация не выполняется повторно
            phoneApplicationInitialized = true;
        }
Листинг 59.3. Фрагмент кода файла App.xaml.cs

На странице MainPage.xaml размещена кнопка и список (Листинг 30.4). В список, используя механизм привязки данных, попадают найденные имена файлов.

<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <Button
        x:Name="scanExternalStorageButton"
        Content="Поиск myapp-файлов на SD-карте"
        Click="scanExternalStorageButton_Click_1"   
        />

    <!-- ListBox is bound to a collection of GPX files named Routes -->
    <ListBox
        x:Name="myappFilesListBox"
        ItemsSource="{Binding MyAppFiles}"
        SelectionChanged="myappFilesListBox_SelectionChanged_1"
        >
        <!-- Каждый элемент ListBox привязан к имени файла -->
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock
                    Margin="0, 12, 0, 0"
                    Text="{Binding Name}"
                    Style="{StaticResource PhoneTextTitle2Style}"
                    />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>
Листинг 59.4. Фрагмент файла MainPage.xaml

В коде страницы (Листинг 59.5) мы, по нажатию на кнопку, пытаемся обратиться к заданной папке SD-карты. Если обращение удаётся, мы получаем список файлов из папки и переносим этот список в коллекцию, которая привязана к элементу управления, выводящему данные на экран.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Storage;
using System.Collections.ObjectModel;
using System.IO;
namespace P22_1
{
    public partial class MainPage : PhoneApplicationPage
    {
        //Коллекция .myapp - файлов для привязки к списку
       
        public ObservableCollection<ExternalStorageFile> MyAppFiles { get; set; }

        // Конструктор
        public MainPage()
        {
            InitializeComponent();

            // Инициализация коллекции файлов.
            MyAppFiles = new ObservableCollection<ExternalStorageFile>();

            // Привязка страницы к своим данным.
            this.DataContext = this;
        }

        // Сканирование SD-карты в поиске .myapp-файлов
        private async void scanExternalStorageButton_Click_1(object sender, RoutedEventArgs e)
        {
            // Очистка коллекции, привязанной к странице
            MyAppFiles.Clear();

            // Подключение к SD-карте
            ExternalStorageDevice _sdCard = 
(await ExternalStorage.GetExternalStorageDevicesAsync()).FirstOrDefault();

            // Если SD-карта подключена к устройству, добавляем .myapp-файл в коллекцию.
            if (_sdCard != null)
            {
                try
                {
                    // Обнаружение папки Myapp на SD-карте.
                    ExternalStorageFolder myappFolder = await _sdCard.GetFolderAsync("Myapp");

                    // Получение файлов, с которыми может работать приложение, из папки.
                    IEnumerable<ExternalStorageFile> myappFiles = await myappFolder.GetFilesAsync();

                    // Добавление .myapp-файлов в коллекцию
                    foreach (ExternalStorageFile esf in myappFiles)
                    {
                        if (esf.Path.EndsWith(".myapp"))
                        {
                            MyAppFiles.Add(esf);
                        }
                    }
                }
                catch (FileNotFoundException)
                {
                    // Нет папки Myapp.
                    MessageBox.Show("На SD-карте нет папки Myapp. 
Добавьте на карту эту папку, разместите в ней хотя бы один .myapp-файл и попробуйте снова.");
                }
            }
            else
            {
                // Нет SD-карты.
                MessageBox.Show("SD-карта не найдена. 
Подключите SD-карту, на которой есть папка Myapp с хотя бы одним 
.myapp-файлом и попробуйте снова.");
            }
        }
        // При выборе файла выполняется вызов страницы FileViewPage с передачей ей пути к файлу
             private void myappFilesListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
        {
            ListBox lb = (ListBox)sender;

            if (lb.SelectedItem != null)
            {
                ExternalStorageFile esf = (ExternalStorageFile)lb.SelectedItem;
                NavigationService.Navigate(new Uri("/FileViewPage.xaml?sdFilePath=" + esf.Path, UriKind.Relative));
            }
        }
    }
}
Листинг 59.5. Код файла MainPage.xaml.cs