iPhone : 해당되는 글 2건

2010/03/05 >> iPhone 에서 OAuth 라이브러리 사용하기 (2)
2008/09/08 >> 위태로운 나날들 (5)

iPhone 에서 OAuth 라이브러리 사용하기

지난 주에 아이폰에 OAuth 컨슈머 라이브러리 돌리는데 삽질을 너무 많이 해서 반성하는 의미로 포스팅 해본다. http://oauth.net에 있는 라이브러리는 아이폰에 바로 쓸 수 없어서 약간 손을 봐야하는데 누군가 이미 해놓은 것도 있지만 기본(?) 라이브러리로 한번 해봤다. 붙이는건 그렇게 어렵지 않은데 아이폰에 써드파티 바이너리 프레임웍 추가 안되는거랑 Security.framework 내용이 Mac의 것과 다르다는 걸 몰라서 시간을 엄청 허비했음.

  1. OAuthConsumer 라이브러리를 체크아웃 한다.

    svn checkout http://oauth.googlecode.com/svn/code/obj-c/ .

  2. 프레임웍으로 빌드해서 넣으면 깔끔하겠지만 아이폰에는 그렇게 넣을 수 없으니 소스를 직접 넣는다. 다운받은 OAuthConsumer 디렉토리 아래에서 필요한 파일만 남기고 모두 삭제한다.

    rm -rf English.lproj OAuthConsumer.xcodeproj *.plist *.pch *.rb *Test.?

  3. Xcode에서 OAuthTest 라는 이름의 View-Based Application 하나를 생성한다.

  4. Finder에서 OAuthConsumer 디렉토리를 끌어다 Groups & Files 창의 Classes 아래에 놓는다. 파일을 복사할꺼니까 끌어다 놓을때 뜨는 'Copy items into destination group's folder'에 체크하고 Add 한다.

  5. 이 상태에서 빌드를 해보면 OAToken_KeychainExtensions.m 파일에서 에러가 난다. 원래 Mac Cocoa 환경이라면 Security.framework 라이브러리를 추가해서 컴파일 할 수 있지만 아이폰용 Security.framework 라이브러리는 맥용과 달라서 OAToken_KeychainExtensions.m 파일을 컴파일 시킬 수 없다. 하지만 이 파일은 꼭 필요한건 아니고 나중에 OAuth 인증 끝나고 토큰과 시크릿을 키체인에 안전하게 보관할 수 있게 도와주는 유틸리티인데 필요하면 알아서 구현하고 일단 지워도 문제 없다. 파일 목록에서 OAToken_KeychainExtensions.? 파일을 삭제하고 빌드하면 일단 문제없이 컴파일이 될 것이다.

  6. 시작하기 전에 OAuthConsumer.h 파일을 열어서 import 경로를 올바른 경로로 바꾸어주자.

    #import <Foundation/Foundation.h> #import <OAuthConsumer/OAToken.h> #import <OAuthConsumer/OAConsumer.h> #import <OAuthConsumer/OAMutableURLRequest.h> ...

    이걸 아래처럼 변경.

    #import <Foundation/Foundation.h> #import "OAToken.h" #import "OAConsumer.h" #import "OAMutableURLRequest.h" ...

  7. 이제 OAuthTestViewController.xib 파일을 열어서 아래 그림처럼 웹뷰, 'Get Request Token' 버튼, 'Get Access Token' 버튼, PIN 번호를 입력받을 텍스트 필드가 있는 화면을 생성한다. 'Get Request Token' 버튼을 누르면 Request Token을 얻어와서 트위터의 Authorize URL로 이동시키고, 사용자가 로그인 한 후 보여지는 PIN 번호를 넣고 'Get Access Token' 버튼을 누르면 Access Token을 가져올 것이다.

  8. 위에서 추가한 웹뷰, 텍스트필드의 아웃렛 변수와 두 버튼에 연결될 액션 메서드를 만들고 연결한다.

    #import <UIKit/UIKit.h> @interface OAuthTestViewController : UIViewController { UIWebView *webView; UITextField *textField; } @property (nonatomic, retain) IBOutlet UIWebView *webView; @property (nonatomic, retain) IBOutlet UITextField *textField; - (IBAction)requestTokenButton:(UIButton *)sender; - (IBAction)accessTokenButton:(UIButton *)sender; @end

  9. 먼저 'Get Request Token' 버튼을 눌렀을때 Request Token을 얻어와서 로그에 찍어보자. 아래처럼 호출하도록 requestTokenButton: 메서드를 작성하고 성공/에러시에 호출될 델리게이트 메서드도 만든다.

    #import "OAuthConsumer.h" ... - (IBAction)requestTokenButton:(UIButton *)sender { OAConsumer *consumer = [[OAConsumer alloc] initWithKey:@"Z0DxPl4q7kmSOgh3LTpV4Q" secret:@"LWryiOYBAHJ58PX9Yn1yG5bzDwpMJiksqpXxfst7kcU"]; NSURL *url = [[NSURL alloc] initWithString:@"http://twitter.com/oauth/request_token"]; OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:url consumer:consumer token:nil realm:@"http://twitter.com/" signatureProvider:nil]; [request setOAuthParameterName:@"oauth_callback" withValue:@"oob"]; OADataFetcher *fetcher = [[OADataFetcher alloc] init]; [fetcher fetchDataWithRequest:request delegate:self didFinishSelector:@selector(requestTokenTicket:didFinishWithData:) didFailSelector:@selector(requestTokenTicket:didFailWithError:)]; [consumer release]; [url release]; [request release]; [fetcher release]; } - (void)requestTokenTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data { if (ticket.didSucceed) { NSString *responseBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; OAToken *token = [[OAToken alloc] initWithHTTPResponseBody:responseBody]; NSLog(@"Request Token: key=%@, secret=%@", [token key], [token secret]); [token release]; [responseBody release]; } else { NSLog(@"Finish but did not succeed."); } } - (void)requestTokenTicket:(OAServiceTicket *)ticket didFailWithError:(NSError *)error { NSLog(@"Error: %@", [error localizedDescription]); }

    위와 같이 작성해서 실행해보면 requestTokenTicket:didFailWithError: 쪽으로 떨어지면서,

    Operation could not be completed. (NSURLErrorDomain error -1012.)

    이런 메시지가 떨어진다. 이유는,

    [request setOAuthParameterName:@"oauth_callback" withValue:@"oob"];

    이 부분 때문인데 oauth_callback 이라는 파라미터를 추가하고 싶어서 이렇게 적었으면 이 파라미터를 포함하여 시그니쳐를 생성해야 하는데 OAuthConsumer 라이브러리에서는 추가된 파라미터를 제외하고 시그니처를 생성해 요청했고 결과적으로 트위터에서 시그니처가 틀리다는 이유로 200 OK가 떨어지지 않는 상태이다(버그이거나 OAuth 1.0a 스펙을 고려하지 않아서인 듯). 추가된 파라미터를 포함하여 시그니처를 생성하도록 OAMutableURLRequest.m 파일을 수정해보자. 파일을 열어서 _signatureBaseString 메서드 중간쯤에,

    ... for (OARequestParameter *param in [self parameters]) { [parameterPairs addObject:[param URLEncodedNameValuePair]]; } for(NSString *parameterName in [[extraOAuthParameters allKeys] sortedArrayUsingSelector:@selector(compare:)]) { [parameterPairs addObject:[[OARequestParameter requestParameterWithName:parameterName value:[extraOAuthParameters objectForKey:parameterName]] URLEncodedNameValuePair]]; } NSArray *sortedPairs = [parameterPairs sortedArrayUsingSelector:@selector(compare:)]; NSString *normalizedRequestParameters = [sortedPairs componentsJoinedByString:@"&"]; ...

    이렇게 for 루프를 하나 추가한다. 이제 다시 실행해서 'Get Request Token' 버튼을 눌러보면,

    2010-03-05 17:09:40.438 OAuthTest[1691:207] Request Token: key=wyGw0VUSE79MTuVm0iqs7ZdWiPI3ZRJWCZ2k6P73w, secret=AUGrkHfx3nr6xb9Q5dUbNQzykZQvFJ62WW90BojT8

    콘솔에 이렇게 찍히면서 정상적으로 토큰을 얻어올 수 있다.

  10. 이제 Request Token을 얻어왔으니 토큰을 임시로 저장하고 트위터의 Authorize URL을 호출한다. 아래처럼 OAuthTestViewController.h 파일을 수정하고,

    #import <UIKit/UIKit.h> @class OAServiceTicket; @class OAToken; @interface OAuthTestViewController : UIViewController { UIWebView *webView; UITextField *textField; OAToken *requestToken; } @property (nonatomic, retain) IBOutlet UIWebView *webView; @property (nonatomic, retain) IBOutlet UITextField *textField; @property (nonatomic, retain) OAToken *requestToken; ...

    아래처럼 OAuthTestViewController.m 파일을 수정한다.

    if (ticket.didSucceed) { NSString *responseBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; OAToken *token = [[OAToken alloc] initWithHTTPResponseBody:responseBody]; NSLog(@"Request Token: key=%@, secret=%@", [token key], [token secret]); self.requestToken = token; [token release]; [responseBody release]; NSString *authorizeURL = [[NSString alloc] initWithFormat:@"http://twitter.com/oauth/authorize?oauth_token=%@", [self.requestToken.key URLEncodedString]]; [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:authorizeURL]]]; [authorizeURL release]; } ...

    이제 실행하고 'Get Request Token' 버튼을 누르면 아래 이미지 처럼 인증을 요구하는 화면이 나오고 Allow 하고 나면,

    아래 이미지 처럼 PIN 번호가 보여진다.

  11. 이제 PIN 번호를 입력하고 'Get Access Token'을 클릭했을 때의 처리를 하면 된다. accessTokenButton: 메서드를 아래처럼 작성하고 accessTokenTicket:didFinishWithData:, accessTokenTicket:didFailWithError: 델리게이트 메서드도 만들자.

    - (IBAction)accessTokenButton:(UIButton *)sender { OAConsumer *consumer = [[OAConsumer alloc] initWithKey:@"Z0DxPl4q7kmSOgh3LTpV4Q" secret:@"LWryiOYBAHJ58PX9Yn1yG5bzDwpMJiksqpXxfst7kcU"]; NSURL *url = [[NSURL alloc] initWithString:@"http://twitter.com/oauth/access_token"]; OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:url consumer:consumer token:self.requestToken realm:@"http://twitter.com/" signatureProvider:nil]; [request setOAuthParameterName:@"oauth_verifier" withValue:self.textField.text]; OADataFetcher *fetcher = [[OADataFetcher alloc] init]; [fetcher fetchDataWithRequest:request delegate:self didFinishSelector:@selector(accessTokenTicket:didFinishWithData:) didFailSelector:@selector(accessTokenTicket:didFailWithError:)]; [consumer release]; [url release]; [request release]; [fetcher release]; } - (void)accessTokenTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data { if (ticket.didSucceed) { NSString *responseBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; OAToken *token = [[OAToken alloc] initWithHTTPResponseBody:responseBody]; NSLog(@"Got Access Token [key:%@, secret:%@]", token.key, token.secret); [token release]; [responseBody release]; } else { NSLog(@"Finish but did not succeed."); } } - (void)accessTokenTicket:(OAServiceTicket *)ticket didFailWithError:(NSError *)error { NSLog(@"Error: %@", [error localizedDescription]); }

  12. 이제 실행해서 PIN 번호를 넣고 'Get Access Token' 버튼을 누르면 아래처럼 Access Token 정보가 콘솔에 출력된다.

    Got Access Token [key:14368376-CyPcPg7uVLcOkzRJBlJLMVKqZQMzCMQnRxHMmzQG8, secret:HY3eENZ6Pt4AFdUUtzAROlZDaKHOJHtcc7lMKMyKE]

  13. 이제 위에서 출력되는 Access Token 정보를 저장해서 OAMutableURLRequest 클래스로 요청 할 때 token 인자에 넣어 보내면 된다. 요청 할 때 파라미터를 세팅해야 할 경우에는, OARequestParameter 파라미터를 NSArray 로 묶어 OAMutableURLRequest 생성 후에 setParameter: 해주면 된다.

