Статьи

SkyDrive Sync на Windows Phone — Как мне управлять внешним хранилищем?

Если вы пропустили это, я запускаю серию, в которой рассказывается, как создать приложение, которое синхронизирует контент с ваших устройств Windows Phone напрямую в SkyDrive. Есть два предыдущих взноса:

Сегодня я собираюсь поговорить о следующей теме на линии — как обрабатывать контент из внешнего хранилища.

Очевидно, что внешнее хранилище не то, что применимо к каждому устройству Windows Phone 8. Хотя API поддерживает это, не все устройства поддерживают. В целях тестирования я использую устройство Nokia Lumia 825 с картой памяти microSD 16 ГБ. Он наполнен произвольным контентом — изображениями, текстовыми файлами, парой электронных книг и видео.

Здесь начинается интересная часть — есть несколько вещей, о которых вы должны знать заранее:

  • На этом этапе вы не можете записывать контент во внешнее хранилище. Это сделано специально, и вы не можете обойти это ограничение через общедоступный SDK / API.
  • Вы не можете получить доступ к встроенным мультимедийным папкам. Это тоже по замыслу. Если вы видите папки, содержащие изображения, музыку или видео, которые не были созданы вами — вы не сможете получить к ним доступ через API. С другой стороны, картинки и скриншоты будут по-прежнему доступны через стандартную PhotoChooserTask .
  • Вы можете читать только те файлы, расширение которых связано с вашим приложением. То есть вы должны указать в манифесте приложения, какие расширения файлов вы хотите обработать.
  • Некоторые расширения, которые вы можете захотеть зарегистрировать, уже зарезервированы ОС. Это означает, что вы не можете читать файлы DOCX, XLSX, MP3 или JPEG, поскольку вы не можете напрямую связать их с вашим приложением. Для более полного списка, пожалуйста, прочитайте эту статью MSDN .

Давайте код.

Прежде всего, давайте погрузимся в файл WMAppManifest.xml, чтобы убедиться, что мы объявляем некоторые примеры расширений файлов. А теперь давайте связать PDF, RAR и MPG с приложением синхронизации. Для этого я собираюсь добавить узел FileTypeAssociation в контексте расширений :

<FileTypeAssociation Name="SyncFiles"
                        NavUriFragment="fileToken=%s"
                        TaskID="_default">
     <Logos>
       <Logo Size="small"
             IsRelative="true">Assets/fileIcon.png</Logo>
       <Logo Size="medium"
             IsRelative="true">Assets/fileIcon_69x69.png</Logo>
       <Logo Size="large"
             IsRelative="true">Assets/fileIcon_176x176.png</Logo>
     </Logos>
     <SupportedFileTypes>
       <FileType>.pdf</FileType>
       <FileType>.rar</FileType>
       <FileType>.mpg</FileType>
     </SupportedFileTypes>
</FileTypeAssociation>

ПРИМЕЧАНИЕ . Узел Extensions следует размещать сразу после токена .

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

Также смело меняйте расположение значков файлов. Подробнее об использовании файловых ассоциаций в Windows Phone вы можете прочитать  здесь .

Теперь поговорим о способах фактического выбора контента с внешнего устройства хранения. Для этого я создал пользовательский элемент управления, называемый  FileExplorer . Это универсальное решение для выбора файлов, позволяющее просматривать файловую систему как в изолированном, так и во внешнем хранилище. Вы можете скачать его, получив экспериментальную ветку  Coding4Fun Toolkit .

ПРИМЕЧАНИЕ. Убедитесь, чтов качестве необходимой возможности выбран ID_CAP_REMOVABLE_STORAGE . В противном случае будет выдано исключение UnauthorizedAccessException.

Возвращаясь к подсказке, где нам нужно было выбрать цель хранения, теперь вы можете использовать элемент управления FileExplorer:

else if (returnButton == 1)
{
    // The user decided to use the external storage.

    Dispatcher.BeginInvoke(() =>
        {
            FileExplorer explorer = new FileExplorer();
            explorer.SelectionMode = SelectionMode.File;
            explorer.StorageTarget = StorageTarget.ExternalStorage;
            explorer.OnDismiss += explorer_OnDismiss;

            explorer.Show();
        });
}

Когда элемент управления FileExplorer отклоняется,   экземпляр ExternalStorageFile возвращается в контексте обработчика события OnDismiss.

После вызова обработчика OnDismiss я получаю имя и путь к файлу в качестве эталонного токена:

void explorer_OnDismiss(StorageTarget target, object file)
{
    var reference = new FileReference();
    reference.FileType = FileType.ExternalStorage;
    reference.Name = ((ExternalStorageFile)file).Name;
    reference.Token = ((ExternalStorageFile)file).Path;

    FileReferences.Add(reference);
}

Ссылка позже добавляется в коллекцию FileReferences, после чего она отображается в ListBox. 

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