0

So i'm trying to get a users Facebook profile image using SLRequest. I feel like I've scoured the entire internet to no avail and am at my wits end. Here's the dilemma...

Version 1 of the code:

let store = ACAccountStore()
let type = store.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)
store.requestAccessToAccountsWithType(type, options: [ ACFacebookAppIdKey: "1437725166510606", ACFacebookPermissionsKey: ["email"] ]) { (granted: Bool, error: NSError!) -> Void in
    if granted {
        let accounts = store.accountsWithAccountType(type)
        if let account = accounts.last as? ACAccount {
            let pictureURLString = "https://graph.facebook.com/v2.1/me/picture"
            let request = SLRequest(forServiceType: SLServiceTypeFacebook, requestMethod: SLRequestMethod.GET, URL: NSURL(string: pictureURLString), parameters: nil)
            request.account = account
            request.performRequestWithHandler() { (data: NSData!, response: NSHTTPURLResponse!, error: NSError!) -> Void in
                if let imageData = data {
                    // Save the image
                    // println("Data size: \(imageData.length)\ndata: \(imageData.description)\nAs string: \(NSString(data: imageData, encoding: NSUTF8StringEncoding))")
                    data.writeToFile(NSFileManager.defaultManager().profileImagePath(), atomically: true)
                }
            }
        }
    }
}

Ok, so this versions works, but returns a really, really small version of the profile image. I want a larger image! According to the Facebook docs, and lot's of others on SO the way to do this is to specify parameters such as: type=large or width=120&height=120 but as soon as I do this I get the following error:

{"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthException","code":2500}}

When the Facebook docs for getting the profile image (at https://developers.facebook.com/docs/graph-api/reference/v2.1/user/picture) explicitly state:

Because profile pictures are always public on Facebook, this call does not require any access token.

Many suggestions, such as this answer https://stackoverflow.com/a/7882628/1175289, suggest using the Facebook id rather than "me" in the request, but this does not seem to work at all now that we get an app_scoped_user_id rather than the canonical fbId.

EDIT: This works fine, I was just being a plank! :)


For the sake of sanity, here is the code that causes the error:

let store = ACAccountStore()
    let type = store.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)
    store.requestAccessToAccountsWithType(type, options: [ ACFacebookAppIdKey: "1437725166510606", ACFacebookPermissionsKey: ["email"] ]) { (granted: Bool, error: NSError!) -> Void in
        if granted {
            let accounts = store.accountsWithAccountType(type)
            if let account = accounts.last as? ACAccount {
                let pictureURLString = "https://graph.facebook.com/v2.1/me/picture?type=large"
                let request = SLRequest(forServiceType: SLServiceTypeFacebook, requestMethod: SLRequestMethod.GET, URL: NSURL(string: pictureURLString), parameters: nil)
                request.account = account
                request.performRequestWithHandler() { (data: NSData!, response: NSHTTPURLResponse!, error: NSError!) -> Void in
                    if let imageData = data {
                        // Save the image
                        // println("Data size: \(imageData.length)\ndata: \(imageData.description)\nAs string: \(NSString(data: imageData, encoding: NSUTF8StringEncoding))")
                        data.writeToFile(NSFileManager.defaultManager().profileImagePath(), atomically: true)
                    }
                }
            }
        }
    }

as you can see, the only thing that has changed is the addition of ?type=large to the url string.


If anyone has faced a similar issue, or has any idea what I'm doing wrong, help would be very much appreciated! :)

Community
  • 1
  • 1
George Green
  • 4,807
  • 5
  • 31
  • 45

1 Answers1

1

Because you are using /me/ in your API call, an access_token is required because the API doesn't know who me is. If you replace this with a User ID, e.g.

https://graph.facebook.com/v2.1/4/picture?type=large

It should work fine.

If you want to continue using /me/ in the URL, just append the user's access_token to the URL too, e.g.:

https://graph.facebook.com/v2.1/4/picture?type=large&access_token=abcdef
Niraj Shah
  • 15,087
  • 3
  • 41
  • 60
  • Hey, thanks for the reply. I would like now to apologise for my stupidity! I had thought that using the user id did not work when using an app_scoped_user_id, when in fact I had previously just been incorrectly constructing the link! It seems it does in fact work, as you say! – George Green Aug 27 '14 at 16:03
  • You wouldn't happen to have any idea why a request to https://graph.facebook.com/v2.1/10204218234286542/picture?type=large works fine in the browser, but when requested via SLRequest in my app, returns: {"error":{"message":"(#100) type must be one of the following values: small, normal, large, square","type":"OAuthException","code":100}} ?? – George Green Aug 27 '14 at 16:16
  • @george-green you will have to add the type=large parameters as part of the SLRequest parameters Dictionary e.g. `parameters:@{@"type":@"normal"}`. Then it will work. – fschaper Mar 02 '15 at 09:12