Friday, June 22, 2012

Posting Image on Facebook Page



In today’s tutorial we will have a look at how to post an image on facebook page via iPhone we will be using the graph api for this.

Recently I was working on a demo for my friend to post an image on facebook page I thought it was a simple task similar to how you post an image on the FB wall but there were many twist and turns here.

Few important points before proceeding with this post



- For posting on your facebook page you have to be the admin of that page.

- For this demo i have created a test page.


- Since i am the admin of that page i can post any conetents in that page.


- For posting the contents on a page facebook provides you with a page id.


- Page ID will only be provided if you are the admin of that page.


So in this demo i will login with my FB credentials fetch the page id of the test page that i have created and then post a sample image on my test page using the graph API



1.    If you want to post an image on facebook page then you have to be the admin of that page which means that non-admin people cannot post any pics on the FB page, this might sound weird but it seems to be some sort of bug in the facebook : 

2.    You have to use the page access_token and not the user access_token which means that by default you get a access_token when you login using the graph api, but in this case you want to post to a page not to your wall or your friends wall so you need to call one api to request the page acces_token with the help of graph api.

3.    You have to call me/accounts api with the access_token that you have got while login as a parameter using the manage_pages and publish_stream permissions because these are the page permissions that allow you to handle the task related to pages. 

4.    If you do not get the page access_token then the image will be posted on your FB wall since the access_token is the user access_token and not the page access_token.

Note: To post some data on the page you have to be the admin of that page, also make sure that you apply the debugger to see the output that you get when you make a request to the page access_token since you will be getting all the information about the pages that you handle.
I have coded this demo based upon the output that I have received in my console so you have to make the code changes accordingly (Modify the code )
After lots of theory am quite bored so let’s see the practical demonstration of this

Step 1: Open xcode and create a window based application and add a view controller with xib (you may or may not add an xib depends upon you) in it and give it a reasonable name.

Step 2: Open the xib file and drag two buttons one of them will get the image from the gallery and the other will post the image on the facebook page (Remember you have to be the admin of that page else this demo is of no use). Also drag one instance of UIImageView where you will select the image from the gallery to post on the facebook page.

Step 3: Write the code to fetch the image from the gallery of the iphone and if you are facing some issues then kindly follow this tutorial of mine. In the button to post the image you have to make a call to the graph api of facebook (In case if you don’t have the graph api of facebook then here’s the link to get it, the output returned by this api is in json format so you would also require the SBJSON library which you will get from here).

Step 4: Write the code to load the facebook graph, what the graph api does it gets your credentials of facebook and returns  your details with a valid user access_token which can be accessed by the accesstoken property of the FBGraph instance remember all these values will be returned in the FBGraph protocol method named fbGraphCallback:(id)sender so make sure you implement that method else everything will be waste. Here’s what the code looks like

- (IBAction)postImageActionButtonClicked:(id)sender
{
    showIndicator();
    objFBGraph = [[FbGraph alloc]initWithFbClientID:kFBAppID];
    [objFBGraph authenticateUserWithCallbackObject:self andSelector:@selector(fbGraphCallback:) andExtendedPermissions:@"publish_stream,manage_pages" :self];
}



