共用方式為


Accessing Photo Albums in Facebook

Hello everyone and welcome to a new episode of the Facebook integration for Windows Store App series. Christophe Nasarre, a French Premier Field Engineer is explaining how to list the photo albums of a Facebook profile. He will detail the photo enumeration and the paging mechanism in the next episode.


For your convenience, here’s the video timeline:

[0:20] App demo to view Facebook albums and photos

[1:40] Facebook documentation for Albums

[2:05] Changes to the LoginAsync code for user_photo permission

[2:26] Graph Explorer session for Albums query and corresponding Json response

[3:57] C# mapping for Albums

[5:30] Code to get the Albums and Json parsing tricks

[8:12] C# pattern to asynchronously update the data bound UI

[10:12] details of asynchronous cover photo album retrieval

 

Preview of the expected result

Here is what I want to achieve:

image

When the user clicks the Albums button, its existing Facebook photo albums are listed with their name and cover picture. When an album is selected, its photos are listed. Facebook is returning only a subset of photos and the user can navigate between chunks with the Previous/Next buttons.

Exploring the album Facebook API

As explained in the previous episode, the first step is always to go to the Facebook documentation and start a session in the Graph Explorer to figure out how to get the information you need. In this case, I’m interested in the Album endpoint

image

The required permissions are “user_photos

image

I will have to add it to the login code in the application

var loginUrl = FbClient.GetLoginUrl(new

{

    client_id = FacebookAppID,

    redirect_uri = WindowsStoreAppSID,

   

    // MS-CN: adding access to the required features

    // user_photos: list of albums + their pictures

    scope = "user_photos",// Facebook permissions

 

    display = "popup",

    response_type = "token"

});

So, open a Graph Explorer session and select the right permission

image

And submit a GET /me/albums query

image

The Json result is a list of albums under a “data” root node

image

Click on the id value of the first album to get an easy to read view of the field describing an album

image

For my App, I’m only interested in the name, count, privacy, type and the cover_photo fields. Well… I should not forget the id because this is how I’ll be able to get its photos!

The C# side of the story

I’m storing these album descriptions into a collection of Album C# class that is bound to a ListView

image

It is important to note that only the id field is mandatory, the others might be empty; i.e. not defined in the Json. This is why it is so important to always check if a field is present before trying to get its value. Here is the stripped down code for the GetAlbumAsync method in charge of sending the GET request and of parsing the return Json:

List albums = new List();

 

dynamic albumsTaskResult = await FbClient.GetTaskAsync("/me/albums");

var result = (IDictionary<string, object>)albumsTaskResult;

var data = (IEnumerable<object>)result["data"];

foreach (var item in data)

{

    var album = (IDictionary<string, object>)item;

    // now you can retrieve data from the dictionary above

 

    string id = (string)album["id"];

    string name = string.Empty;

    string coverPhotoId = string.Empty;

    int count = 0;

    string privacy = string.Empty;

    string type = string.Empty;

 

    if (album.ContainsKey("name"))

        name = (string)album["name"];

    if (album.ContainsKey("cover_photo"))

        coverPhotoId = (string)album["cover_photo"];

    if (album.ContainsKey("count"))

        count = Convert.ToInt32(album["count"]);

    if (album.ContainsKey("privacy"))

        privacy = (string)album["privacy"];

    if (album.ContainsKey("type"))

        type = (string)album["type"];

 

    Album newAlbum = newAlbum(id, name)

    {

        Count = count,

        CoverPhotoId = coverPhotoId,

        Privacy = privacy,

        Type = type

    };

    albums.Add(newAlbum);

}

As you can see, all albums are retrieved in one asynchronous call; not including the cover photo itself: just its id is stored in the CoverPhotoId property. Each cover photo will be asynchronously fetched in two steps. The first one is to get its URI

async private void albumBT_Click(object sender, RoutedEventArgs e)

{

    List<Album> albums = await _fbHelper.GetAlbumsAsync();

    if (albums == null)

        return;

 

    // create a listview and change its data source to the list of albums

    gvAlbums.ItemsSource = albums;

 

    foreach (var album in albums)

    {

        // get the uri

        Uri coverUri = await _fbHelper.LoadAlbumCoverPhotoUriAsync(album.CoverPhotoId);

        if (coverUri == null)

            continue; // some albums might not have cover photo

 

        // get the corresponding picture

        album.CoverPhotoImage = newBitmapImage(coverUri);

    }

}

And the second step is done implicitly for you by the BitmapImage which will download asynchronously the bits of the picture: this is how the cover photos are appearing magically after the name of all albums are visible on the screen.

Note that the first step to get the URI requires a call to the Facebook SDK just passing the id of the cover photo

dynamic albumsTaskResult = await FbClient.GetTaskAsync("/" + coverPhotoId);

var result = (IDictionary<string, object>)albumsTaskResult;

var pictureUri = (string)result["source"]; // the "picture" entry is a thumbnail

if (pictureUri != null)

    uri = newUri(pictureUri);

The string URI is the value of the source key in the returned Json and the picture key is just a thumbnail that might be too small for your needs.

image

The next episode will cover how to retrieve the photos of an album and how to handle pagination when a large number of photos are available.

Happy Coding!