error 401 when i request to get all contacts using GDATA - ios

i am using Gdata and already suceessfully login gmail and call below method
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
finishedWithAuth:(GTMOAuth2Authentication *)auth{
if (error != nil) {
}
else{
// i got successful login here
self.auth=auth;
}
}
in above method i got Authentifacation token and etc.
Now
NSString *urlStr = #"https://www.google.com/m8/feeds/contacts/default/full";
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.auth authorizeRequest:request
completionHandler:^(NSError *error) {
NSString *output = nil;
if (error) {
output = [error description];
} else {
// Synchronous fetches like this are a really bad idea in Cocoa applications
//
// For a very easy async alternative, we could use GTMHTTPFetcher
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (data) {
// API fetch succeeded
output = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] autorelease];
} else {
// fetch failed
output = [error description];
}
}
}];
but i got error 401
please helpful me

Related

iOS: Not able to get all Google People api collection list

Following is my code to get people/contacts from google account using GIDSignIn login.
Code:
- (void)setAuthorizerForSignIn:(GIDSignIn *)signIns user:(GIDGoogleUser *)user {
GTMOAuth2Authentication *auth = [[GTMOAuth2Authentication alloc] init];
[auth setClientID:signIns.clientID];
[auth setUserEmail:user.profile.email];
[auth setUserID:user.userID];
[auth setAccessToken:user.authentication.accessToken];
[auth setRefreshToken:user.authentication.refreshToken];
[auth setExpirationDate: user.authentication.accessTokenExpirationDate];
appDelegate.authGooglePlus = auth;
NSString *urlStr = #"https://people.googleapis.com/v1/people/me/connections?pageSize=200";
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
auth.scope= #"https://www.googleapis.com/auth/contacts";
[auth authorizeRequest:request
completionHandler:^(NSError *error) {
NSString *output = nil;
if (error) {
output = [error description];
} else {
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (data) {
output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSMutableArray *array = [[output JSONValue] objectForKey:#"connections"];
}
} else {
// fetch failed
output = [error description];
}
}
}];
}
Following is my code to fetch people/contact list, but i am able to get only 7 records not all records, Any idea how to achieve that?
The Google People API only returns contacts that are in a contact group. So likely the problem is that the other records are "other contacts", which are not in any contact group and thus are not returned.
Currently there is no way to get other contacts from the Google People API.

Adding Rotten Tomates API to iphone app

