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.
(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:
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
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:
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With