FacebookAgent update: Now upload a photo and then change status in a single call using Facebook connect for iPhone

1 Star2 Stars3 Stars4 Stars5 Stars (6 votes, average: 4.17 out of 5)
Loading ... Loading ...

GET THE LATEST CODE FROM HERE: http://code.google.com/p/iphone-facebook-twitter-connect-easy-integration-tool/
PLEASE JOIN THE PROJECT

In my previous post I shared a FacebookAgent to simplify integrating Facebook connect in iPhone and using common actions without
handling login, permission check etc but in a single method call like:

  • Publish feed
  • Change status
  • Upload photo
Scotopia from iphonedevsdk.com shared an excellent idea of implementing a method which would upload a photo and then update status.
I have updated the FacebookAgent according to that. Now it has few more functions:
/**
 * Upload photo
 */
- (void) uploadPhoto:(NSString*)imageurl;
- (void) uploadPhotoAtURL:(NSString*)imageurl withCaption:(NSString*)captionOrNil toAlbum:(NSString*)aidOrNil;
- (void) uploadPhotoAsData:(NSData*)imagedata withCaption:(NSString*)captionOrNil toAlbum:(NSString*)aidOrNil;

/**
 * Upload photo with status
 */
- (void) uploadPhoto:(NSString*)imageurl withStatus:(NSString*)status;
- (void) uploadPhotoAtURL:(NSString*)imageurl withStatus:(NSString*)status caption:(NSString*)captionOrNil toAlbum:(NSString*)aidOrNil;
- (void) uploadPhotoAsData:(NSData*)imagedata withStatus:(NSString*)status caption:(NSString*)captionOrNil toAlbum:(NSString*)aidOrNil;

/**
 * Ask permission to auto approve uploaded photo and add photo to an album.
 */
- (void) askUplaoadPhotoToAlbumPermission;



