Как получить файлы из музыкальной библиотеки Windows Phone (8.1), используя имена путей?

Я позволяю своим пользователям выбирать файлы из музыкальной библиотеки. После чего я сохраняю путь к выбранным файлам локально. Теперь моя проблема заключается в том, как мне программно получить доступ к файлам по этим путям? Вот несколько вещей, которые я пробовал.

Скажем, мой путь D:\Xyz\abc.mp3

StorageFolder S=KnownFolders.MusicLibrary;

Альтернатива 1:

StorageFile MyFile=await S.GetFileAsync("abc.mp3"); //Ошибка "Файл не найден"

// Я полагаю, что это не работает, потому что метод GetFileAsync может получать файлы только из текущей папки

Альтернатива 2:

S=await S.GetFolderAsync("Xyz"); //После чего я планировал выполнить GetFileAsync. Но это также дает ошибку «Папка не найдена».

И, наконец, я попробовал S=await S.GetFolderAsync("D");

Любая помощь в том, как мне получить доступ к файлу или даже альтернативный способ достижения моей цели, была бы фантастической!

PS: StorageFile.GetFileFromPathAsync("D:\Xyz\abc.mp3") говорит, что у меня нет разрешения на доступ.


person Aditya    schedule 25.04.2014    source источник
comment
GetFileFromPathAsync не гарантирует сохранения доступа к файлам из средства выбора в Windows Phone 8.1. Отказ в доступе является ожидаемым результатом. Для сохранения доступа вам придется использовать пространство имен Windows.Storage.AccessCache. Смотрите мой ответ, чтобы узнать, как сохранить доступ к файлу.   -  person Adam    schedule 02.05.2014


Ответы (3)


(Ответ перестроить, чтобы быть более понятным)

Если вы объявили в файле package.appxmanifest:

  • Music Library возможность в разделе Возможности
  • File Type Association в Declarations (я не уверен, что это необходимо, если вы имеете доступ только к музыкальной библиотеке)

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

StorageFolder folder = KnownFolders.MusicLibrary;
// below code will work unless 'fileName.mp3' is in 
// your Music folder either on phone or SD card
StorageFile file = await folder.GetFileAsync("fileName.mp3");
// you can access them also with path, but in this case
// also Folders must be in Music folder
string path = @"Test\ccc.mp3";
StorageFile file = await folder.GetFileAsync(path);

Подводя итог, вы сможете получить доступ с помощью KnownFolders.MusicLibrary только к файлам, которые находятся либо на телефоне, либо на SD-карте, но в папке «Музыка» - их пути будут тогда:

C:\Data\Users\Public\Music\test.mp3 - для телефона

D:\Music\Test\test2.mp3 - для SD карты

Помните, что доступ с помощью StorageFolder.GetFileAsync() работает относительно StorageFolder (он также будет работать с полным путем, см. примечание ниже):

Имя (или путь относительно текущей папки) извлекаемого файла.

В этом случае, чтобы получить вышеуказанные файлы, вы будете использовать такие имена файлов, как: test.mp3 и Test\test2.mp3.

Вы не сможете получить другие файлы, такие как D:\xxx.mp3 - его нет в музыкальной библиотеке - он находится на SD-карте, если вы хотите получить к нему доступ, вам нужно будет сделать это с помощью KnownFolders.RemovableDevices — после добавления необходимых возможностей вы должны иметь доступ к этому через полный путь. Но также пожалуйста, помните о замечании:

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

В нашем обсуждении выяснилось, что вы используете CommonFileQuery.OrderByName для получения файлов. Как я проверил, там (IMO) может быть небольшая ошибка - в описании VS говорится, что:

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

Запуск фрагмента кода:

// a method to retrieve files from Musiic Library recursively 
private async Task RetriveFilesInFolders(List<StorageFile> list, StorageFolder parent)
{
   foreach (var item in await parent.GetFilesAsync()) list.Add(item);
   foreach (var item in await parent.GetFoldersAsync()) await RetriveFilesInFolders(list, item);
}

// then I've used it like this:

StorageFolder folder = KnownFolders.MusicLibrary;

List<StorageFile> listOfFiles = new List<StorageFile>();
await RetriveFilesInFolders(listOfFiles, folder);
// as a result of above code I have a List of 5 files that are in Music Library

List<IStorageItem> filesFolders = (await folder.GetItemsAsync()).ToList();
List<StorageFile> items = (await folder.GetFilesAsync(CommonFileQuery.OrderByName)).ToList();
// as a result here I've 14 files that are in Music Library and SD card, and Phone

дал результаты:

  • в первом случае 5 файлов, которые на самом деле находятся в папке Музыка и ее подпапках,
  • во втором случае - 14 файлов, которые находятся в: Музыкальной библиотеке, SD-карте и Телефоне

Вы можете легко посмотреть на Path в режиме отладки, и вы увидите, что некоторые файлы во втором методе имеют D:\file.mp3 и так далее - их нет в фонотеке - так что вы не сможете получить их KnownFolders.MusicLibrary. Если вы хотите их получить, вам придется использовать другие KnownFolders — в данном случае SD-карту:

StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
StorageFolder sdCard = (await externalDevices.GetFoldersAsync()).FirstOrDefault();
StorageFile file = await sdCard.GetFileAsync("xyz.mp3"); // for D:\xyz.mp3
StorageFile file = await sdCard.GetFileAsync("XYZ\xyz.mp3"); // for D:\XYZ\xyz.mp3
person Romasz    schedule 25.04.2014
comment
У меня отмечена возможность музыкальной библиотеки. Я извлекаю все файлы из библиотеки и позволяю пользователям выбирать их. Затем я сохраняю пути к файлам, до которых все в порядке. Теперь я хочу получить доступ к этим файлам позже в своем приложении. Как я уже сказал, StorageFile file = await folder.GetFileAsync(fileName.mp3); не работает. И я уверен, что такой файл существует в библиотеке, потому что я получил имя из объектов StorageFile, выбранных моим пользователем. Простым способом было бы каждый раз выполнять GetFilesAsync(Query) и искать мой файл в результате. Но это привело бы к ужасной производительности. - person Aditya; 25.04.2014
comment
@ Aditya Я думаю, вам следует использовать не Path, а Name и родительскую папку. Посмотрите, что StorageFolder folder = KnownFolders.MusicLibrary дает вам доступ к музыкальной библиотеке - вы должны получить файлы относительно нее. Я не уверен, что запоминание пути или имени - хороший способ - посмотрите, что Music Lib может быть на SD-карте и в памяти телефона, пользователь может переключать файлы между ними. Вы также должны проверить, не удалил ли пользователь файл. - person Romasz; 25.04.2014
comment
Пробовал использовать имя, тоже не работает. И ни одна из ситуаций удаления, перемещения не происходит, потому что я делаю это на своем телефоне/эмуляторе. - person Aditya; 25.04.2014
comment
@ Aditya Я пробовал это на устройстве, и оно должно работать. Я не понял - вы тестируете это на эмуляторе или устройстве? - person Romasz; 25.04.2014
comment
Делал оба. Та же ошибка. А можно уточнить, что сработало в вашем случае? - person Aditya; 25.04.2014
comment
@Aditya Я отредактировал ответ и добавил проверенный код - он работает. Вы добавили ассоциацию типов файлов в объявления? А вы используете Win8.1 RT или Silverlight? - person Romasz; 25.04.2014
comment
Можете ли вы сказать мне, как выглядит ваш путь к элементу [1]? - person Aditya; 25.04.2014
comment
давайте продолжим это обсуждение в чате - person Romasz; 25.04.2014
comment
В моем случае мне также пришлось добавить возможность съемного хранилища (в дополнение к музыкальной библиотеке). После этого начинает работать. - person Illidan; 23.06.2014
comment
@Illidan Если вы хотите получить доступ к файлам на SD-картах - да, вы должны добавить эту возможность. Это зависит от пути к файлу, к которому вы хотите получить доступ. - person Romasz; 23.06.2014
comment
@Romasz Все, что я хотел, это получить доступ к папке KnownFolders.MusicLibrary. Пока я не объявил Removable Storage, мне было отказано в доступе. После того, как я заявил - он начал работать - person Illidan; 24.06.2014
comment
@Illidan Возможно, музыкальная библиотека — это виртуальное место, которое фактически существует как на телефоне, так и на SD-карте. Я не проверял, требуется ли для доступа к одному файлу в Music на SD через MusicLibrary функцию Removable. Спасибо за замечание. - person Romasz; 24.06.2014
comment
@Romasz: я хотел знать, как вы обновляете список, когда пользователь меняет контент в своей MusicLibrary. Проверяете ли вы каждый раз, когда приложение открывается, делая данные постоянными, что занимает много времени, или вы пытаетесь делать это в фоновом режиме? - person AbsoluteSith; 12.04.2015
comment
@AbsoluteSith Пока у меня нет такой потребности. Нет доступного события, которое могло бы вам помочь. Я думаю, что лучше всего было бы предоставить пользователю кнопку типа «синхронизировать» или сделать это как-то в фоновом режиме с работающим индикатором, информирующим пользователя о том, что что-то происходит. - person Romasz; 12.04.2015
comment
@Romasz: Спасибо за помощь, я проверю. - person AbsoluteSith; 12.04.2015

Во-первых, убедитесь, что у вас установлены правильные возможности. Ошибка, которую вы получаете, это то, что вы увидите, если не объявите правильный CAP_ID . Вот скриншот:

введите здесь описание изображения

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

"isostore:shared\\Имя_папки\\ИмяФайла.mp3"

Вы можете увидеть весь процесс в мой ТАК пост здесь.

person Lance McCarthy    schedule 25.04.2014
comment
Это приложение для wp 8.1, и у меня отмечена возможность музыкальной библиотеки. Я извлекаю все файлы из библиотеки и позволяю пользователям выбирать их. Затем я сохраняю пути к файлам, до которых все в порядке. Теперь я хочу получить доступ к этим файлам позже в своем приложении. И да попутно, еще же. - person Aditya; 25.04.2014

Вы можете использовать кеш доступа для хранения доступа к файлам вместо путей. Это позволит вам получить объекты StorageFile, с которыми вы сможете сразу же работать, и поможет в некоторых сценариях, связанных с перемещением файлов.

Чтобы сохранить файл в кэше доступа

 StorageFile file; //Get a file
 string mruToken = Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUsedList.Add(file, "20120716");

Затем вы сохраняете токен где-то. Чтобы вернуть файл из кеша:

 StorageFile file = await Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUsedList.getFileAsync(mruToken);

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

person Adam    schedule 01.05.2014