1. Oliver Scheer
Senior Technical Evangelist
Microsoft Deutschland
http://the-oliver.com
Files and Storage in
Windows Phone 8
2. • WP7.1IsolatedStorage and
IsolatedStorageSettings APIs
• Local Storage and Isolated Storage
• Windown Phone Runtime
Windows.Storage programming
Agenda
In This Session…
3/18/20142
• Special Folders
• Shared/Media
• Shared/ShellContent
• Shared/Transfers
• Exploring the local folder with ISET
• Using Removable SD cards
3. • Local Database
• No change from WP 7.1
• See
• http://channel9.msdn.com/Series/Mango-Jump-Start/Mango-Jump-Start-08a-
Application-Data-Storage-on-Windows-Phone--Part-1
• http://channel9.msdn.com/Series/Mango-Jump-Start/Mango-Jump-Start-08b-
Application-Data-Storage-on-Windows-Phone-Part-2
• SQLite database (native only)
Not Covered in this Module…
3/18/2014Microsoft confidential3
5. Local Data Storage: Overview
Application
Settings File
App
Application
Files
Package
Manager
Installation
Folder
WP7.1: “App Data”
WP8 Storage
APIs or
WP7 Isolated
Storage APIs
Install
DB
Database file
DB Database
File (r/o)
6. File Type/ API
Installation
Folder
Local Folder Example
Local Database data
context
appdata:/ isostore:/
MyDataContext db = new MyDataContext
("isostore:/mydb.sdf")
Files access using
WP7.1 Isolated
Storage API
not supported
StorageFile and
StorageFolder
APIs
var isf =
IsolatedStorageFile.GetUserStoreForApplication()
File access using
Windows.Storage API
via URIs
ms-appx:///
ms-
appdata:///local/
var file = await
Windows.StorageFile.GetFileFromApplicationUriAsync(
new Uri("ms-appdata:///local/AppConfigSettings.xml"));
File access using
Windows.Storage API
via StorageFolder
references
Windows.
ApplicationModel.
Package.Current.
InstalledLocation
Windows.Storage.
ApplicationData.
Current.
LocalFolder
var localFolder =
Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.StorageFile storageFile =
await localFolder.GetFileAsync("CaptainsLog.store");
3/18/2014Microsoft confidential6
Different Methods For Addressing Storage Locations
7. • Three ways of getting a reference to the same file:
// WP7.1 IsolatedStorage APIs
var isf = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream fs = new IsolatedStorageFileStream("CaptainsLog.store", FileMode.Open, isf));
...
// WP8 Storage APIs using URI
StorageFile storageFile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(
new Uri("ms-appdata:///local/CaptainsLog.store "));
...
// WP8 Storage APIs
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.StorageFile storageFile = await localFolder.GetFileAsync("CaptainsLog.store");
...
WP8 File Access Alternatives
3/18/2014Microsoft confidential7
9. Isolated Storage Classes
• The IsolatedStorage classes are all in the System.IO.IsolatedStorage namespace
• IsolatedStorageFile
• Represents an isolated storage area containing files and directories
• IsolatedFileStream
• Exposes a file stream access to a file stored within isolated storage
• IsolatedStorageSettings
• Dictionary<(Of <(TKey, TValue>)>) that stores key-value pairs
in isolated storage
10. Saving Data
private void saveGameToIsolatedStorage(string message)
{
using (IsolatedStorageFile isf =
IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream rawStream = isf.CreateFile("MyFile.store"))
{
StreamWriter writer = new StreamWriter(rawStream);
writer.WriteLine(message); // save the message
writer.Close();
}
}
}
11. Loading Data
private string loadString()
{
string result = null;
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isf.FileExists("Myfile.store")
{
using (IsolatedStorageFileStream rawStream = isf.OpenFile(filename, System.IO.FileMode.Open))
{
StreamReader reader = new StreamReader(rawStream);
result = reader.ReadLine();
reader.Close();
}
}
}
return result;
}
13. Application Settings
• If you just want to store setting information
• Username = “Fred”
• TextColor = “Green”
• ..you can use the ApplicationSettings object in Isolated Storage
• You use this as you would a dictionary
• You then write the object to persistent storage
14. Saving Data in Settings
• The storage works as a dictionary
• But you have to remember to call Save when you have finished adding keys
void saveString(string message, string name)
{
IsolatedStorageSettings.ApplicationSettings[name] =
message;
IsolatedStorageSettings.ApplicationSettings.Save();
}
15. Loading from Settings
• Test for the key before you try to find it or you will get an exception thrown
1
5
string loadString(string name)
{
if (IsolatedStorageSettings.ApplicationSettings.
Contains(name))
{
return (string)
IsolatedStorageSettings.ApplicationSettings[name];
}
else
return null;
}
18. Windows.Storage Classes
• Windown Phone Runtime storage classes are in the Windows.Storage
namespace
• StorageFolder
• Represents a storage area containing files and directories
• StorageFile
• Represents a file and provides methods for manipulating them
• Not supported on Windows Phone 8:
• ApplicationData.LocalSettings
• Use custom file or IsolatedStorageSettings
19. Saving Data – Using StorageFolder
using System.IO;
using Windows.Storage;
…
private async void saveToLocalFolderAsync(string message)
{
// Get a reference to the Local Folder
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
// Create the file in the local folder, or if it already exists, just open it
StorageFile storageFile = await localFolder.CreateFileAsync("Myfile.store",
CreationCollisionOption.OpenIfExists);
Stream writeStream = await storageFile.OpenStreamForWriteAsync();
using (StreamWriter writer = new StreamWriter(writeStream))
{
await writer.WriteAsync(logData);
}
}
20. Loading Data
using System.IO;
using Windows.Storage;
…
private async string loadStringAsync()
{
string theData = string.Empty;
// Get a reference to the file in the Local Folder
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await localFolder.GetFileAsync(“Myfile.store"));
// Open it and read the contents
Stream readStream = await storageFile.OpenStreamForReadAsync();
using (StreamReader reader = new StreamReader(readStream))
{
theData = await reader.ReadToEndAsync();
}
return theData;
}
21. Accessing Files Using ms-appdata:///local/ or ms-appx:///
// There's no FileExists method in WinRT, so have to try to open it and catch exception instead
StorageFile storageFile = null;
bool fileExists = false;
try
{
// Try to open file using URI
storageFile = await StorageFile.GetFileFromApplicationUriAsync(
new Uri("ms-appdata:///local/Myfile.store"));
fileExists = true;
}
catch (FileNotFoundException)
{
fileExists = false;
}
if (!fileExists)
{
await ApplicationData.Current.LocalFolder.CreateFileAsync("Myfile.store",
CreationCollisionOption.FailIfExists);
}
...
22. • Windows Phone 8 implementation of Windows.Storage is a subset of Windows 8 WinRT
• All data storage uses the LocalFolder (equivalent to WP7.1 IsolatedStorage)
• Not Supported:
• Roaming Data Store: ApplicationData.Current.RoamingFolder
• Temporary Data Store: ApplicationData.Current.TemporaryFolder
• Local Settings: ApplicationData.Current.LocalSettings
• Roaming Settings: ApplicationData.Current.RoamingSettings
Windows Phone 8 – Windows 8 Compatibility
Only LocalFolder Supported
3/18/201422
23. • In Windows 8, you can programmatically load an Image file that you have included in your
app package into a XAML <Image> element using the URI syntax, as follows:
RecipeImage.Source = new System.Windows.Media.Imaging.BitmapImage(
new Uri(@"ms-appx:///Images/french/French_1_600_C.jpg", UriKind.RelativeOrAbsolute));
• In Windows Phone 8, you cannot use the URI syntax in this way. Continue to use the
relative path to the image, as in Windows Phone OS 7.1:
RecipeImage.Source =
new System.Windows.Media.Imaging.BitmapImage("/Images/french/French_1_600_C.jpg");
Windows Phone 8 – Windows 8 Compatibility
Programmatically Accessing Image Files
3/18/201423
26. Local Folder
• All read-write I/O operations
restricted to local folder
• Create a files and folder structure
hierarchy
• Use Isolated Settings storage to
store application settings
27. Reserved Folders
• In addition to general data storage, the local folder
is used for the following special-use scenarios:
• Shared/Media - Apps can use this folder to
display album art in the Universal Volume Control
(UVC) while playing background audio
• Shared/ShellContent - Background images for
Tiles can be stored in isolated storage, but must
be located in this folder or a subfolder of it
• Shared/Transfers – Storage area used by the
Background File Transfer service
3/18/201427
29. Data Serialization
Data persistence and the app lifecycle
• App Launch
• App being dormant/tombstoned
• App being reactivated
• App being terminated
Not running
Launching
Running
Deactivated
/Closing
30. Why Serialize?
• Serializers write the properties of a collection of
objects into a file so they can be stored in persistent
storage
• Deserializers reverse this: read data out of a file and
use it to ‘re-hydrate’ a collection of in-memory
objects
• Many different serializers are available:
• XmlSerializer
• DataContractSerializer
• DataContractJsonSerializer
• Third party…
3/18/201430
31. Serialization using DataContractSerializer
public class MyDataSerializer<TheDataType>
{
public static async Task SaveObjectsAsync(TheDataType sourceData, String targetFileName)
{
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
targetFileName, CreationCollisionOption.ReplaceExisting);
var outStream = await file.OpenStreamForWriteAsync();
DataContractSerializer serializer = new DataContractSerializer(typeof(TheDataType));
serializer.WriteObject(outStream, sourceData);
await outStream.FlushAsync();
outStream.Close();
}
...
}
List<MyDataObjects> myObjects = ...
await MyDataSerializer<List<MyDataObjects>>.SaveObjectsAsync(myObjects, "MySerializedObjects.xml");
• To use:
32. Deserialization using DataContractSerializer
public class MyDataSerializer<TheDataType>
{
public static async Task<TheDataType> RestoreObjectsAsync(string fileName)
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
var inStream = await file.OpenStreamForReadAsync();
// Deserialize the objects.
DataContractSerializer serializer =
new DataContractSerializer(typeof(TheDataType));
TheDataType data = (TheDataType)serializer.ReadObject(inStream);
inStream.Close();
return data;
}
...
}
List<MyDataObjects> myObjects
= await MyDataSerializer<List<MyDataObjects>>.RestoreObjectsAsync("MySerializedObjects.xml");
• To use:
35. Isolated Storage Explorer
• Isolated Storage Explorer is a command-line tool you use to list, copy, and replace files and
directories in Isolated Storage
• Can be used on emulator or device
• Can be used for applications that target Windows Phone OS 7.0, 7.1 and 8.0
• at Program Files (x86)Microsoft SDKsWindows Phonev8.0ToolsIsolatedStorageExplorerTool
• Syntax:
ISETool.exe <ts|rs|dir[:device-folder]> <xd|de> <Product GUID> [<desktop-path>]
ts–Takesnapshot
rs–Restoresnapshot
dir–Liststhefilesor
directories
xd–targettheemulator
de–targetdevice
Guid–ProductIDfromthe
WPAppManifest.xmlfilefortheapp
Desktop-path–directoryonyour
computerwhereisolatedstoragefilesare
writtentoorcopiedfrom
38. • Windows Phone 8 devices support SD cards
• App can read files stored on a storage card
• Must declare the ID_CAP_REMOVABLE_STORAGE capability in the application
manifest file
• Cannot write files - Access is Read Only
• Can only access file types for which your app has registered a file association in
WMAppManifest.xml
External Storage (SD Card)
3/18/2014
39. • You can only open files for which you have declared a File Association in WMAppManifest.xml
• Edit WMAppManifest.xml using the XML editor, not the Manifest editor
• Add a FileTypeAssociation element inside the Extensions element
• The Extensions element must follow immediately after the Tokens element
• Note that the ContentType attribute on the FileType element is required
<Extensions>
<FileTypeAssociation Name=“foo" TaskID="_default" NavUriFragment="fileToken=%s">
<SupportedFileTypes>
<FileType ContentType="application/foo">.foo</FileType>
</SupportedFileTypes>
</FileTypeAssociation>
</Extensions>
Declare a File Association to WMAppManifest.xml
3/18/2014Microsoft confidential39
40. API Description
ExternalStorageDevice Represents an SD card. Use the ExternalStorageDeviceExternalStorageID()
property to uniquely identify a card.
ExternalStorage.GetExtern
alStorageDevicesAsync()
Returns a collection of SD cards that are inserted in the phone. This
collection will contain no more than one SD card.
ExternalStorageFolder Represents a folder on the SD card. Use the ExternalStorageFolderPath()
property to access the folder later.
ExternalStorageFile Represents a file on the SD card. Use the ExternalStorageFilePath()
property to access the file later.
ExternalStorageDeviceGet
FileAsync() and
ExternalStorageDeviceGet
FolderAsync()
Obtain a file or folder directly from the external storage device object.
3/18/2014Microsoft confidential40
External Storage APIs
42. Quota Management
• There are no quotas on Windows Phone!
• Applications must make careful use of space
• Use only is necessary
• Be transparent about storage usage
• Manage application data
• Delete temporary data and files when no longer required
• Consider synchronizing or archiving data to the cloud to reduce device storage
42
43. Serialization and Threads
• If your status information is a complex object you can easily save the object by serializing
it
• Serialization may slow down the saving and loading of data
• You should consider the use of threading in this situation
• Perform your loading and saving on a separate thread so that the application stays
responsive
43