原生的 Google Reader iPhone 应用程序

3
我目前正在构建一个本地的Google Reader iPhone应用程序,类似于成功的应用程序“Reeder for iPhone”,但是还内置了完整的Twitter客户端。
我已经完成了Twitter客户端,现在正在努力启动Google Reader客户端。我浏览了多个文档,并查看了gdata-objective-client样例,但仍无法理解如何实现与Reeder相同的功能。
基本上,我想能够向用户呈现登录屏幕。然后,用户提交他们的凭据,访问令牌等都是在背景幕后完成的,就像Twitter的xAuth一样。然后,我想推送一个视图控制器,显示带有所有当前未读源的UITableView。当用户单击UITableViewCell时,将分别推入包含帖子内容的详细视图。
这可行吗?如果可以,我该如何实现这些功能?如果人们发布“代码片段”并实际展示如何实现实现,我会非常感激。
提前感谢!
编辑:已经引起我的注意,不需要使用Google应用引擎。然而,问题仍然是一样的。我该如何将Google Reader实现到我的应用程序中?

为什么这被标记为Google App Engine? - Thilo
因为根据我所了解的,它需要以某种方式实现谷歌应用引擎?除非您能够帮忙并指导我正确的方向? - Sebastien Peek
App Engine是用于构建Web应用程序的基础设施 - 它与纯客户端iPhone应用程序无关。 - Nick Johnson
我该如何将Google Reader API集成到我的应用程序中呢? - Sebastien Peek
3个回答

9

非常简单。对于所有想了解如何连接Google Reader API的人,我按照以下步骤进行操作。

