Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve files from the windows phone (8.1) music library using path names?

I am letting my users select files from the music library. After which I am storing the path of the selected files locally. Now my problem is how do I get access to the files programmatically from these paths? Here are a couple of things I've tried.

Say my pathname is D:\Xyz\abc.mp3

StorageFolder S=KnownFolders.MusicLibrary;

Alternative 1:

StorageFile MyFile=await S.GetFileAsync("abc.mp3"); //File not found error

// I figure this doesn't work cause GetFileAsync method can only get files from the current folder

Alternative 2:

S=await S.GetFolderAsync("Xyz"); //After which I planned to do GetFileAsync. But this also gives a folder not found error.

And Finally I've tried S=await S.GetFolderAsync("D");

Any help as to how I get access to the file or even an alternate way to achieve my goal would be fantastic !

P.S : StorageFile.GetFileFromPathAsync("D:\Xyz\abc.mp3") says I don't have permission to access.

like image 336
Aditya Avatar asked Apr 25 '14 13:04

Aditya


3 Answers

(Answer rebuild to be more clear)

If you had declared in package.appxmanifest file:

  • Music Library capability in Capabilities
  • File Type Association in Declarations (I'm not sure if this is needed if you only access Music Library)

then you will be able to retrieve files from Music Library folder like this:

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);

To sum up you will be able to aceess by KnownFolders.MusicLibrary only to files which are either on Phone or SD card but in Music folder - their paths will be then:

C:\Data\Users\Public\Music\test.mp3 - for Phone

D:\Music\Test\test2.mp3 - for SD card

Remember that accessing by StorageFolder.GetFileAsync() works relative to the StorageFolder (it will also work with full path, see remark below):

The name (or path relative to the current folder) of the file to retrieve.

In this case to get above files you will use filenames like: test.mp3 and Test\test2.mp3.

You won't be able to get other files like D:\xxx.mp3 - it isn't in Music Library - it is on SD card, if you want to access it you will have to do it by KnownFolders.RemovableDevices - when you have added required capabilities, then you should be able to access that via fullpath. But also please remember about the remark:

Do not rely on this property to access a file because some files may not have file-system paths. For example if the file is backed by a URI, or was picked using the file picker, the file is not guaranteed to have a file-system path.

In our discussion tured out that you are using CommonFileQuery.OrderByName to get files. As I've checked there (IMO) might be a little bug - in VS description says that:

Query results for deep queries include all files in all of the subfolders of the folder being queried and sorts them based on the specified metadata.

Running a pice of code:

// 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

has given resuls:

  • in first case 5 files that are in fact in Music folder and its subfolders,
  • in second case - 14 files that are in: Music Library, SD card, and Phone

You can easily look at the Path in debug mode and you will see that some of files in second method has D:\file.mp3 and so on - they aren't in Music Library - so you won't be able to get them by KnownFolders.MusicLibrary. If you want to get them then you will have to use other KnownFolders - in this case SD card:

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
like image 91
Romasz Avatar answered Nov 16 '22 17:11

Romasz


First, make sure you have the proper capabilities set. The error you're getting is what you'd see if you didn't declare the right CAP_ID . Here is a screenshot:

enter image description here

Regarding file paths, depending where the file is stored, you may need to use the double-slash. I had a similar issue, I resolved by using the following approach:

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

You can see the whole process in my SO post here.

like image 41
Lance McCarthy Avatar answered Nov 16 '22 18:11

Lance McCarthy


You will want to use the access cache to store access to the files instead of the paths. This will let you retrieve StorageFile objects that you can work with right away, and will help with some scenarios surrounding files being moved.

To store a file in the access cache

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

You then save the token some where. To get the file back from the cache:

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

Storing just the path opens you up to issues with drive letters changing ect. This ensures that if the file is still available, your app can get it.

like image 1
Adam Avatar answered Nov 16 '22 18:11

Adam