틀린 내용이 있다면 지적해주세요!

'컴퓨터 얘기 > 프로그래밍' 카테고리의 다른 글

iPhone 에서 OAuth 라이브러리 사용하기  (2) 2010/03/05
Read Me 플러그인  (3) 2007/12/07
드림위버와 이별하기  (5) 2007/11/28
MySQL Foreign Key 바보짓  (6) 2007/04/09
TinyMCE 플러그인 - WikiExporter  (5) 2007/02/07
멜론 앨범 커버 다운로더  (20) 2007/02/04

위태로운 나날들

iPhone 3G

하반기부터 주주룩 잡힌 스마트폰 출시 일정에 마음이 싱숭생숭 하다. 마지막으로 쓰던 PDA폰을 팔아버리면서 다시는 윈도우즈모바일따위 쓰지 않겠다고 다짐했는데 M480 같은건 쿼티 키패드도 달리고 잡다한 기능들이 많아 요즘 다시 끌리고 있다. 그래도 언젠가 나올 아이폰만 기다리며 잘 참고 있었는데 떡밥이 워낙 많으니 오히려 지치기도 하고 M480 계속 보다 보니 예쁘기도 하고.. 지난주에는 매장에 전화를 걸어 퀵으로 당장 배송해줄 수 있는지 물었는데 택배로 다음주에나 온다고 해서 포기했고 얼마 전에는 KTF로 출시될 M4800이 좀 좋아보이길래 뜬금없이 액정보호필름을 주문했었다. (다음날 일찍 정신차리고 취소했음) M480은 리뷰랑 사용기 읽다보면 확 끌릴때도 있고 이런 저런 제약을 보면 정 떨어질때도 있는데 이 감정의 다이나믹 레인지가 워낙 넓어 자칫 저질러버리기 쉬운 위험이 크다.