Add to Google Reader or Homepage


  • gc
    Hi, I am not sure how to use this...

    1. when should I use "askUplaoadPhotoToAlbumPermission"
    2. What the "status" parameter should be in uploadPhotoAsData: withStatus method?

    Thanks,
  • Unleech
    help, another problem. the dialog keeps on appearing, after i log in.
    and the other problem is *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: session_key)'

    i wonder why the feed dialog keeps on appearing again and again... help thanks!
  • Johnryan1
    I just realized is it possible that these functions don't work exactly right with ios4?
  • Johnryan1
    Hi, I am on the verge of getting this working. I have 2 issues with the upoadphotowith data withstatus function. First, and most importantly, once i have uploaded the photo, the app quits. Is there a way to avoid this?

    Second, when I Use an NSString for the status and album they don't seem to work. Any suggestions? Thanks a lot.
  • Unleech
    i have the same problem with uploading photo with data. tried changing nsdictionary to nsmutabledictionary, still doesnt work. tried also the initwithsession. but it still crashes.
    here is my error:
    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: session_key)'

    any ideas what im doing wrong? thanks! hope you could get back to us asap. :)
  • moholy
    Hi,
    Could you explain this further? I just looked through the example code and can't find what you're talking about - could you please spell out exactly what FQL is and how to run the "common FQL" command that would allow the photos to be published without needing the user to go to Facebook and allow the photos explicitly?
  • mailed you, plz check.
  • Johnryan1
    I was wondering if you could also provide me with some information on the FQL commands? I am hoping that it will stop my program from crashing with the uploadphotoasdata. Thanks a lot.
  • you have to grant permission by executing a FQL.

    I have updated the code last month enabling easy FQL running option and with some ready functions to make some common FQL.

    plz check out the latest code with example, btw plz use your own key/secret.. i trust my reader and committed so that anyone can test right away.

    thanks.
  • Moholy
    Hello, your class is fantastic. But I am having a problem. When users upload a photo, the photos get buried in their facebook under a category:
    "This album contains photos uploaded from another application. Select photos to approve or reject."
    Is there a way to ask/grant this permission from the iPhone app? The standard ask permission dialog comes up the first time someone posts from my app and there are no errors, warnings. Is there a way to get extended permissions or something? Please help - urgent! I just noticed this and my app is already submitted to the app store.
  • you have to grant permission by executing a FQL.

    I have updated the code last month enabling easy FQL running option and with some ready functions to make some common FQL.

    plz check out the latest code with example, btw plz use your own key/secret.. i trust my reader and committed so that anyone can test right away.

    thanks.
  • Hey Aman, thanks for this code, I'm wondering if the new facebook api version didn't break your implementation to upload photos. I can't seem to get the uploadphoto stuff working, and i did change the nsdictionary to nsmutabledictionary.

    what im ultimately trying to do is :

    1.post an image created on the iphone (which ive managed to upload to a google app engine app to get a public url) to a facebook usersphoto album named after my app,

    2.then get the link for that album/photo page send it back to the iphone and then...

    3.create a status update that links to the photo page that we just created in the users app specific photo album.
  • Jack
    FacebookAgent is incredibly useful! I just finished implementing it into my app and have successfully integrated uploading of photos. However, if there is no Internet connection available the login prompt appears and immediately disappears - how can I get round this?
  • Fawad
    Hi,
    I would like to appreciate your efforts for writing this wrapper class. It helped me a lot.

    I have one question, can we upload an image as NSData or you can say in binary format along with the feed, instead of passing an image URL. I actually want to upload my feed with an image, any useful pointers on this will be appreciated.

    Thanks
  • hey Fawad, glad to hear that it helped you.

    To post NSData use the following method of FacebookAgent:

    - (void) uploadPhotoAsData:(NSData*)imagedata withCaption:(NSString*)captionOrNil toAlbum:(NSString*)aidOrNil;


    btw, this code is not fully tested.. shooting me any bug you encounter is highly appreciated :)
  • Fawad
    I have tested it (uploadPhotoAsData), and it is successful, but what i want is, when we publish the feed, say for example using facebookAgent method

    - (void) publishFeedWithName:(NSString*)name
    captionText:(NSString*)caption
    imageurl:(NSString*)url
    linkurl:(NSString*)href
    userMessagePrompt:(NSString*)prompt
    actionLabel:(NSString*)label
    actionText:(NSString*)text
    actionLink:(NSString*)link
    targetId:(NSString*)target

    here, in ImageURL, can we upload the image as NSData, is it possible, is there any possible workaround for this, or do i have to upload the image first on facebook, then retrieve its URL and then upload the feed with the image URL.

    Thanks for your time :)
  • nope.. till now its not possible to upload image data to facebook while publishing feed as stated in their wiki. We have to put some valid image url.
  • Fawad
    i see, ok then i ll use some alternate approach, like first uploadin it on facebook and then retrieving its url, and use it as an extra link to the feed.
  • yep, probably u got to run a fql also.
  • Me
    I'm seeing two errors:

    1) Getting EXC_BAD_ACCESS when calling uploadPhotoAsData and uploadPhotoAsData withStatus. I've confirmed that the image data is valid.

    2) I present the FacebookAgent view from another view. When I log in to Facebook, leave the FacebookAgent view, then go back to the FacebookAgent view and do setStatus I get the Extended Permission window with the message "An invalid next or cancel parameter was specified". Pressing the okay button does not dismiss this permission window.
  • Me
    1) I'm still seeing this error, even after changing uploadImage to use NSMutableDictionary near line 202 in FacebookAgent.m

    2) It looks like I've solved this problem. The Facebook developers mentioned in the iPhone forum that logging in/out across view changes can cause the FB Connect _session variable to get out of sync. The solution is to always use initWithSession when asking permission.

    In FacebookAgent.m in askPermission near line 121 change:

    FBPermissionDialog* dialog = [[[FBPermissionDialog alloc] init] autorelease];

    to

    FBPermissionDialog* dialog = [[[FBPermissionDialog alloc] initWithSession:_session] autorelease];
  • Unleech
    im still having a bad access error T_T
  • Unleech
    mine crashes at line 215
    [[FBRequest requestWithDelegate:self] call:@"facebook.photos.upload" params:params dataParam:uploadImageData];
    with this error
    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: session_key)'
  • Thanks a lot for the fix!

    please check http://code.google.com/p/iphone-facebook-twitte...
  • sorry pal.. I had to move to actionscript development... learning it... hardly getting any time on iphone development :(
  • dev
    General security question folks, I notice here the facebook app API key and secret is being hard coded, which I also noticed was what looked to be the recommended way in facebooks 'integrate facebook connect in 5 minutes' video.

    Is this a security issue? Presumably someone downloading an app with a hardcoded key/secret would be able to dig that out with a 'jail broken' phone. They can then spoof FBConnect use as though it were coming from your application. This could lead to facebook pulling your facebook app from their site, if they spammed for example, making all those copies of your app no longer work.

    With key/secret hard-coding you are relying on facebook keeping the facebook app side of your iphone app running, or your iphone app is dead in the water.

    Is there a better way to set the key/secret?
  • One way can be:

    1. Store the keys in a server.
    2. Iphone request the keys
    3. server encrypts the keys with a random key(ekey)
    4. server sends the keys and the ekey
    5. iphone decrypts the fb keys with the ekey.


    any better idea? Please share..
  • The last version is very useful ! Great Work! But I have a little problem, when I get the pid of the uploaded photo, this is not the pid of the photo, it's a long int different of the pid. Do you have an idea how can I retrieve the correct pid ?
  • yea, I also found this. To retrieve the photo id a fql has to be executed.. i could not find any other easy solution for this. Please share if you solve this. Thanks.
  • dylanmalone
    I can't understand facebook's fql system very well, but it wasn't too hard to hack together a workaround for generating the uploaded photo's URL. This code sets the NSString currentPhotoURL to the correct link address for the newly uploaded photo. If anyone has clean fql code, which would presumably be a more proper method, I'd love to see it, but this at least works.

    - (void) facebookAgent:(FacebookAgent*)agent photoUploaded:(NSString*) pid{
    currentPid = pid;

    currentPhotoURL = [NSMutableString stringWithFormat: @"http://www.facebook.com/photo.php?pid="];
    NSString *endNumbers = [currentPid substringWithRange: NSMakeRange(16,5)]; // ex: 100000864320548_21858
    NSString *startNumbers = [currentPid substringWithRange: NSMakeRange(0,15)];
    [currentPhotoURL appendString:endNumbers];
    [currentPhotoURL appendString:@"&id="];
    [currentPhotoURL appendString:startNumbers];
    NSLog(@"The URL we're going to use is: %@", currentPhotoURL);
    [self publishStream];
    }
  • Transton
    Damn you are good, I must say you are a star developing such excellent stuff and releasing it here on your site. There are two problems though, one regarding the FacebookAgent and one regarding the TwitterAgent.

    Problem 1.)
    The fbagent photo upload works flawlessly in the Simulator 3.1.2 | Debug, but when I try it on the Device 3.1.2 | Debug it crashes with EXC_BAD_ACCESS in [FacebookAgent uploadImage] in the else case on line 213:
    else {
    if(uploadImageAlbum){
    [params setValue:uploadImageAlbum forKey:@"aid"];
    }
    }
    I have tried all uploading-methods, and problem exists on all of them, the publishfeed-stuff works though.
    Does it work on your device?

    Problem 2.)
    The TwitterAgent should save username and password and fill the fields the next time, and I can see in the code that it writes to file and saves them. This also works flawlessly in the Simulator 3.1.2 | Debug, but not on the Device 3.1.2 | Debug. On the device, nothing is filled into the fields the next time the app runs.

    I will let you know if I find any solutions, but I haven't managed to find any the last two hours.
  • danbaumbach
    I found some problems where he declared an NSDictionary and then tried to add to it. I changed it to NSMutableDictionary and that fixed it.
  • dev
    I may be seeing the same issue. Whereabouts in the source do I need to change from NSDictionary to NSMutableDictionary?
  • its near line 202 in FacebookAgent.m.

    -(void)uploadImage{
    NSDictionary *params;
    ---
    change NSDictionary to NSMutableDictionary.

    -----
  • dylanmalone
    I'm seeing exactly what Transtron saw, but can't seem to make code work, even with the change you mentioned. I wonder if I'm not doing it correctly. I'm embarrassed to admit I really don't understand NSDictionary objects... here's my "patched" version of the code, which still doesn't work:

    -(void)uploadImage{
    NSMutableDictionary *params;
    if(uploadImageCaption){
    params = [NSMutableDictionary dictionaryWithObjectsAndKeys:uploadImageCaption,@"caption",nil];
    if(uploadImageAlbum){
    [params setValue:uploadImageAlbum forKey:@"aid"];
    }
    }else {
    if(uploadImageAlbum){
    [params setValue:uploadImageAlbum forKey:@"aid"];
    }
    }

    [[FBRequest requestWithDelegate:self] call:@"facebook.photos.upload" params:params dataParam:uploadImageData];
    }

    Any idea what else I can try? Thanks for this wonderful wrapper class, it's saved me from a mountain of work, and I'm still learning as a developer, so it would have been very hard to do this without using your code!
  • danbaumbach
    I don't remember and I took out the code because I couldn't get it to do what I wanted. It's Facebook Connect and not FBAgent that doesn't allow me to do what I want.

    You'll have to trace through the code and see where the crash occurs. It's where they are trying to add an entry to an NSDictionary rather than an NSMutableDictionary.

    BTW, it doesn't matter what you call the photo album, if any, because FB ends up using the name of your registered Facebook app and not the name you entered.

    - Dan.
  • Transton
    I took a closer look now danbaumbach and you are absolutely right, good work! The problem lies within the uploadImage method in FacebookAgent.m. As we can see he is trying to set values in a NSDictionary. You can keep the NSDictionary with some slight modifications or you can switch to NSMutableDictionary also with some slight modifications. Problem solved!
  • Unleech
    help asap please i already changed everything to nsmutabledictionary, but it still has an error T_T it says
    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: session_key)'

    where is that nscfdictionary??? huhu that happens when i logout then relogin and repost a feed and upload an image, then it crashes. its ok if im already logged in, i can repost and upload as much as i want. but i relog, it crashes. help please T_T thanks!
  • Unleech
    hm, ok... i fixed it temporarily by setting the fbsessionresume to NO :)
  • U guys rock! thanks all for helping :)
  • hey danbaumbach! Thanks a lot!! After writing these classes, I could not test these agents on iphone/ipod yet.
  • Dan Baumbach
    I'm using uploadPhotoAsData and a photo gets uploaded to an album and my status is updated. However in Facebook they appear in two separate posts. If I were to just go to facebook and in the add a comment plus upload a photo, they get posted in the same status post.

    Is there a way to do this with FBAgent or even with Facebook Connect?

    Thanks.

    - Dan.
  • Dan Baumbach
    I've been looking more carefully at the Facebook API and there doesn't appear a way to do this. You can upload a photo and you can change status but you can't post a photo as part of a status update even though you can do it on Facebook on the web.
  • yea, u r right. Please share if you get any clue to do so. Thanks.
  • danbaumbach
    You can't do upload a photo with status on Facebook's iPhone app either. When you do it through Facebook on the web, the photo get's put in a Wall Photos album. However when you do it with Facebook Connect, it gets put in an album named after the app that you registered with Facebook. The API apparently ignores the albumName parameter.
  • Also whenever I click the 'x' or 'cancel' button on the fbconnect login screen it just keeps re-opening the login.
  • I could not reproduce this... Please download again, I've uploaded the latest code.

    is it still happening?
  • I already had my own FBConnect files, so I replaced them with the ones you had in the project, same thing. It keeps reopenning if you click cancel. and I have the latest version
  • What about a session resume method?
  • before calling, add this line.

    fbAgent.shouldResumeSession = YES;
  • It crashes

    -[FacebookAgent setShouldResumeSession:]: unrecognized selector sent to instance 0x4a13d10'
  • I did before, the funny thing is i see the method for it in the facebookagent.h and I guess its not working when I call it?
  • Have you tried and used every method?
  • yea, but still full testing was not done.

    Please check this project. http://www.amanpages.com/wordpress/wp-content/u...

    Here I published a feed with no problem.

    I first removed/deleted any Fbconnect sources. and then adde the FaceBook Agent folder to the project. It has fbconnect inside with some editing.

    However, now when i want to change status getting this error:
    "Error(102) Session key invalid or no longer valid"
    Googling revealed it was a bug : http://forum.developers.facebook.com/viewtopic....

    any idea?
  • Well I was using it without your FacebookAgent class's before to publish status's etc. I just liked how your Project was set up so I wanted to use it.
  • I really appreciate your support. Can you publish feed now? is the login screen is appearing again and again?

    I share the code because I also like to use other piece of work if suits my need. So, just wanted to contribute to the community.
  • Ok well first off, I really appreciate everything you've tried to help me with. And I fixed one Problem. So since I had FBConnect before, I had the header search paths, etc. I took them out, replaced all my FB Connect Files, and it finally worked. Now the only thing that doesn't work is that the Cancel button reopens the Login. So I'm trying to fix that as we speak :)
  • Thanks a lot. Now I am at my day job, so can't work on it by next 6 hours.. so I will really appreciate if you share your fix or suggestion :)
  • No but if you press Login you go to the publish feed page, its just when you click cancel.
blog comments powered by Disqus