#pragma mark postPictureWithFeedsButtonPressed with photos
- (void)fbGraphCallback:(id)sender{
    
    //In case if the first call fails and you dont get the token
if ( (objFBGraph.accessToken == nil) || ([objFBGraph.accessToken length] == 0) ) 
    {
//restart the authentication process once again....
        [objFBGraph authenticateUserWithCallbackObject:self andSelector:@selector(fbGraphCallback:) andExtendedPermissions:@"publish_stream,manage_pages" :self];
    else 
           //call  method to get the page access token
    {
        [self performSelectorInBackground:@selector(getPageAccessToken) withObject:nil];
}
}



Code Explanation: Here i am initializing the graph api and authenticating the user the output wil be received in the FBGraph protocol.

Take a halt for a second and let’s see what do we have:


-        We have the user access_token which is required to get the page access_token.

-        We know that to get the page access_token you have to make a call to the me/accounts api with the user access_token as the parameter.

-        So now what we will do is get the page access_token and then post a image to the FB page.

Code to get the FB page access_token

/* This method will get the page access token from your account
To post on a page you need to have the page access token and not your profile access token
hence giving a call to the fb api to do the needful
i have used custom code here to get the page that i request, you may debug the app and see 
the facebook_response dictionary to get the page u want and modify the code as per your needs*/

- (void)getPageAccessToken
{
    NSString *urlstring = [NSString stringWithFormat:@"%@",krequestPageTokenURL];
    NSString *str = [urlstring stringByAppendingString:[NSString stringWithFormat:objFBGraph.accessToken]];
    FbGraphResponse *response = [objFBGraph doGraphGetWithUrlString:str];
    NSDictionary *facebook_response = [parser objectWithString:response.htmlResponse error:nil];
    NSString *nameofPage = [[[facebook_response valueForKey:@"data"] objectAtIndex:0] valueForKey:@"name"];
    
    //If the page name is the name on which we want to post the image with data then
    if ([nameofPage isEqualToString:kPostPageName]) 
    {
        //extract the page access token
        pageAccessToken = [[NSString alloc]initWithFormat:@"%@",[[[facebook_response valueForKey:@"data"] objectAtIndex:0] valueForKey:@"access_token"]];
        
        //and the page id
        pageID = [[NSString alloc]initWithFormat:@"%@",[[[facebook_response valueForKey:@"data"] objectAtIndex:0] valueForKey:@"id"]];

        //then post the selected image to FB page
        [self postPictureToPage];
    }
    else 
    {
        UIAlertView *objalert = [[UIAlertView alloc]initWithTitle:kAlertTitle message:kunsuccessAlert delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [objalert show];
        hideIndicator();
        //clear off the current session
         [self signOut];
    }
    
}




Once you have the page access_token call the method to post the image on the FB Page and heres how you will do that

/*
 This method will be called once you have the page access token and will post the image to thew page
 */
- (void)postPictureToPage
{
    NSMutableDictionary *variables = [[NSMutableDictionary alloc] init];
    objFBGraph.accessToken = [NSString stringWithFormat:@"%@",pageAccessToken];
FbGraphFile *graph_file = [[FbGraphFile alloc] initWithImage:self.imgvgalleryImage.image];
    NSString *bodyString= @"I AM RADIX";
    
    [variables setObject:graph_file forKey:@"file"];
[variables setObject:bodyString forKey:@"message"];
    
    //sending image with message here to the photo album of the page
    FbGraphResponse *fb_graph_response =  [objFBGraph doGraphPost: [pageID stringByAppendingString:@"/photos"] withPostVars:variables];
    NSDictionary *facebook_response = [parser objectWithString:fb_graph_response.htmlResponse error:nil];
    
    if ([facebook_response valueForKey:@"id"]!=nil
    {
        UIAlertView *objalert = [[UIAlertView alloc]initWithTitle:kAlertTitle message:ksuccessAlert delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil];
        [objalert show];
        hideIndicator();
        //once the posting is done then sign out the current user and kill its session
        [self signOut];
    }
    
}




Step 5: The stage is set we have the code and the FB page so what are you waiting for go the app delegate class create the instance of the view controller and hit the run button. You will get the output something like this


   

























I hope you have understood as how to post the image on to facebook page, in case if you have any queries then kindly mail me up or enter your queries as a comments.

You may download the code from here.

Join us on facebook iPhone by radix Facebook group.

Until then happy iCoding.

Wednesday, June 13, 2012

View will appear getting called twice in iOS 5



Currently i have solved one bug which was very much irritating for me so i thought to share it with you all.

Issue: My view will appear was getting called twice in iOS 5 due to which their was a twice call made to the web service resulting in duplication of data.

Solution:

What i had is a tab bar controller and to make a call to the viewWillAppear method in iOS 4 i made a use of the delegate method of the tab bar controller as per the UITabbarController protocol documentation



- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
    
     [viewController viewWillAppear:NO];
    
}


all was going well when suddenly my QA said to me that the duplication of data is still occuring, after a lot of research on this topic i made a quick fix here with of course a little advice from one of my friend and this is what i did


- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
    int osversion = [[[UIDevice currentDevice]systemVersion] intValue];
    
    if (osversion < 5
    {
         [viewController viewWillAppear:NO];
    }
}

Explanation: in iOS 4 the view will appear gets called only one time but i wanted a frequent call to this method hence i used the delegate method of the tab bar controller thinking that this could the solution but rather than solving the problem i increased it.

In iOS 5 their is no need to manually call or take help of any delegate method to make a call to the view will appear method so i made a small change in the delegate code and solved the issue and that was to check the system version and if its iOS 4 then only make a call to the view will appear method of the selected view controller from the delegate method of the tab bar controller.

This approach did the trick and solved the issue, and finally i don't have to see any duplicated data in my app anymore.


I solved the issue using the above method in case if you have any cool code that did the job for you would be glad if you could share the idea via comment or you may mail me to my mail id.


Until then happy iCoding and have a great day...