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 15 – Photos

10.22.2010
| 5675 views |
  • submit to reddit

This is probably the most important part and at the same time – the most massive, since it is generally the biggest class in the whole Flickr API. Due to the very similar nature of the methods used (really similar to the method implementations I described in the previous articles from this series), I decided not to post code for every single method but rather describe the class as a whole and my implementation of some method calls that might be of interest.

First of all, the Photos class in my implementation has the following methods present:

•    AddTags
•    Delete
•    GetAllContexts
•    GetContactsPhotos
•    GetContactsPublicPhotos
•    GetContext
•    GetCounts
•    GetExif
•    GetFavorites
•    GetInfo
•    GetNotInSet
•    GetPerms
•    GetRecent
•    GetSizes
•    GetUntagged
•    GetWithGeoData
•    GetWithoutGeoData
•    RecentlyUpdated
•    RemoveTag
•    Search
•    SetContentType
•    SetDates
•    SetMeta
•    SetPerms
•    SetSafetyLevel
•    SetTags

All these methods return JSON-formatted data, as expected. One thing to remember here is that the class is not static. The user might want to run specific operations simultaneously and then retrieve the results for each of them – that obviously won’t be possible in a static class.

Each single method here requires a HelperDelegate instance passed. The thing is – you can always pass an anonymous delegate. This way, you will only execute a specific set of actions when the final result for your request is received. The actual response is stored in a string property called PhotoResult, that is set only when the client_DownloadStringCompleted is fired. One important thing here is the fact that invalid responses or responses notifying you of any misplaced/missed parameters will still be returned, therefore if there is a response this doesn’t mean that the method executed the API call successfully.

I’ve also created a set of enums to be used inside the class:

public enum HasAccess
{
    Nobody = 0,
    FriendsAndFamily=1,
    Contacts = 2,
    Everybody = 3
}

public enum Content
{
    Photo = 1,
    Screenshot = 2,
    Other = 3
}

public enum Units
{
    Mi,
    Km
}

public enum GeoContext
{
    Everywhere,
    NotDefined,
    Indoors,
    Outdoors
}

public enum HasGeo
{
    Undefined,
    True,
    False
}

public enum Contacts
{
    All,
    FriendsAndFamily
}

public enum TagMode
{
    Any,
    All
}

public enum Sort
{
    Undefined,
    DatePostedAsc,
    DatePostedDesc,
    DateTakenAsc,
    DateTakenDesc,
    InterestingnessAsc,
    InterestingnessDesc
}

public enum SafetyLevel
{
    Undefined = 0,
    Safe = 1,
    Moderate = 2,
    Restricted = 3
}

public enum PrivacyFilter
{
    Undefined = 0,
    Public = 1,
    PrivateVisibleToFriends = 2,
    PrivateVisibleToFamily = 3,
    PrivateVisibleToBoth = 4,
    CompletelyPrivate = 5
}

public enum Media
{
    All,
    Audio,
    Video
}

public enum ContentType
{
    Undefined = 0,
    Photos = 1,
    Screenshots = 2,
    Other = 3,
    PhotosAndScreenshots = 4,
    ScreenshotsAndOther = 5,
    PhotosAndOther = 6,
    All = 7
}

Some of them are used to pass string values (e.g. Media), others are used for integer values that later on will be converted to strings (e.g. ContentType). Now someone might think – why use enums when the user himself can enter the values needed, especially when it comes to integer. The reasoning here is simple. If there is no enum, the user has to guess what values to use or dig through the API documentation to find the parameter requirements for a specific method. With the help of an enum, it is possible to reduce the risk of an invalid response simply by restricting the possible passed values. Of course, there are still parameters that could not fit in an enum . For example, machine tag queries in the Search method – chances are the user will make some mistakes when using that, but there is no way to really restrict the value passed there because of the free-form nature of the parameter value.

As of the method implementations, you are already familiar with the general structure – all that changes is the parameter set and the method name in the URL. However, there is one method that is exceptionally big – Search.

It’s implementation is in no way different from any other method out there, but the parameter set is quite impressive:

public  void Search(string apiKey, string authToken, string signature, HelperDelegate helperDelegate, TagMode tagMode = TagMode.Any, string text = "", string[] tags = null, string userID = "", string[] extras = null, string maxUploadDate = "", string minTakenDate = "", string maxTakenDate = "", PrivacyFilter privacyFilter = PrivacyFilter.Undefined, Media media = Media.All, string minUploadDate = "", string page = "", string perPage = "", Sort sort = Sort.Undefined, string license = "", string[] bbox = null, string accuracy = "", SafetyLevel safeSearch = SafetyLevel.Undefined, ContentType contentType = ContentType.Undefined, string machineTags = "", TagMode machineTagMode = TagMode.Any, string groupID = "", Contacts contacts = Contacts.All, string woeID = "", string placeID = "", HasGeo hasGeo = HasGeo.Undefined, GeoContext geoTag = GeoContext.Everywhere, string lon = "", string lat="", string radius = "", Units radiusUnits = Units.Km, bool isCommons = false, bool inGallery= false, bool isGetty = false)

This is the method used to search for photos on Flickr and the engineers there give the caller plenty of options to filter their search results only to find interesting photos.  I know that in normal conditions implementing a method like this can be a nightmare, with this amount of parameters. But take a closer look – most of them are optional. According to the API documentation, the parameters that are optional here are also optional for the actual call – you can simply avoid using them or pass another value if that is one of the criteria you are looking for.

This is going to be the last article regarding the core structure of the application – basically, its engine. Of course, I will be adding more method implementations, but the basic set is already here. Now it’s time to switch to the UI and see these methods work. If you would like to download the code for the Photos class, you can do this by clicking here.

I decided that this project evolves in an interesting direction, so it will be published soon on CodePlex, where I will be able to get user and developer feedback and subsequently release updated versions of the application.