Files in UWP
Quite important peace of SoSmartTv project is reading and playing video files. Let's see how to handle basic input/output operations in Universal applications.
Basic IO handlers
In UWP all important IO related classes exist in Windows.Storage namespace. You can still take advantage of standard FileInfo, DirectoryInfo and couple other classes that are accessible through System.IO however they are not first IO citizens in UWP world. To operate on file structures you have to get familiar with three classes: StorageFile and StorageFolder that, as you have probably guessed, provides file and folder handlers, and FileIO that allows you to interact with file content. Below you can find simple example of how to reach a file in certain directory and write to it.
StorageFolder storageFolder = ApplicationData .Current.LocalFolder;
StorageFile sampleFile = await storageFolder.GetFileAsync("sample.txt" );
await FileIO.WriteTextAsync(sampleFile, "Swift as a shadow"); |
Unauthorized access?
Accessing directories on our machine in UWP is not so obvious. Universal platform policy drastically restricts file access directly from code base level. What does it mean? Access to not common directory ends with UnauthorizedAccessException, (like below GetFileAsync example).
StorageFile sampleFile = await storageFolder.GetFileAsync("D:\Custom Folder\sample.txt" ); |
What can we do with it? We have two options, we can use directories that are authorized by default or we can bring into play UI file/directory pickers that require explicit interaction with user. Let's start with first option.
Accessible directories
First directory, already mentioned in example, can be provided by ApplicationData.Current. ApplicationData instance provides access to couple directories tightly related to Universal application that you can find under:
C:\Users\<>UserName>\AppData\Local\Packages\<>ApplicationPackageName>\
- ApplicationData.Current.LocalFolder - data that exists on the current device and is backed up in the cloud
- ApplicationData.Current.RoamingFolder - data that exists on all devices on which the user has installed the app
- ApplicationData.Current.LocalCacheFolder - data that exists on current device
- ApplicationData.Current.TemporaryFolder - data that can be removed by system anytime when app is not running
- ApplicationData.Current.SharedLocalFolder - data that can be shared between many Universal app's on the same device. this feature is by default disabled and has to be enable in machine register.
Next directory that may appeal to you is application package installation path provided by Windows.ApplicationModel.Package.Current.InstalledLocation. This directory coincide with root path of application - so maybe it's not so useful but always good to know (as you can see on the below example you can reach "sample_local.txt" file in two different ways).
StorageFolderfolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFile file1 = await folder.GetFileAsync( "sample_local.txt");
StorageFile file2 = await StorageFile.GetFileFromPathAsync("sample_local.txt" ); |
Last and most useful set of directories can be found under KnownFolders. KnowFolders provides access to common locations that contain user content. Among others you can find such locations like DocumentLibrary, VideoLibrary, MusicLibrary, RemoveableDevices, HomeGroup, etc. - full list that contains also folders specific for different device types you can find here. There is one thing that you have to be aware of if you try to use KnownFolders, you have to specify access capability to given folder in app manifest (Package.appxmanifest).
Pick the file from UI
If predefined directories doesn't satisfy your needs and you want to reach a file outside of them you have to use FileOpenPicker/FileSavePicker or FolderPicker from Windows.Storage.Pickers namespace. Usage of pickers results with display of nice window presented below.
Fortunately UWP delivers mechanism that allows to remember once provided paths. In this way next time (even if application was restarted) we can access path from code without explicit interaction with user and risk of facing access denied error. The list of 'accessed' paths is available under StorageApplicationPermissions.FutureAccessList - it can hold up to 1000 items, both folders and files. The platform never removes items from FutureAccessList, so when the limit is reached you cannot add more items until you remove them manually to make room. Below you can check sample code that demonstrate how to use file picker and FutureAccessList
var folderPicker = new FolderPicker();
StorageFolder folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
StorageApplicationPermissions.FutureAccessList.Add(folder);
} |
Cheers!