/*  Google clientLogin API:
     Content-type: application/x-www-form-urlencoded
     Email=userName
     Passwd=password
     accountType=HOSTED_OR_GOOGLE
     service=xapi
     source = @"myComp-myApp-1.0"
     */

    //define our return objects
    BOOL authOK;
    NSString *authMessage = [[NSString alloc] init];
    NSArray *returnArray = nil;
    //begin NSURLConnection prep:
    NSMutableURLRequest *httpReq = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:GOOGLE_CLIENT_AUTH_URL] ];
    [httpReq setTimeoutInterval:30.0];
    //[httpReq setCachePolicy:NSURLRequestReloadIgnoringCacheData];
    [httpReq setHTTPMethod:@"POST"];
    //set headers
    [httpReq addValue:@"Content-Type" forHTTPHeaderField:@"application/x-www-form-urlencoded"];
    //set post body
    NSString *requestBody = [[NSString alloc] 
                             initWithFormat:@"Email=%@&Passwd=%@&service=reader&accountType=HOSTED_OR_GOOGLE&source=%@",
                             gUserString, gPassString, [NSString stringWithFormat:@"%@%d", gSourceString]];

    [httpReq setHTTPBody:[requestBody dataUsingEncoding:NSASCIIStringEncoding]];

    NSHTTPURLResponse *response = nil;
    NSError *error = nil;
    NSData *data = nil;
    NSString *responseStr = nil;
    NSArray *responseLines = nil;
    NSString *errorString;
    //NSDictionary *dict;
    int responseStatus = 0;
    //this should be quick, and to keep same workflow, we'll do this sync.
    //this should also get us by without messing with threads and run loops on Tiger.
    data = [NSURLConnection sendSynchronousRequest:httpReq returningResponse:&response error:&error];

    if ([data length] > 0) {
        responseStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
        //NSLog(@"Response From Google: %@", responseStr);
        responseStatus = [response statusCode];
        //dict = [[NSDictionary alloc] initWithDictionary:[response allHeaderFields]];
        //if we got 200 authentication was successful
        if (responseStatus == 200 ) {
            authOK = TRUE;
            authMessage = @"Successfully authenticated with Google. You can now start viewing your unread feeds.";
        }
        //403 = authentication failed.
        else if (responseStatus == 403) {
            authOK = FALSE;
            //get Error code.
            responseLines  = [responseStr componentsSeparatedByString:@"\n"];
            //find the line with the error string:
            int i;
            for (i =0; i < [responseLines count]; i++ ) {
                if ([[responseLines objectAtIndex:i] rangeOfString:@"Error="].length != 0) {
                    errorString = [responseLines objectAtIndex:i] ;
                }
            }

            errorString = [errorString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
            /*
             Official Google clientLogin Error Codes:
             Error Code Description
             BadAuthentication  The login request used a username or password that is not recognized.
             NotVerified    The account email address has not been verified. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
             TermsNotAgreed The user has not agreed to terms. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
             CaptchaRequired    A CAPTCHA is required. (A response with this error code will also contain an image URL and a CAPTCHA token.)
             Unknown    The error is unknown or unspecified; the request contained invalid input or was malformed.
             AccountDeleted The user account has been deleted.
             AccountDisabled    The user account has been disabled.
             ServiceDisabled    The user's access to the specified service has been disabled. (The user account may still be valid.)
             ServiceUnavailable The service is not available; try again later.
             */

            if ([errorString  rangeOfString:@"BadAuthentication" ].length != 0) {
                authMessage = @"Please Check your Username and Password and try again.";
            }else if ([errorString  rangeOfString:@"NotVerified"].length != 0) {
                authMessage = @"This account has not been verified. You will need to access your Google account directly to resolve this";
            }else if ([errorString  rangeOfString:@"TermsNotAgreed" ].length != 0) {
                authMessage = @"You have not agreed to Google terms of use. You will need to access your Google account directly to resolve this";
            }else if ([errorString  rangeOfString:@"CaptchaRequired" ].length != 0) {
                authMessage = @"Google is requiring a CAPTCHA response to continue. Please complete the CAPTCHA challenge in your browser, and try authenticating again";
                //NSString *captchaURL = [responseStr substringFromIndex: [responseStr rangeOfString:@"CaptchaURL="].length]; 
                //either open the standard URL in a browser, or show a custom sheet with the image and send it back...
                //parse URL to append to GOOGLE_CAPTCHA_URL_PREFIX
                //but for now... just launch the standard URL.
                //[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:GOOGLE_CAPTCHA_STANDARD_UNLOCK_URL]];         
            }else if ([errorString  rangeOfString:@"Unknown" ].length != 0) {
                authMessage = @"An Unknow error has occurred; the request contained invalid input or was malformed.";
            }else if ([errorString  rangeOfString:@"AccountDeleted" ].length != 0) {
                authMessage = @"This user account previously has been deleted.";
            }else if ([errorString  rangeOfString:@"AccountDisabled" ].length != 0) {
                authMessage = @"This user account has been disabled.";
            }else if ([errorString  rangeOfString:@"ServiceDisabled" ].length != 0) {
                authMessage = @"Your access to the specified service has been disabled. Please try again later.";
            }else if ([errorString  rangeOfString:@"ServiceUnavailable" ].length != 0) {
                authMessage = @"The service is not available; please try again later.";
            }

        }//end 403 if

    }
    //check most likely: no internet connection error:
    if (error != nil) {
        authOK = FALSE;
        if ( [error domain]  == NSURLErrorDomain) {
            authMessage = @"Could not reach Google.com. Please check your Internet Connection";
        }else {
            //other error
            authMessage = [authMessage stringByAppendingFormat:@"Internal Error. Please contact notoptimal.net for further assistance. Error: %@", [error localizedDescription] ];
        }
    }
    //NSLog (@"err localized description %@", [error localizedDescription]) ;
    //NSLog (@"err localized failure reasons %@", [error localizedFailureReason]) ;
    //NSLog(@"err code  %d", [error code]) ;
    //NSLog (@"err domain %@", [error domain]) ;


    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Authentication" message:authMessage delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];
    [alertView show];
    [alertView release];

    [gUserString    release];
    [gPassString    release];
    [gSourceString  release];

    [authMessage    release];

}

}

显然我使用了自己的代理等,但这是我为我的应用程序带来的总体需求和感觉。

我目前正在努力将未读的Feed/Item拉入UITableView中,在我的RootViewController中显示。 我会更新更多信息。

感谢所有试图提供帮助的人:D


谢谢这个解决方案,我已经为此苦恼了几周。 - daihovey

2

谢谢。我知道有一个简单的登录方式,但是我一直在苦苦寻找它。顺便说一下,如果你把the0rkus上面的代码复制/粘贴,你会遇到一些错误。为了测试它,我添加了:

NSString *gUserString = @"yourlogin@gmail.com";
NSString *gPassString = @"yourpassword";
NSString *GOOGLE_CLIENT_AUTH_URL = @"https://www.google.com/accounts/ClientLogin?client=YourClient";
NSString *gSourceString = @"YourClient";

我从哪里可以获取GOOGLE_CLIENT_AUTH_URL和gSourceString???我需要在Google的网站上注册我的应用程序吗? - Shri

0

他们解释了如何在Python中使用它,但几乎没有详细说明如何在Objective-C中使用它... - Sebastien Peek
@the0rkus - 那个教程是关于PHP的...不是Python。但它应该非常易于转换。该API使用标准的HTTP请求/响应对进行通信,因此您只需要知道如何进行GET/POST请求以及如何在Objective-C中解析响应即可。如果您不知道,请在尝试与任何外部API进行接口之前学习它。 - EAMann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接