Social.framework&Account.framework #twtr_hack

23
Social.framework Account.framework MediaTechnologyLabs 黒田 樹 13125日金曜日

description

社内のObjective-Cエンジニアの勉強会で発表する(した)スライドです。 iOS6のフレームワーク周りの説明をしています。Facebook周り、SLRequest使おうとするとpermission周り意外とめんどいね。

Transcript of Social.framework&Account.framework #twtr_hack

Page 1: Social.framework&Account.framework #twtr_hack

Social.frameworkAccount.framework

MediaTechnologyLabs黒田 樹

13年1月25日金曜日

Page 2: Social.framework&Account.framework #twtr_hack

自己紹介• TwitterID : i2key

• MediaTecnologyLabsのJavaエンジニア

• Social x Music App「Attacca」

• 企画&開発(ObjC/Java)&運用

• 前職時代はSIerにてアーキテクトとして官公庁のシステム開発(Java/C#)に参画

13年1月25日金曜日

Page 3: Social.framework&Account.framework #twtr_hack

Agenda

• サンプルアプリの紹介

• Tweet / Wall Post

• SLComposeViewController

• Login

• ACAccountStore , ACAccount , ACCredential

• Tweet / Wall Post

• SLRequest

• ReverseAuth

13年1月25日金曜日

Page 4: Social.framework&Account.framework #twtr_hack

サンプルアプリ紹介再生している曲情報をTwitter/Facebookに投稿

https://github.com/i2key/SocialframeworkExampleGithub : i2key

13年1月25日金曜日

Page 5: Social.framework&Account.framework #twtr_hack

13年1月25日金曜日

Page 6: Social.framework&Account.framework #twtr_hack

Tweet/WallPost

- (IBAction)tweet:(id)sender { SLComposeViewController *twitterPostVC = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter]; [twitterPostVC setInitialText:@”メッセージ本文”]; [twitterPostVC addImage:UIImageクラスによる画像データ]; [self presentViewController:twitterPostVC animated:YES completion:nil];}

- (IBAction)postWall:(id)sender { SLComposeViewController *facebookPostVC = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook]; [facebookPostVC setInitialText:@”メッセージ本文”]; [facebookPostVC addImage: UIImageクラスによる画像データ]; [self presentViewController:facebookPostVC animated:YES completion:nil];}

SLComposeViewController

iOS5 : TWTweetComposeViewControlleriOS6 : SLComposeViewController

13年1月25日金曜日

Page 7: Social.framework&Account.framework #twtr_hack

Login(Twitter)

- (IBAction)showTwitterAccounts:(id)sender {! ACAccountStore *accountStore = [[ACAccountStore alloc] init]; ACAccountType *twitterType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];

