Родно приложение за iPhone на Google Reader

В момента съм в процес на създаване на родно приложение за iPhone на Google Reader, подобно на успешното приложение „Reeder за iPhone“, но също така с вграден пълен клиент за Twitter.

Завърших клиента на Twitter и сега се боря да стартирам клиента на Google Reader. Прегледах множество документи и разгледах примерите на gdata-objective-client, но все още не мога да разбера какво трябва да направя, за да постигна същата функционалност като Reeder.

По принцип искам да мога да представя на потребителя екран за вход. След това потребителят изпраща своите идентификационни данни и токена за достъп и всичко това се прави зад кулисите, както правят с xAuth на Twitter. След това искам да натисна контролер за изглед, който показва UITableView с всички текущи непрочетени емисии. Когато потребителят щракне върху UITableViewCell, съответно се извежда подробен изглед, съдържащ съдържанието на публикациите.

Възможно ли е това и ако е така, как да приложа тези функции? Ще съм благодарен, ако хората публикуват „кодови фрагменти“ и действително покажат как постигат имплементациите.

Благодаря предварително!

РЕДАКТИРАНЕ: Беше ми обърнато внимание, че не е необходима машината за приложения на Google. Въпросът обаче си остава същият. Как да внедря Google Reader в моето приложение?


person Sebastien Peek    schedule 27.09.2010    source източник
comment
защо това е маркирано с google-app-engine?   -  person Thilo    schedule 27.09.2010
comment
защото от това, което прочетох, трябва по някакъв начин да внедри двигателя на приложението на Google? освен ако не можете да помогнете и да ме насочите в правилната посока?   -  person Sebastien Peek    schedule 27.09.2010
comment
App Engine е инфраструктура за изграждане на уеб приложения - няма нищо общо с чисто клиентско приложение за iPhone.   -  person Nick Johnson    schedule 27.09.2010
comment
Как тогава да внедря API на Google Reader в моето приложение?   -  person Sebastien Peek    schedule 27.09.2010


Отговори (3)


Беше толкова просто. За всички, които се чудят, за да се свържа с API на Google Reader, направих следното.

/*  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];

}

}

Очевидно използвах собствени делегати и други подобни, но това е цялостното желание/усещане, което внесох в приложението си.

В момента работя върху изтеглянето на непрочетените емисии/елементи в UITableView за показване в моя RootViewController. Ще актуализирам това с повече информация.

Благодаря на всички, които се опитаха да помогнат :D

person Sebastien Peek    schedule 30.09.2010
comment
благодаря за това решение, скубах косата си за това от седмици - person daihovey; 24.01.2011

БЛАГОДАРЯ ТИ. Знаех, че има лесен начин за влизане, но ми беше ужасно време да го разбера. Между другото за тези от вас, които копират/пасват кода на the0rkus по-горе - ще получите няколко грешки. За да го тествам, добавих:

NSString *gUserString = @"[email protected]";
NSString *gPassString = @"yourpassword";
NSString *GOOGLE_CLIENT_AUTH_URL = @"https://www.google.com/accounts/ClientLogin?client=YourClient";
NSString *gSourceString = @"YourClient";
person Designeveloper    schedule 06.10.2010
comment
Откъде мога да получа GOOGLE_CLIENT_AUTH_URL и gSourceString??? Трябва ли да регистрирам приложението си някъде на сайта на Google? - person Shri; 19.11.2011

Потърсете в Google, има много блогове, които описват как да използвате API на Google Reader. Ето една прилична отправна точка: http://mindsharestrategy.com/google-reader-api-a-brief-tutorial/

person Abhijit Rao    schedule 27.09.2010
comment
Те обясняват как да го използвате с python, едва ли има такива, които навлизат в подробности за използването му с Objective-C... - person Sebastien Peek; 27.09.2010
comment
@the0rkus - Този урок е на PHP ... не на Python. Но трябва да е много преносимо. API използва стандартни двойки HTTP заявка/отговор за комуникация, така че наистина трябва да знаете как да правите GET/POST заявки и как да анализирате отговорите в Objective-C. Ако не го направите, тогава трябва да научите това, преди да опитате да се свържете с какъвто и да е външен API. - person EAMann; 17.05.2011