2

我想制作一个在 Google Reader API 上使用的应用程序。但我发现它没有官方 API - 就 App Store 指南/批准而言,使用非官方 API 是否有问题?其他应用程序(Reeder 等)会使用这个吗?

另外登录的最佳方法是什么?OAuth 是首选方法吗?使用 Janrain 是个好主意吗?

4

2 回答 2

7

坦率地说,Apple 不在乎你是否使用 Google 的非官方 API。

我为使用 Google Reader 进行同步的 RSS 阅读器应用程序的客户工作。我们没有使用 OAuth,而是使用标准 HTTP 登录,它返回一个 cookie,您必须从中提取一个令牌,以便在对各种阅读器 URL 的连续调用中使用。

我可以从我的(旧)概念证明应用程序中向您发布登录代码。它使用 ASIHTTP 和一些自定义字符串类别。这个想法是发送登录请求,获取响应并从响应的 cookie 标头中提取会话 ID/身份验证代码。然后,您可以使用该会话 ID/身份验证代码进行连续呼叫。

#pragma mark -
#pragma mark login

//this is your sessionID token you get from the login
//use this in consecutive calls to google reader
//this method returns you the header string you have to add to your request
//[request addRequestHeader: @"Cookie" value: [self sidHeader]];
- (NSString *) sidHeader
{
    return [NSString stringWithFormat: @"SID=%@", [self sid]];
}

- (NSString *) authHeader
{
    return [NSString stringWithFormat: @"GoogleLogin auth=%@",[self auth]];
}


//login to your google account and get the session ID
- (void) login
{
    NSString *username = @"my.googlelogin@gmail.com";
    NSString *password = @"mypassword123";
    NSString *loginUrl = @"https://www.google.com/accounts/ClientLogin?client=NNW-Mac";
    NSString *source = @"NNW-Mac"; //let's fake NetNewsWire
    NSString *continueUrl = @"http://www.google.com";

    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString: loginUrl]]; // log in & get cookies
    [request addRequestHeader: @"User-Agent" value: @"NetNewsWire/3.2b25 (Mac OS X; http://www.newsgator.com/Individuals/NetNewsWire/)"];

    [request setPostValue: username forKey: @"Email"];
    [request setPostValue: password forKey: @"Passwd"];
    [request setPostValue: @"reader" forKey: @"service"];
    [request setPostValue: source forKey: @"source"];
    [request setPostValue: continueUrl forKey: @"continue"];

    [request setDelegate: self];
    [request setDidFailSelector: @selector(loginRequestFailed:)];
    [request setDidFinishSelector: @selector(loginRequestFinished:)];

    [request start];
}   

-(void)loginRequestFinished:(ASIHTTPRequest *)request
{
    NSString *responseString = [request responseString];

    //login failed
    if ([responseString containsString: @"Error=BadAuthentication" ignoringCase: YES])
    {
        [self setLastError: [self errorWithDescription: @"Bad Username/Passsword" code: 0x001 andErrorLevel: 0x00]];

        if ([delegate respondsToSelector: @selector(gReaderLoginDidFail:)])
        {
            [delegate gReaderLoginDidFail: self];
        }

        return NO;
    }

    //captcha required
    if ([responseString containsString: @"CaptchaRequired" ignoringCase: YES])
    {
        [self setLastError: [self errorWithDescription: @"Captcha Required" code: 0x001 andErrorLevel: 0x00]];

        if ([delegate respondsToSelector: @selector(gReaderLoginDidFail:)])
        {
            [delegate gReaderLoginDidFail: self];
        }

        return NO;
    }

    //extract SID + auth
    NSArray *respArray = [responseString componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]];

    NSString *sidString = [respArray objectAtIndex: 0];
    sidString = [sidString stringByReplacingOccurrencesOfString: @"SID=" withString: @""];
    [self setSid: sidString];

NSString *authString = [respArray objectAtIndex: 2];
authString = [authString stringByReplacingOccurrencesOfString: @"Auth=" withString: @""];
[self setAuth: authString];
    //mesage delegate of success
    if ([delegate respondsToSelector: @selector(gReaderLoginDidSucceed:)])
    {
        [delegate gReaderLoginDidSucceed: self];
    }

    return YES;
}

- (void)loginRequestFailed:(ASIHTTPRequest *)request
{
    NSError *error = [request error];

    //NSLog(@"login request failed with error: %@", [error localizedDescription]);
    [self setLastError: error];

    if ([delegate respondsToSelector: @selector(gReaderLoginDidFail:)])
    {
        [delegate gReaderLoginDidFail: self];
    }

}

登录后,您可以使用 sid 和 auth 伪造对 Reader API 端点的请求。

例子:

- (ASIHTTPRequest *) requestForAPIEndpoint: (NSString *) apiEndpoint
{
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString: apiEndpoint]];
    [request addRequestHeader: @"User-Agent" value: @"NetNewsWire/3.2b25 (Mac OS X; http://www.newsgator.com/Individuals/NetNewsWire/)"];
    [request addRequestHeader: @"Cookie" value: [self sidHeader]];
    [request addRequestHeader: @"Authorization" value: [self authHeader]];

    return request;
}

关于 Google Reader 及其私有 API 的有趣读物是http://timbroder.com/2007/08/google-reader-api-functions.html

请务必阅读最新评论:)

/edit:我更新了代码以使用 auth 标头(谷歌在今年 6 月推出)。如果您使用 OAuth,我想这将是放置您的 OAuth 令牌的地方。猜测

于 2010-09-22T10:53:26.360 回答
6

我后来发现:“Google Data APIs Objective-C Client Library 提供了一个 iPhone 静态库、一个 Mac OS X 框架和源代码,可以轻松通过 Google Data APIs 访问数据。” code.google.com/p /gdata-objectivec-client - 太棒了!但是,它不包括 Reader API(因为它尚未发布)。

我已经能够通过更改来访问 API(在 OAuthSampleTouch 示例中)

NSString *scope = @"http://www.google.com/m8/feeds/";

在 OAuthSampleRootViewControllerTouch.m 到

NSString *scope = @"http://www.google.com/reader/api/*";

urlStr = @"http://www.google.com/m8/feeds/contacts/default/thin";

urlStr = @"http://www.google.com/reader/atom/user/-/label/Design";

其中 Design 是一个文件夹名称 - 检查这个http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI它有很大的帮助。


更新

从那以后,我发现这种技术是最好的/最轻的/不太复杂的: Native Google Reader iPhone Application

于 2010-11-03T06:59:16.840 回答