iPhone Facebook Connect: How Do I publish feed with FacebookAgent

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

I planned to write a series of “How Do I…”s with Facebook Connect. Certainly the primary target is YOU but it will also work as a reference to me as well :)

The first article will be on publishing a feed.

So lets start…!

App Requirement Spec

  1. Option to login/logout to Facebook
  2. Option to publish a feed with:
    • With an image with link
    • Action link

Get FacebookAgent code

Checkout the latest code from Google Code project. The checkout url is:

svn checkout http://iphone-facebook-twitter-connect-easy-integration-tool.googlecode.com/svn/trunk/ iphone-facebook-twitter-connect-easy-integration-tool-read-only

Create a project

Open up the xcode project and create a view based application; name it “FacebookFeedPublish”

Add FacebookAgent code to project

Right click on the project. Select Add->Existing File. Select the “xutils” folder from the checked out code.

Picture 17.png

Do not copy.

Add JSON libraries

Right click on the project. Select Add->Existing File. Select the “JSON” folder from the checked out xutils-example project.

Picture 19.png

Do not copy this either.

Build the project. It should build with no error.

Initialize FacebookAgent

Edit FacebookPublishFeedAppDelegate.m.

import FacebookAgent.h at the top.

#import FacebookAgent.h

Add the following line in applicationDidFinishLaunching method:

// initiazlie FacebookAgent
[[FacebookAgent sharedAgent]  initializeWithApiKey:@"YOUR_API_KEY"
							ApiSecret:@"YOUR_API_SECRET"
							ApiProxy:nil];

You have to put your Facebook Application api key and secret. Just incase you are not sure about this, create a Facebook application from http://www.facebook.com/developers/createapp.php. After creating one, you will get api key and secret. Copy and paste those value in the above code.

Prepare FacebookConnectDelegate handler

We can use FacebookAgent in multiple view controllers. Very likely we will use it in many places. We have to override and define many delegate methods in each view controllers where we like to use FacebookAgent.

To simplify the process, we well create a UIViewController subclass which will define all the FacebookAgentDelegate methods. Our view controller class will extend this class and override only the required ones.

Add a new file of UIViewController subclass. Name it MyCustomController.

Picture 23.png

Uncheck “With xib for user interface”.

Implement FacebookAgentDelegate protocol:

#import "FacebookAgent.h"

@interface MyCustomController : UIViewController {

}

Now define the protocol methods:

#pragma mark FacebookAgentDelegate
- (void) facebookAgent:(FacebookAgent*)agent statusChanged:(BOOL) success{}
- (void) facebookAgent:(FacebookAgent*)agent didLoadInfo:(NSDictionary*) info{}
- (void) facebookAgent:(FacebookAgent*)agent didLoadFriendList:(NSArray*) data onlyAppUsers:(BOOL)yesOrNo{}
- (void) facebookAgent:(FacebookAgent*)agent didLoadPermissions:(NSArray*) data{}
- (void) facebookAgent:(FacebookAgent*)agent didLoadFQL:(NSArray*) data{}
- (void) facebookAgent:(FacebookAgent*)agent permissionGranted:(FacebookAgentPermission)permission{}
- (void) facebookAgent:(FacebookAgent*)agent photoUploaded:(NSString*) pid{}
- (void) facebookAgent:(FacebookAgent*)agent requestFaild:(NSString*) message{}
- (void) facebookAgent:(FacebookAgent*)agent loginStatus:(BOOL) loggedIn{}
- (void) facebookAgent:(FacebookAgent*)agent dialog:(FBDialog*)dialog didFailWithError:(NSError*)error{}

Then edit FacebookPublishFeedViewController.h file and make it extend to the newly created class:

Build the project, it should build without any error.

Enable login/logout option

Add a button to the view. Set its image for default state “Connect_iphone.png”.

Press ‘cmd + =’ to adjust the size.

Picture 21.png

Set selected state button “Logout_iphone.png”.

Picture 22.png

These images are downloaded from Facebook site and available in FacebookAgent code base.

Connecting the button

Edit FacebookPublishFeedViewController class.

Create an IBOutlet connect it with the button.
Then create an IBAction method and set it as button onTouchUpInside handler.