출시 예정된 폰 중에 아이폰 말고 관심 가는건 HTC 터치 다이아몬드, 삼성 옴니아, 소니 엑스페리아 인데 셋 다 윈도우즈 모바일을 OS로 사용한다. 아이팟 터치를 계속 쓰면서 느낀 스마트폰 UX의 최소 요건은 누르면 즉시 반응하는 반응 속도와 무조건 예쁜거라고 생각하는데 위에 말한 기계들은 이 것들과는 완전 거리가 멀다. 일단 디자인부터 틀려먹은게 버전이 6개나 올라가는 동안에 윈도우즈 3.1보다 조금도 나아진게 없는 화면에 얹어진 굴림체를 보고 있으면 깝깝해 목이 메일 수 밖에 없고 가장 성능이 좋다고 하는 옴니아도 유튜브에 올라온 동영상들을 보면 하나같이 창 한번에 못닫고 삽질하고 랙걸리고 화면 렌더링 하는 과정이 눈에 다 보이고 (이제 막 박스 까서 부팅한 제품인데!) 특히 전화 어플에서 화면을 가로로 뉘었을때 어플 옆으로 돌아가는거 보면 '도대체 왜?' 하는 생각이 든다. 터치 다이아몬드나 엑스페리아는 화면은 예쁜데 반응속도가 너무 답답해서 쓰면 속버릴꺼 같음.