Im trying to add Rotten Tomatoes API to my app but it doesn't seem to like it? What am I doing wrong?? The error says "Data Argument not used by format string"
-(void)main {
NSLog(#"Service has run");
NSString *api_key = #"j4jz49tvf76cmnb4mwfyjvyt";
NSString *search_term = [searchTerm stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *url = [NSString stringWithFormat:#"http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=j4jz49tvf76cmnb4mwfyjvyt", api_key, search_term];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *responseData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:nil];
if (responseData !=nil) {
NSError *error =nil;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions error:&error];
if (error) {
[delegate serviceFinished:self withError:YES];
} else {
results = (NSArray *) [json valueForKey:#"movies"];
[delegate serviceFinished:self withError:NO];
}
} else {
[delegate serviceFinished:self withError:YES];
}
}
#end
Your error is on this line
NSString *url = [NSString stringWithFormat:#"http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=j4jz49tvf76cmnb4mwfyjvyt", api_key, search_term];
String with format works with adding a data argument like %# in a string as a placeholder, and then replacing that with the following arguments in your method call.
What you want to do is probably something like:
NSString *url = [NSString stringWithFormat:#"http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=%#&search_term=%#", api_key, search_term];

authorizeRequest oAuth not called from another class?

I'm currently using Oauth2SampleTouch by Google, so people can log-in with their google accounts into my app. However whenever I call a method from The SampleRootViewController it doesn't go through the authorizeRequest method (only if I call it from another class.).
Here's the method in SampleRootViewController that I'm calling form another class.(the user is already logged in by this time)
-(NSString *)hasLikedVideo:(NSString *)videoID {
liked = #"NULL";
NSString *clientID = #"myClientID";
NSString *clientSecret = #"myClientSecret";
self.auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:clientID
clientSecret:clientSecret];
NSString *urlStr = [NSString stringWithFormat:#"https://www.googleapis.com/youtube/v3/videos/getRating?id=%#&key=AIzaSyB437bMtpbJh-OrkieCDRtYLe6L1Ijb3Ww", videoID];
NSLog(#"URL FOR LIKE : %# auth:(%#)", urlStr, self.auth);
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSLog(#"stage 1");
[self.auth authorizeRequest:request
completionHandler:^(NSError *error) {
if (error == nil) {
// the request has been authorized
NSLog(#"ERROR LOADING AUTH 1 : %#", [error description]);
} else {
NSLog(#"ERROR LOADING AUTH 2 : %#", [error description]);
}
NSLog(#"stage 2");
NSString *output = nil;
if (error) {
output = [error description];
NSLog(#"ERROR FROM LOADING LIKE INFO : %#", output);
} else {
NSLog(#"stage 3");
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
[self displayAlertWithMessage:output];
if (data) {
// API fetch succeeded
NSLog(#"stage 32");
output = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
// NSLog(#"%#", data);
[self displayAlertWithMessage:output];
} else {
NSLog(#"stage 34");
// fetch failed
output = [error description];
[self displayAlertWithMessage:output];
}
}
NSData* json = [output dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *allCourses = [NSJSONSerialization
JSONObjectWithData:json
options:kNilOptions
error:&error];
NSArray *monday = allCourses[#"items"];
for ( NSDictionary *theCourse in monday )
{
liked = theCourse[#"rating"];
NSLog(#"LIKE INSIDE ARRAY : %#", theCourse[#"rating"]);
}
if( error )
{
NSLog(#"%#", [error localizedDescription]);
}
}];
NSLog(#"stage 4");
return liked;
}
The method runs because I can see it log the string, however it doesn't go through the authorizeRequest, it doesn't even print out the error messages. HOWEVER if my viewController is SampleRootViewController and I call the method from itself it works.
So basically
TestViewcontroller calls a method in SampleRootViewController -> doesn't go through authorizeRequest.
SampleRootViewController calls a method in SampleRootViewController (from itself) -> goes through authorizeRequest and works.
EDIT:
I found out what I was doing "wrong"
I was calling the method like this in background
[self performSelectorInBackground:#selector(getAuthDetails) withObject:nil];
instead of
[self getAuthDetails];

NSURLConnection wrong order

I have a NSURLConnection (two of them), and they're running in the wrong order.
Here's my method:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password {
NSURL *url = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"Pin=%#&Password=%#",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from login), it was = %#", loggedInPage);
}
}
else {
NSLog(#"error: %#", error);
}
}];
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[request setHTTPMethod:#"POST"];
[NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError)
{
// do whatever with the data...and errors
if ([homeData length] > 0 && homeError == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from home), it was = %#", homePage);
}
}
else {
NSLog(#"error: %#", homeError);
}
}];
}
- (NSString *)percentEscapeString:(NSString *)string
{
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
(CFStringRef)#" ",
(CFStringRef)#":/?#!$&'()*+,;=",
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:#" " withString:#"+"];
}
So, it's two NSURLConnection's that are added to the [NSOperationQueue mainQueue]. What my output is showing me is that the second NSURLConnection is running before the first one. So it tries to go to the page where I download data before I'm logged in, so it (obviously) returns a "You're not logged in" error.
How do I schedule them one after another?
The issue, as I suspect you have realized, is that you're doing asynchronous network requests (which is good; you don't want to block the main queue), so there's no assurance of the order they'll finish.
The quickest and easiest answer is to simply put the call to the second request inside the completion block of the first one, not after it. You don't want to be making that second one unless the first one succeeded anyway.
To keep your code from getting unwieldy, separate the login from the request for main page. And you can use the completion block pattern which is common with asynchronous methods. You add a parameter to loginToMistarWithPin that specifies what it should do when the request finishes. You might have one completion block handler for success, and one for failure:
- (void)loginToMistarWithPin:(NSString *)pin password:(NSString *)password success:(void (^)(void))successHandler failure:(void (^)(void))failureHandler {
NSURL *url = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/Login"];
//Create and send request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"Pin=%#&Password=%#",
[self percentEscapeString:pin],
[self percentEscapeString:password]];
NSData * postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// do whatever with the data...and errors
if ([data length] > 0 && error == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
// assuming you validated that everything was successful, call the success block
if (successHandler)
successHandler();
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *loggedInPage = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from login), it was = %#", loggedInPage);
if (failureHandler)
failureHandler();
}
}
else {
NSLog(#"error: %#", error);
if (failureHandler)
failureHandler();
}
}];
}
- (void)requestMainPage {
//Now redirect to assignments page
NSURL *homeURL = [NSURL URLWithString:#"https://mistar.oakland.k12.mi.us/novi/StudentPortal/Home/PortalMainPage"];
NSMutableURLRequest *requestHome = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[requestHome setHTTPMethod:#"GET"]; // this looks like GET request, not POST
[NSURLConnection sendAsynchronousRequest:requestHome queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *homeResponse, NSData *homeData, NSError *homeError)
{
// do whatever with the data...and errors
if ([homeData length] > 0 && homeError == nil) {
NSError *parseError;
NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:homeData options:0 error:&parseError];
if (responseJSON) {
// the response was JSON and we successfully decoded it
NSLog(#"Response was = %#", responseJSON);
} else {
// the response was not JSON, so let's see what it was so we can diagnose the issue
NSString *homePage = [[NSString alloc] initWithData:homeData encoding:NSUTF8StringEncoding];
NSLog(#"Response was not JSON (from home), it was = %#", homePage);
}
}
else {
NSLog(#"error: %#", homeError);
}
}];
}
Then, when you want to login, you can do something like:
[self loginToMistarWithPin:#"1234" password:#"pass" success:^{
[self requestMainPage];
} failure:^{
NSLog(#"login failed");
}];
Now, change those successHandler and failureHandler block parameters to include whatever data you need to pass back, but hopefully it illustrates the idea. Keep your methods short and tight, and use completion block parameters to specify what an asynchronous method should do when it's done.
Can you check the below link. It is about forcing one operation to wait for another.
NSOperation - Forcing an operation to wait others dynamically
Hope this helps.

Making a GET request using NSURL not working

I am trying to get a simple GET request to work for my api. But it doesnt seem to work, and I am not sure why.
My code is as follows
Edit, also tried NSURLCredential But that does not seem to work either
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *urlAsString = #"https://www.test.com/api/v1/user/logout/";
NSURL *url = [NSURL URLWithString:urlAsString];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; [urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:#"GET"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response,NSData *data, NSError *error) {
if ([data length] >0 && error == nil){
NSString *html = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"HTML = %#", html); }
else if ([data length] == 0 && error == nil){
NSLog(#"Nothing was downloaded."); }
else if (error != nil){
NSLog(#"Error happened = %#", error); }
}];
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
My API spits out json. So I should be getting a json object back that says
success: False
reason: 'Already Logged out'
But instead it gives me the following error
2013-03-07 16:24:44.038 test[8957:1d03] Error happened = Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x715db20 {NSErrorFailingURLKey=https://www.test.com/api/v1/user/logout/, NSErrorFailingURLStringKey=https://www.test.com/api/v1/user/logout/, NSUnderlyingError=0x7181cb0 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1012.)"}
Method 2
after some reseach, I found another way of sending get requests, and this method seems to work fine
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSError *error = nil;
NSURL *url = [NSURL URLWithString:#"https://www.test.com/api/v1/user/logout/"];
NSString *json = [NSString stringWithContentsOfURL:url
encoding:NSASCIIStringEncoding
error:&error];
if(!error) {
NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData
options:kNilOptions
error:&error];
BOOL success = [[jsonDict objectForKey:#"success"] boolValue];
if (!success) {
NSString *reason = [jsonDict objectForKey:#"reason"];
NSLog(#"Cannot log out, as user %#", reason);
}
//NSLog(#"JSON: %#", jsonDict);
}else{
NSLog(#"\nJSON: %# \n Error: %#", json, error);
}
});
The solution to the problem was in the API itself. The API was supposed to send HTTPUnauthorized signal if the user is already logged out. And since that was the case, iOS was showing all these exceptions. when I dropped that and just sent back a simple json response, everything got fixed.

Resources