#import 
#import "MyCustomController.h"

@interface FacebookPublishFeedViewController : MyCustomController {
	UIButton* btnFbConnect;
}
- (IBAction)OnFBConnect:(id)sender;
@property(nonatomic, retain) IBOutlet UIButton* btnFbConnect;
@end

In OnFBConnect method we will login to facebook. If already connected we will sign out. So, method definition will be like this:

#pragma mark actions
- (IBAction)OnFBConnect:(id)sender{
	if([[FacebookAgent sharedAgent] isLoggedIn]){
		[[FacebookAgent sharedAgent] logout];
	}else {
		[[FacebookAgent sharedAgent] login];
	}
}

Update connect button state

Override the following method like below in FacebookPublishFeedViewController class:

#pragma mark FacebookAgentDelegate method
- (void) facebookAgent:(FacebookAgent*)agent loginStatus:(BOOL) loggedIn{
	if(loggedIn){
		btnFbConnect.selected = YES;
	}else {
		btnFbConnect.selected = NO;
	}
}

This code will update the button image according to login status.

Run the app and connect to Facebook by clicking the button…. Oops button state is not changed! Add the following line in MyCustomController class viewLoaded method:

- (void)viewDidLoad {
    [super viewDidLoad];
	[FacebookAgent sharedAgent].delegate = self;
}

Now build and run… after login or logout now button image is updated accordingly.

Publish Feed

Add another Round button and add touch up inside handler in FacebookPublishFeedViewController class in this way:

- (IBAction)OnFBPublishFeed:(id)sender{
	[[FacebookAgent sharedAgent] publishFeedWithName:@"Hello Facebook!"
			captionText:@"This is a test publish"
			imageurl:@"http://xapplab.com/images/appss/puzzleshot/puzzleshot-icon.png"
			 linkurl:@"http://itunes.apple.com/app/puzzleshot/id343659310?mt=8"
			userMessagePrompt:@"Whats on your mind?"
			actionLabel:@"Play PuzzleShot"
			actionText:@"PuzzleShot!"
			actionLink:@"http://itunes.apple.com/app/puzzleshot/id343659310?mt=8"];
}

The feed will look this:

Picture 26.png

Thats it!

Next article will be on showing logged in user information and image. But let me manage some time first :)

Download the project source :FacebookPublishFeed.zip

Don’t forget to change api key and secret to run the project correctly!




