Mobile Zone is brought to you in partnership with:

Den is a DZone Zone Leader and has posted 460 posts at DZone. You can read more from them at their website. View Full User Profile

Flickr API for Windows Phone 7 – Part 6 – Blogs

10.04.2010
| 7512 views |
  • submit to reddit

Yes, Flickr indeed supports blogs. Not directly, but rather by providing an intermediate layer between Flickr and various blogging services (where you can publish pictures from Flickr). The public Flickr API exposes three methods that allow developers to access their blogs:

•    getList – gets the list of blogs associated with the current user
•    getServices – gets the list of available blog services that can be used with Flickr
•    postPhoto – posts a photo to a user  blog

The first two methods are fairly easy to implement – all these do is retrieve that familiar JSON-formatted data listing associated blogs and available services. The last one – that will actually post the photo will require some additional work, but it is not overly complicated either.

Let’s start with getServices. But before I implement the method, I am creating an additional class in the Core folder called Blogs.

This is not a static class – the user will be able to instantiate it. Now, you will need an instance of HelperDelegate once again, since I will be invoking these methods asynchronously and I will need for tasks to complete.

private HelperDelegate helperDelegateInstance;

The actual method is based on the same skeleton as other methods in the application core.

public void GetServiceList(string apiKey, HelperDelegate helperDelegate)
{
    helperDelegateInstance = helperDelegate;

    WebClient client = new WebClient();
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
    string URL = string.Format("http://www.flickr.com/services/rest/?method=flickr.blogs.getServices&api_key={0}&format=json",
            apiKey);

    client.DownloadStringAsync(new Uri(URL));
}

But there is one clear difference – the method doesn’t require authentication. And it doesn’t need a signature – all you have to provide is an API key. This is because the method is not tied to any user-specific data, but rather to the data tied to the core of the Flickr service. There is also an event handler for the WebClient instance that is triggered when the data is downloaded - client_DownloadStringCompleted.

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    LastBlogResult = e.Result;
    helperDelegateInstance();
}

LastBlogResult is a simple string property.

public string LastBlogResult { get; set; }

That’s it for this method. On the test page, try calling this code:

Core.Blogs blogs = new Core.Blogs();
blogs.GetBlogList(apiKey, () =>
    {
        Debug.WriteLine(blogs.LastBlogResult);
    });

apiKey is a string that contains the API key. The final result should resemble something like this:

The getList method on the other side will retrieve the list of blog services associated with the account that is authorized. It requires a signature:

public void GetBlogList(string apiKey, string authToken, string signature, HelperDelegate helperDelegate,string service="")
{
    helperDelegateInstance = helperDelegate;

    WebClient client = new WebClient();
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
    string URL = string.Format("http://www.flickr.com/services/rest/?method=flickr.blogs.getList&api_key={0}&api_sig={1}&auth_token={2}&format=json",
            apiKey,signature,authToken);

    if (service != "")
        URL += "&service=" + service;

    client.DownloadStringAsync(new Uri(URL));
}

The service parameter is optional and will list blogs associated with a specific service ID (e.g. you want to only get the Twitter account). Test it on your experimental page with this:

Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("api_key", apiKey);
param.Add("method","flickr.blogs.getList");
param.Add("auth_token", "AUTHTOKEN");
param.Add("format", "json");

Core.Authentication.GetSignature(param, "SECRET", () =>
{
    txtLog.Text += "\nGetting list of associated blogs...";
    Core.Blogs blogs= new Core.Blogs();

    blogs.GetBlogList(apiKey, "AUTHTOKEN",Core.Authentication.Signature, () =>
    {
        txtLog.Text += "\n" + blogs.LastBlogResult;
    });
});

Here is what you should get:

I only have Twitter associated with my Flickr account, so that’s why I only have Twitter listed. Now let’s try posting a picture to a blog. The method is shown below:

public void PostPhoto(string apiKey, string authToken, string signature, string photoID,
    string title, string description, string blogID, HelperDelegate helperDelegate,
    string blogPassword="",string blogService ="")
{
    helperDelegateInstance = helperDelegate;
    string URL = string.Format(
        "http://www.flickr.com/services/rest/?method=flickr.blogs.postPhoto&api_key={0}&api_sig={1}&auth_token={2}&photo_id={3}&title={4}&description={5}&format=json",
        apiKey, signature, authToken, photoID, title, description);

    if (blogPassword != "")
        URL += "&blog_password=" + blogPassword;
    if (blogService != "")
        URL += "&blog_service=" + blogService;

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
    request.Method = "POST";

    request.BeginGetResponse(asyncCallback =>
    {
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncCallback);
        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
        {
            LastBlogResult = reader.ReadToEnd();
        }
        helperDelegate();
    },null);
}

Now you can see why I said that this part is a bit more complicated. First of all, instead of a WebClient I am using a HttpWebRequest that performs a POST request to the server with the needed parameters. You can also see that there are new parameters included in the method: photoID, title, description and blogID.

photoID is the unique photo identifier. I will be showing how to implement API calls that will request photo IDs later, but for now, open your browser and navigate to a Flickr photo. The ID will be displayed in the address bar:

The title and description parameters are attributes that you will assign to the picture and those will be used in the blog post.

NOTE: When publishing to Twitter, only title will be used. description is still a required parameter, though.

In my case, I will be publishing the picture to Twitter. The blogID is set to the ID I received via getList (I erased my blog ID from the screenshot).

NOTE: You will have to manually authorize your account on Twitter (or any other services) to allow interactions with the Flickr application.

The blog might require a password (especially if you are using a service like Blogger or Wordpress), so there is the optional blogPassword parameter. blogService is an optional parameter as well, specifying the service ID that will be used to publish the picture.

Notice that the calls required to get the response are executed asynchronously and the delegate is called from inside an asynchronous callback.

LastBlogResult is once again used to get the server response. Now you can test this method call on the main page with something like this:

Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("api_key", apiKey);
param.Add("method","flickr.blogs.postPhoto");
param.Add("auth_token", "AUTHTOKEN");
param.Add("format", "json");
param.Add("photo_id", "4706005543");
param.Add("title", "Cat Look");
param.Add("description", "A cat looks at the camera.");
param.Add("blog_id", "BLOGID");

Core.Authentication.GetSignature(param, "SECRET", () =>
{
    txtLog.Text += "\nTrying to post the photo...";
    Core.Blogs blogs= new Core.Blogs();

    blogs.PostPhoto(apiKey, "AUTHTOKEN",Core.Authentication.Signature,"4706005543","Cat Look","A cat looks at the camera.", "BLOGID", () =>
    {
        Dispatcher.BeginInvoke(new Action(() => { txtLog.Text += "\n" + blogs.LastBlogResult; }));
    });
});

You will get a JSON response with 200 : OK if the request was succesful. You will also see your photo published:

Notice that the URL to the picture is shortened automatically and the location of the tweet is automatically set to the location where the photo was taken (consider that when publishing content from Flickr to Twitter).

Instead of attaching the entire modified project, I am simply going to link to the Blogs class - you can download it here.