[accountStore requestAccessToAccountsWithType:twitterType options:Nil completion:^(BOOL granted, NSError *error) { if (granted) {! ! ! //ActionSheetを表示する処理! ! } }]; }

ACAccountStore, ACAccount

self.accounts = [self.accountStore accountsWithAccountType:serviceType];

Accountへのアクセス要求

Accountを取り出す

13年1月25日金曜日

Page 8: Social.framework&Account.framework #twtr_hack

Login(Twitter)ACAccountStore, ACAccount

入力だるい離脱・・?

13年1月25日金曜日

Page 9: Social.framework&Account.framework #twtr_hack

Login(Twitter)ACAccountStore, ACAccount

TweetSheetであれば設定へ遷移させることが出来るが、この場合は出来ないのでユーザに設定させることになる・・・離脱・・?

便利になったものの、iOSにアカウント設定していない人は・・?

13年1月25日金曜日

Page 10: Social.framework&Account.framework #twtr_hack

Login(Twitter)ACAccountStore, ACAccount

Migrationto

AccountFW

ReverseAuth

Login

設定無し

設定済みServerでもAccessToken必要iOS5 > version

13年1月25日金曜日

Page 11: Social.framework&Account.framework #twtr_hack

Login(Facebook)

- (IBAction)showFacebookAccounts:(id)sender { ACAccountType *facebookType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];

NSDictionary *options = @{ACFacebookAppIdKey : @"AppID", ACFacebookPermissionsKey : @[@"email"], ACFacebookAudienceKey : ACFacebookAudienceOnlyMe};

[self.accountStore requestAccessToAccountsWithType:facebookType options:options completion:^(BOOL granted, NSError *error) { if(granted){ //ActionSheet表示する処理 } }]; }

ACAccountStore, ACAccount

self.accounts = [self.accountStore accountsWithAccountType:serviceType];

Accountへのアクセス要求

Accountを取り出す

13年1月25日金曜日

Page 12: Social.framework&Account.framework #twtr_hack

Login(Facebook)

- (IBAction)showFacebookAccounts:(id)sender { ACAccountType *facebookType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];

NSDictionary *options = @{ACFacebookAppIdKey : @"AppId", ACFacebookPermissionsKey : @[@"email"], ACFacebookAudienceKey : ACFacebookAudienceOnlyMe};

[self.accountStore requestAccessToAccountsWithType:facebookType options:options completion:^(BOOL granted, NSError *error) { if(granted){ //ActionSheet表示する処理 } }]; }

ACAccountStore, ACAccount

self.accounts = [self.accountStore accountsWithAccountType:serviceType];

Accountへのアクセス要求

Accountを取り出す

ACFacebookAppIdKey : APPID

ACFacebookPermissionsKey : 取得したいパーミッション

ACFacebookAudienceKey : 開示範囲

13年1月25日金曜日

Page 13: Social.framework&Account.framework #twtr_hack

ACFacebookAppIdKey : APPIDACFacebookPermissionsKey : 取得したいパーミッションACFacebookAudienceKey : 開示範囲

https://developers.facebook.com/apps

13年1月25日金曜日

Page 14: Social.framework&Account.framework #twtr_hack

ACFacebookAppIdKey : APPIDACFacebookPermissionsKey : 取得したいパーミッションACFacebookAudienceKey : 開示範囲

Step 1: Request basic profile information

Step 2: Request read permissions

Step 3: Request publish permissions

初めから書き込み権限、読み込み要求はNG例1)ACFacebookPermissionsKey : @[@”publish_actions”]

例2)ACFacebookPermissionsKey : @[@”email”,@”read_stream”]

以下のようなエラーが出るThe Facebook server could not fulfill this access request: The app must ask for a basic read permission at install time.”初めから基本情報権限要求のみはOKACFacebookPermissionsKey : @[@”email”]

基本情報権限要求後なら書き込み権限要求OKACFacebookPermissionsKey : @[@”publish_action”]

https://developers.facebook.com/docs/howtos/ios-6/

13年1月25日金曜日

Page 15: Social.framework&Account.framework #twtr_hack

ACFacebookAppIdKey : APPIDACFacebookPermissionsKey : 取得したいパーミッションACFacebookAudienceKey : 開示範囲

13年1月25日金曜日

Page 16: Social.framework&Account.framework #twtr_hack

ACFacebookAppIdKey : APPIDACFacebookPermissionsKey : 取得したいパーミッションACFacebookAudienceKey : 開示範囲

ACFacebookAudienceEveryone : Posts are visible to everyone.

ACFacebookAudienceFriends : Posts are visible only to friends.

ACFacebookAudienceOnlyMe : Posts are visible to the user only.

13年1月25日金曜日

Page 17: Social.framework&Account.framework #twtr_hack

Tweet/WallPost (Twitter)

- (void)tweetUsingSLRequest{ if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) { NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1.1/statuses/update_with_media.json"]; NSDictionary *params = [NSDictionary dictionaryWithObject:[[MusicManager sharedManager] createShareMessage] forKey:@"status"]; SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:url parameters:params]; NSData *imageData=UIImagePNGRepresentation([[MusicManager sharedManager] trackImage]); [request addMultipartData:imageData withName:@"media[]" type:@"multipart/form-data" filename:@"hoge"]; [request setAccount:self.selectedAccount]; [request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) { NSLog(@"responseData=%@", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]); }]; }}

SLRequest(iOS5 : TWRequest)

13年1月25日金曜日

Page 18: Social.framework&Account.framework #twtr_hack

Tweet/WallPost (Facebook)

- (void)postWallUsingSLRequest{ ACAccountStore *accountStore = [[ACAccountStore alloc] init]; ACAccountType *facebookType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook]; NSDictionary *options = @{ACFacebookAppIdKey : @"AppID", ACFacebookPermissionsKey : @[@"publish_actions"], ACFacebookAudienceKey : ACFacebookAudienceOnlyMe}; [accountStore requestAccessToAccountsWithType:facebookType options:options completion:^(BOOL granted, NSError *error) { if(granted){ NSString *urlStr = [NSString stringWithFormat:@"https://graph.facebook.com/me/feed"]; NSURL *url = [NSURL URLWithString:urlStr]; NSDictionary *params = @{@"message" : [[MusicManager sharedManager] createShareMessage]}; SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodPOST URL:url parameters:params]; [request setAccount:self.selectedAccount]; [request performRequestWithHandler:^(NSData *response, NSHTTPURLResponse *urlResponse, NSError *error){ NSLog(@"response:%@",[[NSString alloc]initWithData:response encoding:NSUTF8StringEncoding]); }]; }else{ NSLog(@"error post:%@",[error description]); } }]; }

SLRequest

13年1月25日金曜日

Page 19: Social.framework&Account.framework #twtr_hack

ReverseAuth (Twitter)ServerサイドでもTwitterAPIを利用する場合、AccessTokenが必要になるが、ACAccount.frameworkからは取り出せない

13年1月25日金曜日

Page 20: Social.framework&Account.framework #twtr_hack

ReverseAuth (Twitter)

Twitter

SingedRequest

Socialframework

SLRequest

ACAcount

https://api.twitter.com/oauth/access_token

https://api.twitter.com/oauth/request_token

<input>header : consumer_key...etcbody: x_auth_mode(reverseauth)

<output>reverseauth用token...etc

<input>Singned Requestのresponse

ConsumerKey

<output>oauth_tokenoauth_tokenSecretscreen_nameuser_id

Step1: Special Request Token取得

Step2: Access Token取得

https://dev.twitter.com/docs/ios/using-reverse-auth

13年1月25日金曜日

Page 21: Social.framework&Account.framework #twtr_hack

ReverseAuth (Twitter)Step1: Special Request Token取得

Signed Request(Header)の作り方https://dev.twitter.com/docs/auth/authorizing-request

13年1月25日金曜日

Page 22: Social.framework&Account.framework #twtr_hack

ReverseAuth (Twitter)Step1: Special Request Token取得

https://github.com/seancook/TWReverseAuthExample

13年1月25日金曜日

Page 23: Social.framework&Account.framework #twtr_hack

ReverseAuth (Twitter)- (IBAction)reverseAuth:(id)sender { // Step 1) Ask Twitter for a special request_token for reverse auth! NSURL *url = [NSURL URLWithString:TW_OAUTH_URL_REQUEST_TOKEN];!! // "reverse_auth" is a required parameter! NSDictionary *dict = [NSDictionary dictionaryWithObject:TW_X_AUTH_MODE_REVERSE_AUTH forKey:TW_X_AUTH_MODE_KEY];! TWSignedRequest *signedRequest = [[TWSignedRequest alloc] initWithURL:url parameters:dict requestMethod:TWSignedRequestMethodPOST];!! [signedRequest performRequestWithHandler:^(NSData *data, NSURLResponse *response, NSError *error) {! ! if (!data) {! ! ! [self dismissProgress:@"Error occurred in Step 1."];! ! }! ! else {! ! ! NSString *signedReverseAuthSignature = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];! ! !! ! ! // Step 2) Ask Twitter for the user's auth token and secret! ! ! // include x_reverse_auth_target=CK2 and x_reverse_auth_parameters=signedReverseAuthSignature parameters! ! ! dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{! ! ! ! NSDictionary *step2Params = [NSDictionary dictionaryWithObjectsAndKeys:[TWSignedRequest consumerKey], TW_X_AUTH_REVERSE_TARGET, signedReverseAuthSignature, TW_X_AUTH_REVERSE_PARMS, nil];! ! ! ! NSURL *authTokenURL = [NSURL URLWithString:TW_OAUTH_URL_AUTH_TOKEN]; //-- iOS5 -----! ! ! //TWRequest *step2Request = [[TWRequest alloc] initWithURL:authTokenURL parameters:step2Params requestMethod:TWRequestMethodPOST]; //------------- //-- iOS6 -----! ! ! ! SLRequest *step2Request = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:authTokenURL parameters:step2Params]; //------------- ! ! ! ! [step2Request setAccount:self.selectedAccount];! ! ! ! [step2Request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {! ! ! ! ! if (!responseData || ((NSHTTPURLResponse*)response).statusCode >= 400) {! ! ! ! ! ! [self dismissProgress:@"Error occurred in Step 2."];! ! ! ! ! } else {! ! ! ! ! ! NSString *responseStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; NSLog(@"AuthData : %@",responseStr); ! ! ! ! ! }! ! ! ! }];! ! ! });! ! }! }];}

13年1月25日金曜日