Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Windows Phone 8 - 4 Files and Storage
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/17/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/17/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/17/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/17/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/17/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/17/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/17/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/17/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/17/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/17/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/17/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
Programming persistent file storage in Windows Phone 8 is one of those areas where managed code developers have two choices: use the Windows Phone OS 7.1 Isolated Storage APIs, or to use the Windows Phone Runtime Windows.Storage APIs. In this module we will take a look at both techniques.We’ll also look at the reserved folders, exploring the file storage area with the Isolated Storage Explorer Tool and how a Windows Phone 8 app can read files from a removable micro SD card.
We don’t cover the Local Database APIs in this module. The functionality there is the same as in Windows Phone OS 7.1, and you can watch video training sessions at the URLs shown. We also do not cover the Sqlite database which is an open source database that is available for native code developers on Windows Phone 8.
Persistent Storage in Windows Phone 8First, let’s get an introduction to the persistent storage available on Windows Phone 8 and the naming you need to use to access it.
Local Data Storage: OverviewFirst thing to point out is that each app actually has two separate locations on the phone where files and sub-directories can be stored.Firstly, there’s the Installation Folder (previously known as the AppData folder on Windows Phone OS 7.1). This where the contents of your XAP is exploded on installation and is where your content you’ve included in the project, such as images, XML files or read-only pre-configured databases.Everything in there is Read Only, and when you install an app update, everything in there is blown away and replaced with the new contents of your XAP.Secondly, there is the Local Folder (previously known under Windows Phone OS 7.1 as Isolated Storage), which is the sandboxed area of persistent storage on the phone where you can use File System APIs to store files and folders. Everything in there is read/writeable. Whenever an app creates new writeable files, they are created in the Local Folder, which is maintained on an app update so that any existing data in there is not destroyed.
This table is a ‘quick reference’ guide on how to name files in the different places.There’s an unfortunate naming confusion when dealing with database files. On Windows Phone OS 7.1, and the URI naming scheme usedto allow you to identify the root folder when specifying the path to a database located in what was then called Isolated Storage or in the installation folder which was known then as ‘App Data’ begins with isostore:/ and appdata:/ respectivelyisostore:/{folder}/filename.ext – located in IsolatedStorageappdata:/{folder}/filename.ext – located in the AppData folderUnfortunately, in Windows Phone 8, naming conventions have changed to align with Windows 8 usage, so when using a URI naming scheme to access files in the Local Folder and the Installation Folder, you use ms-appx:/// and ms-appdata:///local/ respectively – and now ‘appdata’ refers not to the installation folder, but the local folder!Notice that with the Windows Phone Runtime APIs, you can refer to the folders using URIs or by using the Windows.ApplicationModel.Package.Current.InstalledLocation and Windows.Storage.ApplicationData.Current.LocalFolder static properties which return you a StorageFolder object pointing at the primary storage locations.
All these different APIs and naming schemes means that there are three different ways of getting a reference to the exact same file. The top code snippet shown uses the Isolated Storage APIs to open a file in the local folder called CaptainsLog.store. The second snippet does the same thing but uses the Windows Phone Runtime APIs and the URI naming scheme. The third snippet also uses the Windows Phone Runtime APIs, but this time uses the Windows.Storage.ApplicationData.Current.LocalFolder static property to get a StorageFolder object referencing the local folder.
Storing Data in Isolated Storage In this section, we will cover storing data in files in isolated Storage using the Windows Phone OS 7.1 Isolated Storage APIs.
Isolated Storage ClassesThese are the key classes you will be working with to work with files and settings in isolated storage.
Saving dataThe slide shows how simple it is to create a file in isolated storage and to write a string into the file.Get a reference to the IsolatedStorageFile object by calling the static IsolatedStorageFile.GetUserStoreForApplication() method.IsolatedStorageFile has a number of useful methods for manipulating files, such as CreateFile() shown here, or OpenFile(). These methods return an IsolatedStorageFileStream object.Use the IsolatedStorageFileStream object to read and write to the file, using objects such as a StreamWriter or a StreamReader.It is a good idea to use the using statement to ensure that these objects are closed and disposed properly.
Loading dataThis slide shows the reverse operation, to read the string out of the file.The sequence is very similar, although this code snippet shows the use of the IsolatedStorageFile.FileExists() method – similar methods exist for testing for the existence of directories.Here, IsolatedStorageFileStream.OpenFile() is used to open a stream to the file, and a StreamReader is used to read the data in the file.
For demonstration notes please look in the “Demonstration” folder and open the corresponding Word document.
Application SettingsThe Windows Phone SDK offers the IsolatedStorageSettings API as a convenience to developers as it allows saving of simple settings data as key/value pairs in a dictionary which is persisted in isolated storage.Note however, that usage of this class is not recommended to communicate program settings between the foreground application and a background agent. The class is not designed for shared access from a foreground app and its Background Agent. To support this, you should use a custom file to store settings and protect access by using a Mutex (see the Background Agents module for more information on using a Mutex to ensure that a process has sole access to a file resource).
Saving data in settingsYou set values just as in any other key/value dictionary. The IsolatedStorageSettings.ApplicationSettings property is static and exposes the settings dictionary. You then just use:IsolatedStorageSettings.ApplicationSettings[key] in C#IsolatedStorageSettings.ApplicationSettings(key) in VBto get or set values in the dictionary.You must remember to call IsolatedStorageSettings.ApplicationSettings.Save() to save the updated dictionary to isolated storage.
Loading from settingsYou can use the IsolatedStorageSettings.ApplicationSettings.Contains(key) method to test whether the settings dictionary contains a key value. This is better than to just try to get a value and then catching the exception that is thrown if the key value is not present.
For demonstration notes please look in the “Demonstration” folder and open the corresponding Word document.
Now let’s look at doing the same thing using the Windows Phone Runtime APIs.
Isolated Storage ClassesThese are the key classes in the Windows.Storage namespaces you will be working with to work with files in the local folder.The Windows.Storage implementation in Windows Phone is a subset of that on Windows 8. One difference is that there is no ApplicationData.LocalSettings class on Windows Phone to store user settings. You will have to either use the IsolatedStorageSettingsAPI that we just looked at, or create a custom solution storing your own settings to a file.
First step when using the Windows.Storage APIs is to get a StorageFolder object referencing the folder you want to work with. Here we use the Windows.Storage.ApplicationData.Current.LocalFolder static property to get a reference to the local folder.Once you have your StorageFolder instance, there are a bunch of methods you can call on that such as CreateFileAsync (as shown here) or others such as CreateFolderAsync, GetFileAsync and GetFolderAsync. In this sample, we use CreateFileAsync along with the CreationCollisionOption.OpenIfExists option to open an existing file if it exists, and if not to create it.CreateFileAsync (and GetFileAsync) return you a StorageFile instance that you can use to access the file. Here we call its OpenStreamForWriteAsync method to open a writeable stream, which we then wrap in a StreamWriter which we use to write text to the file.The code on this slide actually achieves exactly the same thing that we saw using the IsolatedStorage APIs a few slides back.
Loading dataThis slide shows the reverse operation, to read the string out of the file.The sequence is very similar, although note the use of the GetFileAsync()method – this method tests for existence of a file and returns a StorageFile instance referencing the file. If the file does not exists it throws a FileNotFoundException.Here, we use StorageFile.OpenStreamForReadAsynctoopen a readable stream to the file, and a StreamReader is used to read the data in the file. Note that OpenStreamForReadAsync is an extension method; you need to add a using System.IO; to access it.
As an alternative to using the Windows.Storage.ApplicationData.Current.LocalFolder and Windows.ApplicationModel.Package.Current.InstalledLocation static properties t get StorageFolder references to the local folder and the installation folder respectively, you can use the StorageFile.GetFileFromApplicationUriAsync static method instead, specifying the file location using either a Uri beginning ms-appdata:///local/ for the local folder, or ms-appx:/// for the installation folder.Note that you must always use the full ms-appdata:///local/ path to refer to the local folder.This snippet illustrates one other interesting characteristic of the Windows.Storage APIs: there is no FileExists method, so to find out if a file is present you must call the StorageFolder instance method GetFileAsync or the static method GetFileFromApplicationUriAsync and catch the FileNotFoundException that will be thrown if the target does not exist.
The Windows.Storage API implemented in Windows Phone is a subset of that implemented on Windows 8.Most routine file and folder access operations are exactly the same, but the roaming data folder and roaming settings API is not supported on Windows Phone, nor is the temporary data store.As already called out on an earlier topic, there is no ApplicationData.LocalSettings class on Windows Phone to store user settings. You will have to either use the IsolatedStorageSettingsAPI that we looked at previously, or create a custom solution storing your own settings to a file.
One other difference between Windows Phone and Windows 8 we can call out:On Windows 8, you can create a BitmapImage object for an image that you have included as content in your project by using the ms-appx:/// URI syntax to refer to the image file. On Windows Phone, this doesn’t work. The workaround is simple though: simply refer to the image file using a direct path rather than to try to use a URI.
For demonstration notes please look in the “Demonstration” folder and open the corresponding Word document.
All read-writeable file I/O operations in a Windows Phone application take place in the local folder, or in a sub-folder you create below there. This area is sandboxed and private to your application It is not possible to have a common storage area where different applications can read and write to the same files. There are new APIs in Windows Phone 8 that allows one application to create a custom file and to send it to another app, launching it in the process – we will cover that in a later module.Within the local folder, you can create files and folders, just the same as persistent storage to a drive in desktop windows.
You can create whatever sub-folders you want.However, the Shared sub-folder has a special purpose and may be used by certain system APIs that you might call for the following purposes:In the shared/media folder you can save album art images that may be displayed by the shell on the lock screen and in the phones Universal Volume Control if you app uses the Background Audio APIs.The shared/ShelllContent folder is where you can store images to be used on tiles (as distinct from static images that you include as content in your project which will be in the installation folder). You might have pulled these images down from the server or created them on the fly using a WriteableBitmap object. When background agents or the foreground application use APIs to change tile images, these images must be in this folder.Shared/Transfers is where files that you fetch or files that you send using the Background File Transfer service (covered in the background processing module) are stored.
A brief explanation on data serialization and deserialization
Data SerializationIn the earlier demos in this module, we already encountered data persistence and its importance within the application lifecycle. The demos used a very simple string read and write for data persistence, but of course in any real app, we will probably be dealing with collections of in-memory objects that our app uses to operate.Data persistence needs to occur at different parts of the app lifecycle. When an app closes or is deactivated we need to save the state of our in-memory objects into a file in persistent storage. When an app restarts, it needs to read the data from the file and to turn it back into in-memory objects.The process of copying the state of a collection of objects into a file is called serialization, and the reverse process is called deserialization.
A serializer object writes the data of a collection of in-memory objects into XML, JSON or some other format that can be stored in a file in the local folder. When an app restarts, it needs to deserialize the objects, which is the process of using a serializer object in reverse to read data from a serialized form from a file or stream and to turn it back into in-memory objects.There are many different Serializer classes you can choose for this task, including the XmlSerializer, DataContractSerializer,DataContractJsonSerializer and others including popular 3rd party libraries such as JSON.NET.We will shortly show a demo that uses serializers instead of the simple string read/write that we have covered so far.
Serializing dataThe slide shows a general purpose utility method you can use to serialize any object – a single object or a collection object such as an ObservableCollection<T>into a file.The code to call it is shown at the foot of the slide: simply call SaveObjectsAsync passing as parameters the object or object collection to save and the name of the file.Inside the method, it uses the DataContractSerializer. To serialize data using this object, you just new it up passing the type of the objects to be serialized in the constructor, and then call its WriteObject method, passing the output stream to the file, and the objects to serialize.
Here’s the reverse operation.Again, the calling code is shown at the bottom. Just call RestoreObjectsAsync specifying the name of the file.Inside the RestoreObjectsAsync implementation, you again new up a DataContractSerializer instance passing the type of the objects, then call its ReadObject method passing the stream into the file, and casting the result to the required type.
For demonstration notes please look in the “Demonstration” folder and open the corresponding Word document.
Tools: Isolated Storage ExplorerThis section describes how to use a new tool shipped with the Windows Phone 8.0 SDK that allows you to examine the contents of isolated storage on a developer unlocked phone or an emulator.
Isolated Storage Explorer ExampleThis slide simply shows an example of using the tool to list a directory of the files in the isolated storage of a particular application.There are a number of open source tools that implement a GUI to this tool. See:http://wptools.codeplex.com/http://isostorespy.codeplex.com/
One new feature in Windows Phone 8.0 is the ability for an application to read files from a storage card.This feature is targeted at enabling side-loading of large app data files, such as maps or large data sets.
Windows Phone 8 devices may support the use of microSD cards. Implementation is up to the OEM so not all phones will support this.An application can read files from an SD card. The ID_CAP_REMOVABLE_STORAGE capability is required for this.Direct access to the SD card is read-only and is limited to file types for which your app has registered to handle with a file association.
You register a file association by adding the following XML to the WMAppManifest.xml file. You cannot add this using the Manifest Editor GUI, you must edit the file using the XML editor.Each of the elements is described in the following table.Extensions - Must follow the Tokens element.FileTypeAssociation -Describes a file association. You can register a maximum of 20 file associations. The Name attribute is required, but you choose your own friendly name. Specify the TaskID and NavUriFragment elements as shown.SupportedFileTypes - Lists all file extensions that are associated with the file type.FileType - Lists the file extension that is associated with the file type, including the period (‘.’). The ContentType attribute in the format application/extension is required.
The full set of APIs you use with external storage is very similar to the Windows.StorageStorageFolder and StorageFile APIs, with the addition of the ExternalStorage.GetExternalStorageDevicesAsync()method to return the collection of SD cards in the device – note that this will return at most one storage card, represented by an ExternalStorageDevice instance
This section gives some general advice on best practices with persistent data storage.
Windows Phone applications do not have a limit on the quota for storage on disk. It is up to you as an application developer to “do the right thing” and be a good citizen on your users’ device.When a Windows Phone has only 10% of storage space remaining, the user will receive a notification of this status. They can then perform actions such as deleting pictures, music, and applications to create the necessary storage space. However, this is not a favorable option from a user’s perspective.If your application has large data storage needs, consider whether you can store some of that data in a cloud service. Alternatively, if the data storage requirements of your application will grow based on user choices, you should expose the size that is taken up by each choice they have made in a settings page of your application and give the user an option to delete data. This allows the user to make a more informed decision about what to select for deletion. However, this option is more relevant for unstructured data such as files as opposed to structured data. Examples of structured data include a weather application with a list of cities, or a shopping list. If the size of the structured data such as a database can increase over time, you should find a way to communicate this to the user.
As mentioned earlier in this module, if you are desterilizing data on application launch or when being reactivated from being tombstoned, or indeed at any other time, this can take time if the data set is large. If you are using a database and are selecting a large collection of objects from it, this too can take time.Consider performing these operations on a background thread so that you do not tie up the UI thread. The UI thread also has to respond to user input and gestures and has to execute most of your application code, so if you can use other threads for some operations, the user experience will be improved. Programming background threads can be tricky, so consider using the Task object and the new async/await mechanisms which makes this very much easier.