여러 가지를 고려하면 아이폰 나올때 까지 잘 참고 기다리는게 맞는데 그 중간에 뭐라도 나와주면 못 참고 사버릴거 같기도 하다. 추석 전후로 출시된다는 소문이 흉흉한 M4800 지름신을 이겨내기 위해 M4800의 단점들을 나열해 지름신을 물리쳐보자.

M4800 박스

남자라면 실물보다는 박스샷에 끌리기 마련이죠

어정쩡한 해상도
왜 240x320 96DPI보다 320x320 128DPI가 더 글자가 크게 나오는지 모르겠지만 아무튼 그렇단다. RealVGA 라는 어플로 DPI 조정은 가능 하지만 안돌아가는 프로그램이 있다고 함.
악명 높은 문자 어플
M480의 SMS 어플리케이션은 SK에서 만들었는데 전작인 블랙잭의 그 것 보다 눈꼽만큼 좋아져서 문자 확인하는데 10초밖에 걸리지 않는다고 한다. M4800에는 삼성에서 만든 조금 더 빠른 어플이 들어가있다네. 문자 메시지 송수신 하는걸 GMail처럼 스레드로 묶어주거나 아이폰처럼 채팅하듯이 보여주는게 어려운 것도 아니고 생각해보지 않았을리도 없는데 2008년의 SMS 어플은 여전히 이모양이다.
핑거마우스
안써봐서 잘은 모르지만 터치스크린에 마우스가 왜 필요한건지 잘 모르겠다. 덕분에 방향키가 없어졌다.
네이트 스토어
내장 메모리의 적절한 파티셔닝 덕분에 어플들 많이 설치하다보면 애로사항이 꽃피기 시작한다.
교통카드 안됨
USIM 티머니 써보니 편하던데..
OK 버튼
M480과는 다르게 M4800은 OK 버튼이 키패드 구석에 있고 OK 버튼이 있어야 할 자리에는 문자메시지 버튼이 있다. 아.. 왜그랬어..
액정
노란 빛이 감도는.. 오줌액정이라고 하던가;
키패드 동시 입력
한번에 하나의 키만 눌려서 에뮬 게임 하기가 매우 어렵다. 돌아가긴 아주 잘돌아간다고 하던데..
싱크 에러
나온지 꽤 시간이 지났음에도 ActiveSync가 불안정한 사람이 많다.
벨소리 모드
이어폰으로 음악을 듣고 있을때 전화가 오면 벨소리가 본체에서 난다고 한다. 버그가 아니고 그렇게 의도한거라 함. 문자 수신 벨도 스피커로. 벨소리를 진동후 벨로 해놓으면 이어폰으로 벨소리가 나온다고 한다. 매너모드로 설정하면 MP3 볼륨도 0이 된다. 블루투스로 음악을 듣다가 블루투스 연결이 끊어지면 본체의 빵빵한 스피커로 갑자기 음악이 나오기 시작한다. 뭥미?
전화기능의 불안정
통화중 대기 전환중에 먹통이 된다던가 무슨 무슨 GPS 프로그램을 설치하면 전화 수신을 못한다던가 하는 불안요소들이 존재한다.

위 내용들은 과장되거나 뻥일수도 있고 심심할때마다 업데이트 됨.

'평범한 얘기 > 흥미거리' 카테고리의 다른 글

BlackBerry Softwares  (1) 2009/08/01
BlackBerry Bold  (7) 2009/07/13
위태로운 나날들  (5) 2008/09/08
큐브 맞추기  (0) 2008/01/23
Anycall SCH-W380  (4) 2007/12/30
COWON D2  (23) 2007/02/02
태그 : iPhone, m480, 지름신