I am going to fetch four or multiple records of from facebook through graph api with batch request like this
NSString *jsonRequest1 = #"{ \"method\": \"GET\", \"relative_url\": \"133028623426021\" }";
NSString *jsonRequest2 = #"{ \"method\": \"GET\", \"relative_url\": \"152881298125928\" }";
NSString *jsonRequest3 = #"{ \"method\": \"GET\", \"relative_url\": \"20870926514\" }";
NSString *jsonRequest4 = #"{ \"method\": \"GET\", \"relative_url\": \"124551187593106\" }";
NSString *jsonRequestsArray = [NSString stringWithFormat:#"[ %#, %#, %#, %# ]", jsonRequest1, jsonRequest2,jsonRequest4,jsonRequest3];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObject:jsonRequestsArray forKey:#"batch"];
FbGraphResponse *fb_graph_response1 = [fbGraph doGraphPost:jsonRequestsArray withPostVars:params];
NSLog(#"%#",fb_graph_response1.htmlResponse);
But my response is like this
response =
How can i get response through graph api with batch request?
For request_ids, you do not need to create a batch request. You can simply pass them as a comma separate list and avoid doing a batch request.
NSString *requestIds = #"123456789,987654321";
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObject:requestIds forKey:#"ids"];
[facebook requestWithGraphPath:#"" andParams:params andDelegate:self];
Your final graph URL wants to look like:
https://graph.facebook.com/?ids=REQUEST_ID1,REQUEST_ID2,REQUEST_ID3&access_token=ACCESS_TOKEN
Related
I'm trying to use a service of DocuSign API in an objective C project. This link shows what data I've to add to body but I'm still starting with objective C development and I can't know how do it.
I tried the following but I received nil data
NSDictionary *EnvelopesStatusRequestData = #{#"envelopeIds": envelopesPending};
where envelopesPending is an array that I fill with envelopesId that I have in a DDBB.
NSMutableArray *envelopesPending = [NSMutableArray array];
This is the code that I use to call service API:
NSDictionary *authenticationHeader = #{ #"Username": email, #"Password" : password, #"IntegratorKey" : integratorKey };
NSDictionary *EnvelopesStatusRequestData = #{#"envelopeIds": envelopesPending};
NSData* dataStatus = [[self jsonStringFromObject:EnvelopesStatusRequestData] dataUsingEncoding:NSUTF8StringEncoding];
NSString *envelopesURL = [NSMutableString stringWithFormat:#"%#/envelopes/status",baseUrl];
NSMutableURLRequest *envelopeRequest = [self initializeRequest:envelopesURL setMethod:#"GET" setBody:dataStatus];
[envelopeRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
[envelopeRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLResponse *envelopesResponse = nil;
NSError *envelopesError = nil;
NSData *envelopeData = [NSURLConnection sendSynchronousRequest:envelopeRequest returningResponse:&envelopesResponse error:&envelopesError];
EDIT:
The error was that is a PUT method, so the request is:
NSMutableURLRequest *envelopeRequest = [self initializeRequest:envelopesURL setMethod:#"PUT" setBody:dataStatus];
With this change I have an error that says:
errorCode = "INVALID_REQUEST_PARAMETER";
message = "The request contained at least one invalid parameter. Query parameter 'from_date' must be set to a valid DateTime, or 'envelope_ids' or 'transaction_ids' must be specified.";
This error is solved adding the envelope_ids parameter to request:
PUT https://{server}/restapi/{apiVersion}/accounts/{accountId}/envelopes/status?envelope_ids=request_body
I pass the dictionary to a string with this code:
NSData *dataEnv = [NSJSONSerialization dataWithJSONObject:envelopesPending options:NSJSONReadingMutableLeaves error:&error];
NSString *querystring = [[NSString alloc] initWithData:dataEnv encoding:NSUTF8StringEncoding];
querystring = [querystring stringByReplacingOccurrencesOfString:#"[" withString:#""];
querystring = [querystring stringByReplacingOccurrencesOfString:#"]" withString:#""];
querystring = [querystring stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSString *envelopesURL = [NSMutableString stringWithFormat:#"%#/envelopes/status?envelope_ids=%#",baseUrl, querystring];
It looks like you've figured this out, but basically here are the details of the REST API call you need to make:
Get Envelope Status for more than One Envelope
This returns envelope status for the requested envelopes.
URL:
/accounts/{accountId}/envelopes/status
Formats:
XML, JSON
HTTP Method:
PUT
Required URL Parameter:
?envelope_ids=request_body
Request Body:
{
"envelopeIds":[
"String content",
"String content"
],
}
So a sample request would look like:
PUT https://{server}/restapi/{apiVersion}/accounts/{accountId}/envelopes/status?envelope_ids=request_body
X-DocuSign-Authentication: <DocuSignCredentials><Username>{name}</Username><Password>{password}</Password><IntegratorKey>{integrator_key}</IntegratorKey></DocuSignCredentials>
Accept: application/json
Content-Type: application/json
{
"envelopeIds":[
"12af49cd-....................",
"b342c324-...................."
],
}
The error was that is a PUT method, so the request is:
NSMutableURLRequest *envelopeRequest = [self initializeRequest:envelopesURL setMethod:#"PUT" setBody:dataStatus];
With this change I have an error that says:
errorCode = "INVALID_REQUEST_PARAMETER"; message = "The request contained at least one invalid parameter. Query parameter 'from_date' must be set to a valid DateTime, or 'envelope_ids' or 'transaction_ids' must be specified.";
This error is solved adding the envelope_ids parameter to request:
PUT https://{server}/restapi/{apiVersion}/accounts/{accountId}/envelopes/status?envelope_ids=request_body
I pass the dictionary to a string with this code:
NSData *dataEnv = [NSJSONSerialization dataWithJSONObject:envelopesPending options:NSJSONReadingMutableLeaves error:&error];
NSString *querystring = [[NSString alloc] initWithData:dataEnv encoding:NSUTF8StringEncoding];
querystring = [querystring stringByReplacingOccurrencesOfString:#"[" withString:#""];
querystring = [querystring stringByReplacingOccurrencesOfString:#"]" withString:#""];
querystring = [querystring stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSString *envelopesURL = [NSMutableString stringWithFormat:#"%#/envelopes/status?envelope_ids=%#",baseUrl, querystring];
I have an application in which I am having a json response like this.
{"success":"true","message":"You have logged in","pserial":"1"} and I am separating with ":".
And I am getting data like this pSerial:"1"} but I want only 1 value.
NSURL *url = [NSURL URLWithString:strUrl];
NSData *respData = [NSData dataWithContentsOfURL:url];
NSString *strResp = [[NSString alloc]initWithData:respData encoding:NSUTF8StringEncoding];
NSString *approvalString = [[strResp componentsSeparatedByString:#":"] objectAtIndex:3];
NSLog(#"pSerial:%#",approvalString);
for Example :
SBJsonParser *jsonPar = [[SBJsonParser alloc] init];
NSError *error = nil;
NSArray *jsonObj = [jsonPar objectWithString:jsonString error:&error];
id jsonObj = [jsonPar objectWithString:jsonString error:&error];
if ([jsonObj isKindOfClass:[NSDictionary class]])
// treat as a dictionary, or reassign to a dictionary ivar
else if ([jsonObj isKindOfClass:[NSArray class]])
// treat as an array or reassign to an array ivar.
Then get the value :
NSMutableArrary *userMutArr = [NSMutableArray array];
for (NSDictionary *dict in jsonObj)
{
User *userObj = [[[User alloc] init] autorelease];
[userObj setFirstName:[dict objectForKey:#"firstName"]];
[userObj setLastName:[dict objectForKey:#"lastName"]];
[userObj setAge:[[dict objectForKey:#"age"] intValue]];
[userObj setAddress:[dict objectForKey:#"address"]];
[userObj setPhoneNumbers:[dict objectForKey:#"phoneNumber"]];
[userMutArr addObject:userObj];
}
Hope you will understand. and read some Documents. it will help you.
It looks like you are in need of JSON Parsing. Here, what you want is JSON Parsing, not separating data from the JSON Response. JSON is the format of the data in which data is formatted in Key-Value pairs. You can fetch the "Value" of any object using the "Key".
Your first two lines are correct.
NSURL *url = [NSURL URLWithString:strUrl];
NSData *respData = [NSData dataWithContentsOfURL:url];
Now, you can parse JSON Response like this :
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:respData options:kNilOptions error:&error];
NSString *pSerial = [json objectForKey:#"pserial"];
This will give you the value of "pserial" from your response. Similarly, you can get the values for "success" and "message". You can check it using this line :
NSLog(#"pserial :: %#",pserial);
You need to parse the JSON Response String, you can use any JSON parser like:
https://github.com/stig/json-framework/
And in your code do:
NSString *strResp = [[NSString alloc]initWithData:respData encoding:NSUTF8StringEncoding];
NSDictionary *ResponseDictionary = [strResp JSONValue];
NSString * pSerial = (NSString*)[ResponseDictionary objectForKey:#"pserial"];
Dont separation by ":" just use JSONValue your response is like
// {"success":"true","message":"You have logged in","pserial":"1"}
// with SBJsonParser parse your object like this
NSDictionary *responseJson = [YOUR-OBJECT JSONValue];
Note: dont forget to add Json header file
Its better you use any OpenSource Json Parser
Here is a stack post Comparison of different Json Parser for iOS
I use Flickr API for my app to manage user's photo. I decided to make authentication using Apple's classes and it works fine for me. Now my app is authenticated and has all necessary tokens and secret keys so it's possible to perform GET requests with authentication for methods like flickr.photos.search, flickr.test.login and so on.
But I spent a few days trying to perform upload using http://api.flickr.com/services/upload/
and their instructions here.
They say that request should have argument 'photo' and this parameter should not be included in the signature. That is clear, but I have no idea how to implement this parameter the request.
#import "FlickrUploader.h"
#import "HMACSH1.h"
#import "Prefs.h"
#import "NSString+URLEncode.h"
#implementation FlickrUploader
- (void)uploadPhotoAtPath:(NSString*)filePath {
NSString *upload_api_url = #"http://api.flickr.com/services/upload/";
NSString *oauth_nonce = [NSString stringWithFormat:#"%d", 10000000 + arc4random()%1000000];
NSString *oauth_timestamp = [NSString stringWithFormat:#"%d", (long)[[NSDate date] timeIntervalSince1970]];
NSString *oauth_consumer_key = CONSUMER_KEY;
NSString *oauth_signature_method = #"HMAC-SHA1";
NSString *oauth_version = #"1.0";
NSString *oauth_token = [[NSUserDefaults standardUserDefaults] objectForKey:OAUTH_ACCESS_TOKEN_KEY];
//creating basestring to make signature without a 'photo' argument according to API
NSMutableString *basestring = [[NSMutableString alloc] initWithCapacity:8];
[basestring appendFormat:#"&oauth_consumer_key=%#",oauth_consumer_key];
[basestring appendFormat:#"&oauth_nonce=%#",oauth_nonce];
[basestring appendFormat:#"&oauth_signature_method=%#",oauth_signature_method];
[basestring appendFormat:#"&oauth_timestamp=%#",oauth_timestamp];
[basestring appendFormat:#"&oauth_token=%#", oauth_token];
[basestring appendFormat:#"&oauth_version=%#",oauth_version];
//this is may class to make HMAC-SHA1 signature (it works for authentication and for GET requests)
HMACSH1 *hMACSH1 = [[HMACSH1 alloc] init];
NSMutableString *urlEncodedBaseString = [[NSMutableString alloc] initWithCapacity:3];
[urlEncodedBaseString appendString:#"POST"];
[urlEncodedBaseString appendFormat:#"&%#",[upload_api_url urlEncodedString]];
[urlEncodedBaseString appendFormat:#"&%#",[basestring urlEncodedString]];
NSString *oauth_token_secret = [[NSUserDefaults standardUserDefaults] objectForKey:OAUTH_TOKEN_SECRET_KEY];
NSString *hash_key = [CONSUMER_SECRET stringByAppendingFormat:#"&%#",oauth_token_secret];
NSString *oauth_signature = [hMACSH1 hmacSH1base64ForData:urlEncodedBaseString keyValue:hash_key];
//creating url for request
NSMutableString *urlString = [[NSMutableString alloc] initWithCapacity:8];
[urlString appendFormat:#"%#",upload_api_url];
[urlString appendFormat:#"?"];
[urlString appendString:basestring];
[urlString appendFormat:#"&oauth_signature=%#", oauth_signature];
NSURL *authURL = [[NSURL alloc] initWithString:urlString];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:authURL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
request.HTTPMethod = #"POST";
UIImage *img = [UIImage imageNamed:filePath];
NSData *imgData = UIImageJPEGRepresentation(img, 0.8);
//here I don't know what to do :((( perhaps NSOutputStream
}
I had done following code with reference to following link to create batch request for uploading multiple photos in Facebook.
I had got some solution for uploading multiple photos on Facebook through this Facebook graph API.
CODE:
NSString *jsonRequest1 = #"{ \"method\": \"POST\", \"relative_url\": \"me/photos\" , \"body\": \"Hello 1\", \"attached_files\": \"file1\" }";
NSString *jsonRequest2 = #"{ \"method\": \"POST\", \"relative_url\": \"me/photos\" , \"body\": \"Hello 2\", \"attached_files\": \"file2\" }";
NSString *jsonRequestsArray = [NSString stringWithFormat:#"[ %#, %# ]", jsonRequest1, jsonRequest2];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:jsonRequestsArray,#"batch",nil];
[params setObject:UIImagePNGRepresentation(self.image1) forKey:#"file1"];
[params setObject:UIImagePNGRepresentation(self.image2) forKey:#"file2"];
[objFacebook requestWithGraphPath:#"me" andParams:params andHttpMethod:#"POST" andDelegate:self];
Now when I am running this code I got the following output.
Result Dictionary in - (void)request:(FBRequest *)request didLoad:(id)result
(
{
body = "{\"error\":0,\"error_description\":\"File file1 has not been attached\"}";
code = 400;
headers = (
{
name = "HTTP/1.1";
value = "400 Bad Request";
},
{
name = "Content-Type";
value = "text/javascript; charset=UTF-8";
}
);
},
{
body = "{\"error\":0,\"error_description\":\"File file2 has not been attached\"}";
code = 400;
headers = (
{
name = "HTTP/1.1";
value = "400 Bad Request";
},
{
name = "Content-Type";
value = "text/javascript; charset=UTF-8";
}
);
}
)
I don't know how this files attached.. Can anyone help me to figure out this problem.
Is there any change in my code then please let me know.
Thanks in advance...
I recommend you use the new integrated Facebook API's in iOS 6 to do this instead of Facebook's API: https://developer.apple.com/videos/wwdc/2012/?id=306 there's a golden WWDC video for all social tasks. Plus using the new API's in iOS 6 is MUCH faster then using Facebooks.
For your NSDictionary of parameters ,use the NSData representation, instead of directly using the UIImage object.
Depending on the compression format of the images you are trying to upload, you'll need to use a different method to convert the UIImage to NSData. Here are two techniques, one for PNG and one for JPEG
//...cut...
[params setObject:UIImageJPEGRepresentation(self.jpegImage, 0.8) forKey:#"file1"];
[params setObject:UIImagePNGRepresentation(self.pngImage) forKey:#"file2"];
//...cut...
This is a tutorial from the Facebook Developer blog that shows something similar (although it is for a video, and not the batch API), and one significant difference from your code is that the parameter passed is in NSData representation, not UIImage.
http://developers.facebook.com/blog/post/532/
[params setObject:UIImagePNGRepresentation(self.image1) forKey:#"file1"];
This should not be the data, it should be the path for that images. It will work fine if you provide a path instead of NSData.
I got the solution for multiple file upload using FBgraph.
here is my code.
-(void) fbGraphCallback
{
FbGraphFile *graph_file = [[FbGraphFile alloc]initWithImage:imgView1.image];
FbGraphFile *graph_file1 = [[FbGraphFile alloc]initWithImage:imgView2.image];
NSString *jsonRequest1 = #"{ \"method\": \"POST\", \"relative_url\": \"me/photos\" , \"body\": \"First Image\", \"attached_files\": \"file1\" }";
NSString *jsonRequest2 = #"{ \"method\": \"POST\", \"relative_url\": \"me/photos\" , \"body\": \"Second Image\", \"attached_files\": \"file2\" }";
NSString *jsonRequestsArray = [NSString stringWithFormat:#"[ %#, %# ]", jsonRequest1, jsonRequest2];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:jsonRequestsArray,#"batch",nil];
[params setObject:graph_file forKey:#"file1"];
[params setObject:graph_file1 forKey:#"file2"];
[fbgraph doGraphPost:#"" withPostVars:params];
}
Thanks mehul.
You are adding the binary to the Dictionary incorrectly. Take a look at the file upload method in Facebook's sample app. You should be able to easily adopt Facebook's sample code to your app.
/**
* Upload a photo.
*/
-(IBAction)uploadPhoto:(id)sender
{
NSString *path = #"http://www.facebook.com/images/devsite/iphone_connect_btn.jpg";
NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
img, #"picture",
nil];
[_facebook requestWithMethodName:#"photos.upload"
andParams:params
andHttpMethod:#"POST"
andDelegate:self];
[img release];
}
I want to upload video from my app to the youtube. I am using the example YoutubeTest for this purpose. I have set the developer key and client Id for my app. Now when trying to upload the video using example source code, it shows an error which is:
2012-03-19 10:51:07.947 YouTubeTest[539:f803] serviceBase: objectFetcher: failedWithStatus:400 data:
2012-03-19 10:51:07.985 YouTubeTest[539:f803] Error: Error Domain=com.google.GDataServiceDomain Code=400 "The operation couldn’t be completed. (com.google.GDataServiceDomain error 400.)" UserInfo=0x6c49e50 {}
Has anyone successfully implemented the GData to upload videos to youtube from the iphone app. Can anyone give me the example source code.
Yes ofcourse many had successfully implemented it ... hmmm try this link http://urinieto.com/category/google/ follow instructions line by line.
Not Sure y you are getting this error. Follow above instructions if problem still persists i will help you out .
Cheers
I am having the same issue with YouTubeTest app. here is the code for request:
(IBAction)uploadPressed:(id)sender {
NSString *devKey = [mDeveloperKeyField text];
GDataServiceGoogleYouTube *service = [self youTubeService];
[service setYouTubeDeveloperKey:devKey];
NSString *username = [mUsernameField text];
NSString *clientID = [mClientIDField text];
NSURL *url = [GDataServiceGoogleYouTube youTubeUploadURLForUserID:username
clientID:clientID];
// load the file data
NSString *path = [[NSBundle mainBundle] pathForResource:#"YouTubeTest" ofType:#"m4v"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSString *filename = [path lastPathComponent];
// gather all the metadata needed for the mediaGroup
NSString *titleStr = [mTitleField text];
GDataMediaTitle *title = [GDataMediaTitle textConstructWithString:titleStr];
NSString *categoryStr = [mCategoryField text];
GDataMediaCategory *category = [GDataMediaCategory mediaCategoryWithString:categoryStr];
[category setScheme:kGDataSchemeYouTubeCategory];
NSString *descStr = [mDescriptionField text];
GDataMediaDescription *desc = [GDataMediaDescription textConstructWithString:descStr];
NSString *keywordsStr = [mKeywordsField text];
GDataMediaKeywords *keywords = [GDataMediaKeywords keywordsWithString:keywordsStr];
BOOL isPrivate = mIsPrivate;
GDataYouTubeMediaGroup *mediaGroup = [GDataYouTubeMediaGroup mediaGroup];
[mediaGroup setMediaTitle:title];
[mediaGroup setMediaDescription:desc];
[mediaGroup addMediaCategory:category];
[mediaGroup setMediaKeywords:keywords];
[mediaGroup setIsPrivate:isPrivate];
NSString *mimeType = [GDataUtilities MIMETypeForFileAtPath:path
defaultMIMEType:#"video/mp4"];
// create the upload entry with the mediaGroup and the file data
GDataEntryYouTubeUpload *entry;
entry = [GDataEntryYouTubeUpload uploadEntryWithMediaGroup:mediaGroup
data:data
MIMEType:mimeType
slug:filename];
SEL progressSel = #selector(ticket:hasDeliveredByteCount:ofTotalByteCount:);
[service setServiceUploadProgressSelector:progressSel];
GDataServiceTicket *ticket;
ticket = [service fetchEntryByInsertingEntry:entry
forFeedURL:url
delegate:self
didFinishSelector:#selector(uploadTicket:finishedWithEntry:error:)];
[self setUploadTicket:ticket];
}
Solved my problem. The error info in your case is not enough. But if you print out the HTTPURLResponse from the server , it will help to spot the error. In my case keywords length was too long.
I faced the same error. But I did find a solution through trial and error :)
Actually as Youtube itself states
You don't need to provide Client_Id anymore. Please remove it.
But the actual problem was with the login credentials. API was returning error response when i login as "xyz#gmail.com". It started working when i provided just the username without domain "xyz".
Hope this helps!