Add to Google Reader or Homepage


  • I seem to have an issue with remaining logged into FB but not really.

    Steps to Repro:
    1) Launch App
    2) Use FacebookAgent to login (just login, DON'T update FB status or publish to feed or anything)
    3) Quit/Close App
    4) Launch App Again
    5) Use FacebookAgent to check if user is logged in (it'll return YES that the user is logged in).
    6) Try and update status or publish to feed...

    Here a facebook login dialog is presented as if the user isn't logged into FB connect. Not sure why this dialog is popping up if the user is still logged into FB connect. So either the user is not logged in and FacebookAgent is incorrect when checking the status or the user is logged in but somehow another login dialog pops up.

    NOTE: The login dialog on the second launch of the app (the unexpected one) is different than the FB connect dialog that FacebookAgent presents for the first time when logging in.

    Anyone else have this issue or know how to solve it? Obviously I can always have the FacebookAgent logout before the app exists but this is not desirable.

    Thanks for the FacebookAgent package, it has really helped me easily add FB integration to my app. Again, thanks!
  • Jon
    Hi Aman,

    This sample code is great, it greatly simplifies the process of accessing the Facebook Connect API, hover I have one issue with the implementation of the code. I find it rather difficult to have to subclass the "MyCustomController" every time I create a new view controller. Some of my view controllers are already custom classes that I have to make subclasses of "MyCustomController". Is there there an easier way to implement FacebookAgent?
  • Ali
    Hi, I'm pretty frustated in trying to implement this into my project. I've tried many ways but with no success. Please help me with this. Thanks a lot. Here's my code.
    `@implementation ScoresLayer

    - (id)init {
    if ((self = [super init])) {
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    CCSprite *bg = [CCSprite spriteWithFile:@"menubg1.png"];

    [bg setPosition:ccp(winSize.width / 2, winSize.height / 2)];
    [self addChild:bg z:0];

    /* [CCMenuItemFont setFontName: @"American Typewriter"];
    [CCMenuItemFont setFontSize:(winSize.height == 1024 ? 36 : 18)];
    CCMenuItemFont *title1 = [CCMenuItemFont itemFromString: @"Sound"];
    [title1 setIsEnabled:NO];
    CCMenuItemFont *title2 = [CCMenuItemFont itemFromString: @"Music"];
    [title2 setIsEnabled:NO];
    CCMenuItemFont *title3 = [CCMenuItemFont itemFromString: @"Graphic Quality"];
    [title3 setIsEnabled:NO];

    [CCMenuItemFont setFontName: @"Marker Felt"];
    [CCMenuItemFont setFontSize:(winSize.height == 1024 ? 68 : 34)];
    CCMenuItemToggle *item1 = [CCMenuItemToggle itemWithTarget:self selector:@selector(toggleSound:) items:
    [CCMenuItemFont itemFromString: @"On"],
    [CCMenuItemFont itemFromString: @"Off"],
    nil];
    CCMenuItemToggle *item2 = [CCMenuItemToggle itemWithTarget:self selector:@selector(toggleMusic:) items:
    [CCMenuItemFont itemFromString: @"On"],
    [CCMenuItemFont itemFromString: @"Off"],
    nil];
    CCMenuItemToggle *item3 = [CCMenuItemToggle itemWithTarget:self selector:@selector(toggleGraphic:) items:
    [CCMenuItemFont itemFromString: @"High"],
    [CCMenuItemFont itemFromString: @"Low"],
    nil];

    if ([[VariableStore sharedVariableStore] sound])
    [item1 setSelectedIndex:0];
    else
    [item1 setSelectedIndex:1];

    if ([[VariableStore sharedVariableStore] music])
    [item2 setSelectedIndex:0];
    else
    [item2 setSelectedIndex:1];
    if ([[VariableStore sharedVariableStore] hiQ])
    [item3 setSelectedIndex:0];
    else
    [item3 setSelectedIndex:1];

    CCMenu *menu = [CCMenu menuWithItems:
    title1, title2,
    item1, item2,
    title3,
    item3, nil];
    [menu alignItemsInColumns:
    [NSNumber numberWithUnsignedInt:2],
    [NSNumber numberWithUnsignedInt:2],
    [NSNumber numberWithUnsignedInt:1],
    [NSNumber numberWithUnsignedInt:1],
    nil
    ];

    [self addChild:menu z:1];*/

    CCMenuItemImage *back = [CCMenuItemImage itemFromNormalImage:@"b1.png" selectedImage:@"b2.png" target:self selector:@selector(getBack:)];
    if (winSize.height == 1024)
    [back setScale:2];
    _fb = [CCMenuItemToggle itemWithTarget:self selector:@selector(connectFB:) items:
    [CCMenuItemImage itemFromNormalImage:@"Connect_iphone.png" selectedImage:@"Connect_iphone.png"],
    [CCMenuItemImage itemFromNormalImage:@"Logout_iphone.png" selectedImage:@"Logout_iphone.png"],
    nil];

    CCMenu *menu1 = [CCMenu menuWithItems:back, _fb, nil];
    [menu1 setPosition:CGPointZero];
    [back setPosition:ccp(winSize.width * 0.2, winSize.height * 0.1)];
    [_fb setPosition:ccp(winSize.width * 0.8, winSize.height * 0.1)];

    [self addChild:menu1 z:1];

    [self schedule:@selector(update:)];

    [[FacebookAgent sharedAgent] setDelegate:self];

    /* UIAlertView *myAlert = [[[UIAlertView alloc] initWithTitle:@"New Score"
    message:@"You got new score. Would you like to publish it?"
    delegate:self cancelButtonTitle:@"Why Not" otherButtonTitles:@"No", nil] autorelease];
    [myAlert show];*/
    [[FacebookAgent sharedAgent] publishFeedWithName:@"Scored 0123456789"
    captionText:@"Download BurningArmor now to beat his record"
    imageurl:@"http://img101.imageshack.us/img101/6311/balogo.png"
    linkurl:@"http://www.apple.com"
    userMessagePrompt:@"What's on your mind?"];
    }

    return self;
    }

    - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    if (!buttonIndex)
    [[FacebookAgent sharedAgent] publishFeedWithName:@"Scored 0123456789"
    captionText:@"Download BurningArmor now to beat his record"
    imageurl:@"http://img101.imageshack.us/img101/6311/balogo.png"
    linkurl:@"http://www.apple.com"
    userMessagePrompt:@"What's on your mind?"];
    }

    - (void)update:(ccTime)dt {
    [_fb setSelectedIndex:[[FacebookAgent sharedAgent] isLoggedIn]];
    }

    - (void)connectFB:(id)sender {
    if ([[FacebookAgent sharedAgent] isLoggedIn])
    [[FacebookAgent sharedAgent] logout];
    else
    [[FacebookAgent sharedAgent] login];
    }

    - (void)getBack:(id)sender {
    [[CCDirector sharedDirector] popScene];
    }

    - (void) facebookAgent:(FacebookAgent*)agent statusChanged:(BOOL) success{}
    - (void) facebookAgent:(FacebookAgent*)agent didLoadInfo:(NSDictionary*) info{}
    - (void) facebookAgent:(FacebookAgent*)agent didLoadFriendList:(NSArray*) data onlyAppUsers:(BOOL)yesOrNo{}
    - (void) facebookAgent:(FacebookAgent*)agent didLoadPermissions:(NSArray*) data{}
    - (void) facebookAgent:(FacebookAgent*)agent didLoadFQL:(NSArray*) data{}
    - (void) facebookAgent:(FacebookAgent*)agent permissionGranted:(FacebookAgentPermission)permission{}
    - (void) facebookAgent:(FacebookAgent*)agent photoUploaded:(NSString*) pid{}
    - (void) facebookAgent:(FacebookAgent*)agent requestFaild:(NSString*) message{}
    - (void) facebookAgent:(FacebookAgent*)agent loginStatus:(BOOL) loggedIn{}
    - (void) facebookAgent:(FacebookAgent*)agent dialog:(FBDialog*)dialog didFailWithError:(NSError*)error{}

    @end`
    This code works fine. But this is not what I want. I want my game to publish the score via publishFeedWithName method on when then user gives the app permission. So I call the publish method in alertView method. When the user click Why Not button, it publish. And it won't when the user click No in UIAlertView. But ... it doesn't work.

    My question is how should I do it? It works very fine in the init method. But when I move the code into the alertView method. I doesn't. Thanks for the reply. And sorry for my bad English.
  • coneybeare
    have you tried this on 4.0? I am having compilation warnings and missing info in the feeds
  • coneybeare
    I was able to patch up the issues I was having with the info for the story, I had some escaped double quotes and it turns out they need to be double escaped. The compilation warnings still persist. Right now I am looking for a way to get a callback on a successfully published story, something like @"The post was published successfully". Any ideas?
  • Irene
    Any progress on that? I think it's important to let the users know if their content was published properly..
  • rajdn
    Aman,

    I have checked IB that the selected state using logout image button. Followed the same above steps. Interesting it works fine with sample project that you provided. But the logout button doesn't showup with my existing code..
  • rajdn
    I'm using the same sample code "FacebookPublishFeed.zip" which has exact steps for Enable login/logout option. It does'nt show logout button after I login and click back login button. It alwasy shows login button for logout button. I have followed same above steps "Enable login/logout option" with loginstatus cheking code. Anything missing or needs to tweak?
  • plz check on Interface Builder if you set the the correct image for selected state of the button.
  • rajdn
    Excellent Tutorial and really helpful..I tried the project sample it works without a problem.

    Can we copy all the xutils folder into the exisitng project?

    How do I get all my facebook friend list and select each of them , then publish feed?
  • Thanks.
    Yea, you can also copy the xutils folder into the existing project.

    To get the friend list, you have to run a fql, soon i will integrate this into FacebookAgent.

    But still not tried publishing feed to more than one target... need to try.

    all the best.
  • JWeldin
    Do you have an example of this? I am trying to allow the user to choose the target for publishing to their wall, but I can't get the friend list to load before publishing. Can you share some sample code?
blog comments powered by Disqus