barbarian meets coding

WebDev, UX & a Pinch of Fantasy

Windows Phone 8 Wiki - Introduction to Windows Phone 8

Welcome to the Introduction to Windows Phone 8 wiki. In this part of the blog I will add introductory content to Windows Phone 8 development, stuff that’s good to remember but one usually ends up forgetting :).

Files and Data

In order to persist data permanently in your windows phone 8 apps you have different possibilities:

  • Installation folder
    • That is, the files contained in the app project
  • Data store reserved for each app in a user’s phone
    • Local folder (Windows 8 API)
    • Isolated storage API (Windows Phone 7)
  • Media library (for media files)
  • Local database

Settings

The Settings store provides a very simple and easy way to store data in our apps. The Settings store allows the user to store key-value pairs that will be persisted to the app’s local folder when an app is closed and which will be recreated on app relaunch. It is recommended for storing simple data so as not to affect the app relaunch experience.

In Windows Phone 8 we use the IsolatedStorageSettings API as depicted below:

1
2
3
4
5
6
7
8
9
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains("amIAwesome"))
{
    settings["amIAwesome"] = "You Bet!";
}
else
{
    settings.Add("amIAwesome", "You Bet!");
}

Files and Folders

Using WP8 APIs you can also create and access files and folders in your app isolated storage (Package.Current.InstalledLocation).

Windows Runtime Storage

These are a series of APIs shared with Windows 8. They reside in the Windows.Storage namespace and can be accessed via the StorageFile and StorageFolder classes.

These two classes provide asynchronous methods and use the TPL library that lets us use the async/await pattern.

1
2
3
4
5
var installFolder = Package.Current.InstalledLocation;

var imagesFolder = await installFolder.GetFolderAsync("Images");
var images = await imagesFolder.GetFilesAsync();
lb.ItemsSource = images;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private async Task CopyToLocalFolderAsync(StorageFile fileToCopy, string folderName)
{
    byte[] buffer;
    var localFolder = ApplicationData.Current.LocalFolder;
    var newFolder = wait LocalFolder.CreateFolderAsync(folderName, Create
    CollisionOptions.OpenIfExists);
    var toFile = await newFolder.CreateFileAsync(fileToCopy.Name, CreateCollisionOptions.ReplaceExisting);
    using (var instream = await fileToCopy.OpenStreamForReadAsync())
    {
        buffer = new byte[instream.length];
        await instream.ReadAsync(buffer, 0, (int)buffer.Length);
    }
    using (var outstream = await toFile.OpenStreamForWriteAsync())
    {
        await outstream.WriteAsync(buffer, 0, (int)buffer.Length);
        await outstream.FlushAsync();
    }


    // note that in order to read and
    // write text, it is much easier to 
    // wrap the input and output streams 
    // with a StreamWriter and a StreamReader.
}

You can use the native SDK command line tools to get access to the isolated storage or the Windows Phone Power Tools which provide a much better experience for exploring the phone isolated storage.

Isolated Storage (Legacy)

towrite

Relational Database

In those cases where we want to store large datases or perform query operations on a set of data, windows phone 8 offers the possibility of using a local SQL CE database (.sdf files in isolated storage or install folder that are private to the app).

We can define, create and access the database using LINQ to SQL.

We create the different tables and columns by using a code first approach using attributes to decorate our domain model.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[Table(Name="Users")]
public class User
{
    [Column(IsPrimaryKey=true)]public int Id {get;set;}
    [Column]public string Name {get;set;}
    private EntitySet<Badge> badges;
    [Association(Storage="badges", ThisKey = "Id", OtherKey = "userId")]
    public EntitySet<Badge> Badges
    {
        get {return badges;}
        set {badges.Assign(value);}
    }
}

[Table(Name="Badges")]
public class Badge
{
    [Column(IsPrimaryKey=true)]public int Id {get;set;}
    [Column]public string Name {get;set;}
    [Column]internal int userId;
    private EntityRef<User> user;
    [Association(Storage = "user", ThisKey="userId", OtherKey = "Id")]
    public User User
    {
        get { return user.Entity;}
        set
        {
            user.Entity = value;
            if (value != null)
            {
                userId = value.userId;
            }
        }
    }
}

We define a data context that will represent the Unit Of Work using the DataContext API and exposing collections of entities through Table<T>.

1
2
3
4
5
6
public class AppDataContext : DataContext
{
    public AppDataContext(string connectionString) : base (connectionString){}

    public Table<User> Users;
}

To access the database at runtime, you will need to first create the database via DataContext.CreateDatabase() and then perform operations using LINQ to SQL (remember to call db.SubmitChanges() to persist changes to the database).

1
2
3
4
5
using (var ctx = new AppDataContext("isostore:/app.sdf"))
{
    if (!ctx.DatabaseExists())
        ctx.CreateDatabase();
}

HTTP Data

You can access web services in your windows phone app via HTTP by using the WebClient for common scenarios or the HttpWebRequest when you need to have more control of the HTTP requests you send to the server. The problem with these APIs are that they work with callbacks although you can wrap the beginning and ending of calls in Tasks to take advantage of the async/await pattern.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void GetData()
{
    var baseUri = new Uri("someBaseUri");
    string uri = "somerelativeUri";

    var webClient = new WebClient();
    webClient.DownloadStringCompleted += WebClient_OnDownloadStringCompleted;
    webClient.DowndloadStringAsync(new Uri(baseUri, uri));
}

private void WebClient_OnDownloadStringCompleted(object sender, DownloadSringCompletedEventArgs e)
{
    if (e.Error != null)
    {
        Deployment.Current.Dispatcher.BeginInvoke(()=>
        {
            MessageBox.Show(e.Error.Message);
        });
    }
    else
    {
        var jsonData = e.Result;
        var list = JsonConvert.DeserializeObject<List<Something>>(jsonData);
        ls.ItemsSource = list;
    }
}

Additionally, you can use the portable HttpClient, an API that is shared with Windows 8 that provides built-in support for asynchronous operations via Tasks. You will need to install this library via NuGet (Microsoft.Net.Http).

1
2
3
4
5
var client = new HttpClient();
client.BaseAddress = baseUri;
var jsonData = await client.GetStringAsync(uri)
var list = JsonConvert.DeserializeObject<List<Something>>(jsonData);
return list;

Windows Phone Integration

Live Tiles

Launchers and Choosers

Lock Screen

References

Comments