Как да извлека файлове от музикалната библиотека на 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");

Всяка помощ за това как да получа достъп до файла или дори алтернативен начин за постигане на целта си би била фантастична!

P.S: 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 в Декларации (не съм сигурен дали това е необходимо, ако имате достъп само до музикалната библиотека)

тогава ще можете да извличате файлове от папка 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
Можете ли да ми кажете как изглежда вашият път за item[1]? - person Aditya; 25.04.2014
comment
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 изисква възможност за преместване. Благодаря за забележката. - person Romasz; 24.06.2014
comment
@Romasz: Исках да знам как актуализирате списъка, когато потребителят промени съдържанието в своята музикална библиотека. Проверявате ли всеки път, когато приложението се отваря, като правите данните постоянни, което отнема много време, или се опитвате да го правите на заден план? - person AbsoluteSith; 12.04.2015
comment
@AbsoluteSith За сега нямам такава нужда. Няма налично събитие, което да ви помогне. Мисля, че най-добре би било да предоставите на потребителя бутон като „синхронизиране“ или да го направите по някакъв начин във фонов режим с работещ индикатор, който информира потребителя, че нещо се случва. - person Romasz; 12.04.2015
comment
@Romasz : Благодаря за помощта, ще го проверя. - person AbsoluteSith; 12.04.2015

Първо се уверете, че сте задали правилните възможности. Грешката, която получавате, е това, което ще видите, ако не сте декларирали правилния CAP_ID. Ето екранна снимка:

въведете описание на изображението тук

По отношение на файловите пътища, в зависимост от това къде се съхранява файлът, може да се наложи да използвате двойна наклонена черта. Имах подобен проблем, разреших го, като използвах следния подход:

"isostore:shared\\folderName\\NameOfFile.mp3"

Можете да видите целия процес в моят SO пост тук.

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