2

Google Reader API を利用したアプリを作りたいです。しかし、そのための公式 API がないことがわかりました。App Store のガイドライン/承認に関して、非公式 API の使用に問題はありますか? 他のアプリ (Reeder など) はこれを使用しますか?

また、ログインするための最良の方法は何ですか? 推奨される方法は OAuth ですか? Janrain を使用することは良い考えですか?

4

2 に答える 2

7

率直に言って、Apple は、Google の非公式 API を使用するかどうかは気にしません。

私は、同期に Google リーダーを使用する RSS リーダー アプリの顧客のために働いていました。OAuth は使用しませんでしたが、さまざまなリーダー URL への連続した呼び出しで使用するトークンを抽出する必要がある Cookie を返す標準の HTTP ログインを使用しました。

私の(古い)概念実証アプリからのログインコードを投稿できます。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 リーダーとそのプライベート API に関する興味深い記事はhttp://timbroder.com/2007/08/google-reader-api-functions.htmlです。

最新のコメントを必ずお読みください:)

/edit: auth ヘッダー (Google が今年 6 月に導入したもの) を使用するようにコードを更新しました。OAuth を使用する場合は、これが OAuth トークンを配置する場所になると思います。推測してみて

于 2010-09-22T10:53:26.360 に答える
6

「Google Data API Objective-C クライアント ライブラリは、iPhone 静的ライブラリ、Mac OS X フレームワーク、および Google Data API を介してデータに簡単にアクセスできるソース コードを提供します。」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を確認すると、非常に役立ちます。


アップデート

それ以来、この手法が最良/軽量/複雑でないことがわかりました: ネイティブ Google リーダー iPhone アプリケーション

于 2010-11-03T06:59:16.840 に答える