まいまいワークス

主にiPhoneアプリの開発で考えた事、調べた事、感じた事などを記していきます。

Twitter/Facebookのアカウントで認証して、アプリからタイムライン/フィードに投稿する[#8]〜Facebookのフィード投稿〜

メッセージの投稿

これが投稿の基本パターンになります。

//例によって以下の項目をインポートする
#import <Parse/Parse.h>
#import <FacebookSDK/FacebookSDK.h>
#import <AFNetworking/AFNetworking.h>



-(void)fbpost:(NSString *)message{
    
    //プライバシー(公開範囲)の設定
    NSDictionary* privacy = @{@"value":@"CUSTOM", @"friends":@"ALL_FRIENDS"};
    
    NSMutableDictionary* params = @{@"message":message,
                                    @"privacy":[dictionary_to_JSON dictionaryToJSON:privacy],
                                    }.mutableCopy;
    
    //FBリクエストの作成
    FBRequest *request = [FBRequest requestWithGraphPath:@"me/feed"
                                              parameters:params
                                              HTTPMethod:@"POST"];
    
    
    //コネクションをセットしてすぐキャンセル→NSMutableURLRequestを生成するため???
    //ここはStack Overflowの受け売り
    FBRequestConnection *requestConnection = [request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
    }];
    [requestConnection cancel];
    
    //リクエストの作成
    NSMutableURLRequest *urlRequest = requestConnection.urlRequest;
    
    //送信!
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        // Do your success callback.
        NSLog(@"success!");
        
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // Do your failure callback.
        NSLog(@"fail!");
        NSLog(@"operation=%@",operation);
        NSLog(@"error=%@",error);
    }];
    

    //進捗状況の確認
    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite) {
        NSLog(@"Sent %ld of %ld bytes", totalBytesWritten, totalBytesExpectedToWrite);
    }];
    
    [[NSOperationQueue mainQueue] addOperation:operation];

}

プライバシーの設定はJSON形式で埋め込む必要があるため何らかの方法でNSDictionary→JSONの変換をする必要があります。
ここではdictionaryToJSONというクラスメソッドで変換をするという想定で記述しています。
NSMutableURLRequestの設定部分はStack Overflowを参考にしました。

テキストだけじゃなくて画像を添付する場合は以下のように書き換えます。

画像添付の場合

    NSMutableDictionary* params = @{@"message":message,
                                    @"privacy":[dictionary_to_JSON dictionaryToJSON:privacy],
                                    @"picture":data,
                                    }.mutableCopy;

    //FBリクエストの作成
    FBRequest *request = [FBRequest requestWithGraphPath:@"me/photos"
                                              parameters:params
                                              HTTPMethod:@"POST"];

paramsのところにpictureを追加し、NSData形式の画像データを指定します。 また、requestのme/feedme/photosにかわります。

動画の添付の場合

    NSMutableDictionary* params = @{@"message":message,
                                    @"privacy":[dictionary_to_JSON dictionaryToJSON:privacy],
                                  @"movie.mp4":data,
                                      @"title":@"タイトル",
                                    }.mutableCopy;

    //FBリクエストの作成
    FBRequest *request = [FBRequest requestWithGraphPath:@"me/videos"
                                              parameters:params
                                              HTTPMethod:@"POST"];

動画の場合は同じくNSData形式でデータを渡すことには変わりないのですが、keyが動画のファイル名になるようです。
あとは、動画のタイトルが付加できます。
一方、requestの方はme/videosとなります。

facebookの資料としては本家のドキュメントのほか、こちらのサイトは日本語での解説なので分かりやすかったです。


  1. イントロダクション
  2. Twitterのアプリ登録
  3. Facebookのアプリ登録
  4. Parseの登録と設定
  5. Twitterアカウントでの認証
  6. Twitterのタイムライン投稿
  7. Facebookアカウントでの認証
  8. Facebookのフィード投稿

Twitter/Facebookのアカウントで認証して、アプリからタイムライン/フィードに投稿する[#7]〜Facebookアカウントでの認証〜

基本的な設定

ここはすでに前回のTwitterアカウントでの認証で行っているので省略

Facebook認証

-(void)facebook{
    
    // パーミッション
    // タイムラインにユーザーに代わって書き込むにはpublish_streamが必要
    NSArray *permissionsArray = @[ @"user_about_me", @"user_relationships", @"user_birthday", @"user_location",@"publish_stream"];

    // Facebook アカウントを使ってログイン
    [PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {
        if (!user) {
            if (!error) {
                NSLog(@"Facebook ログインをユーザーがキャンセル");
            } else {
                NSLog(@"Facebook ログイン中にエラーが発生: %@", error);
            }
        } else if (user.isNew) {
            NSLog(@"Facebook サインアップ & ログイン完了!");
        } else {
            NSLog(@"Facebook ログイン完了!");
        }
        
        NSLog(@"sessionToken=%@",user.sessionToken);
        NSLog(@"isNew=%d",user.isNew);
        NSLog(@"username=%@",user.username);

    }];
}

メソッド名がちょっと違うくらいで、Twitterの時とよく似ていますが、 Facebookの場合はNSArray形式でパーミッション設定があります。
ここに列挙している項目に対してユーザーにお伺いを立て、ユーザーが許可するとアクセスが可能になります。
パーミッション設定の詳細はこちら

続いて、基本的なパラメータを取得してみます。

//facebookの各種データ取得
-(void)info{

    FBRequest *request = [FBRequest requestForMe];
    
    // Send request to Facebook
    [request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
        if (!error) {
            // result is a dictionary with the user's Facebook data
            NSDictionary *userData = (NSDictionary *)result;
            
            NSString *facebookID = userData[@"id"];
            NSString *name = userData[@"name"];
            NSString *location = userData[@"location"][@"name"];
            NSString *gender = userData[@"gender"];
            NSString *birthday = userData[@"birthday"];
            NSString *relationship = userData[@"relationship_status"];
            
            NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large&return_ssl_resources=1", facebookID]];
            
            // Now add the data to the UI elements
            // ...
            
            
            NSLog(@"name=%@",name);
            NSLog(@"location=%@",location);
            NSLog(@"gender=%@",gender);
            NSLog(@"birthday=%@",birthday);
            NSLog(@"relation=%@",relationship);
            NSLog(@"pict=%@",pictureURL);
            
        }
    }];
}

これはParseのドキュメントからそのまま拝借したソースなんですが、これで基本的な項目が取得できます。
これで、TwitterFacebookの認証と情報取得ができました。
次回以降では実際にユーザーに代わってアプリから投稿を行う部分に入って行きます。


  1. イントロダクション
  2. Twitterのアプリ登録
  3. Facebookのアプリ登録
  4. Parseの登録と設定
  5. Twitterアカウントでの認証
  6. Twitterのタイムライン投稿
  7. Facebookアカウントでの認証
  8. Facebookのフィード投稿

Twitter/Facebookのアカウントで認証して、アプリからタイムライン/フィードに投稿する[#6]〜Twitterのタイムライン投稿〜

メッセージのみを投稿

//以下の項目をインポートしておく
#import <Parse/Parse.h>
#import <FacebookSDK/FacebookSDK.h>
#import <AFNetworking/AFNetworking.h>



//twitter 文章のみ投稿
-(void)tweet:(NSString *)message {
    
    //URLとパラメータを生成
    NSString* url = @"https://api.twitter.com/1.1/statuses/update.json";
    NSMutableDictionary* param = @{@"status":message}.mutableCopy;

    //リクエストにメソッド(POST)、URL、パラメータを設定
    NSMutableURLRequest *tweetRequest = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST"
                                                                           URLString:url
                                                                          parameters:param
                                                                               error:nil];

    //認証
    [[PFTwitterUtils twitter] signRequest:tweetRequest];
    
    //operationの定義
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:tweetRequest];
    
    //実行
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject){
        
        NSLog(@"success!");
        
    }failure:^(AFHTTPRequestOperation *operation, NSError *error){
        
        NSLog(@"fail!");
        NSLog(@"operation=%@",operation);
        NSLog(@"error=%@",error);

    }];
    
    [[NSOperationQueue mainQueue] addOperation:operation];
}

メッセージのみの投稿はこんな感じです。
簡単ですね。

画像とメッセージを投稿

//以下の項目をインポートしておく
#import <Parse/Parse.h>
#import <FacebookSDK/FacebookSDK.h>
#import <AFNetworking/AFNetworking.h>



//twitter 画像添付バージョン
-(void)tweetWithImage:(NSString *)message image:(UIImage *)image{
    
    //受け取ったUIImageをNSData形式に変換
    NSData* data = UIImageJPEGRepresentation(image, 1.0);
    
    // AFHTTPRequestOperationManagerの定義
    AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    
    //URLとパラメータを生成
    NSString* url = @"https://api.twitter.com/1.1/statuses/update_with_media.json";
    NSMutableDictionary* param = @{@"status":message}.mutableCopy;
    
    //リクエストにメソッド(POST)、URL、パラメータ、添付画像を設定
    NSMutableURLRequest *tweetRequest = [manager.requestSerializer multipartFormRequestWithMethod:@"POST"
                                                                                      URLString:url
                                                                                     parameters:param
                                         
                                                           constructingBodyWithBlock:^(id<AFMultipartFormData> formData){

                                                               [formData appendPartWithFormData:data name:@"media[]"];
                                                               
                                                           }
                                                                                          error:NULL];
    
    
    //認証!
    [[PFTwitterUtils twitter] signRequest:tweetRequest];
    
    //送信!
    AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:tweetRequest success:^(AFHTTPRequestOperation* operation, id responseObject){
        
        NSLog(@"success!");
        
    }failure:^(AFHTTPRequestOperation* operation, NSError* error){
        
        NSLog(@"operation=%@",operation);
        NSLog(@"eror=%@",error);
        
    }];
    
    
    // データを送信する度に実行される処理を設定する
    //プログレスバーなど
    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite) {
        // アップロード中の進捗状況をコンソールに表示する
        NSLog(@"bytesWritten: %@, totalBytesWritten: %@, totalBytesExpectedToWrite: %@, progress: %@",
              @(bytesWritten),
              @(totalBytesWritten),
              @(totalBytesExpectedToWrite),
              @((float)totalBytesWritten / totalBytesExpectedToWrite));
    }];
    
    [manager.operationQueue addOperation:operation];
}

画像添付の場合も基本的なパターンは同じです。
リクエストの設定で画像を設定しているところと、画像送信で少し待たされることを想定して進捗を取得できるようにしています。
あと、ビルドの環境によってはlongがlong longになるかもしれません。

TwitterAPIに関しては本家のドキュメントを参考にするか、 最終的には本家にリンクされているのですが、こちらのサイトがよくまとまっていてわかりやすかったです。


  1. イントロダクション
  2. Twitterのアプリ登録
  3. Facebookのアプリ登録
  4. Parseの登録と設定
  5. Twitterアカウントでの認証
  6. Twitterのタイムライン投稿
  7. Facebookアカウントでの認証
  8. Facebookのフィード投稿

Twitter/Facebookのアカウントで認証して、アプリからタイムライン/フィードに投稿する[#5]〜Twitterアカウントでの認証〜

基本的な設定

//ParseとFacebookのSDKをimport
#import <Parse/Parse.h>
#import <FacebookSDK/FacebookSDK.h>



//アプリ起動時の設定
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

    //Parse初期設定
    [Parse setApplicationId:@"ParseのアプリケーションID" clientKey:@"Parseのクライアントキー"];
    [PFUser enableAutomaticUser];
    PFACL *defaultACL = [PFACL ACL];
    [PFACL setDefaultACL:defaultACL withAccessForCurrentUser:YES];

    
    // Facebook
    [PFFacebookUtils initializeFacebook];
    
    //Twitter
    [PFTwitterUtils initializeWithConsumerKey:@"twitterのConsumerKey"
                               consumerSecret:@"twitterのconsumerSecret"];
    
    
    return YES;
}



- (void)applicationDidBecomeActive:(UIApplication *)application
{
    //この行を追加
    [FBAppCall handleDidBecomeActiveWithSession:[PFFacebookUtils session]];

}

//このメソッドを追加
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    return [FBAppCall handleOpenURL:url
                  sourceApplication:sourceApplication
                        withSession:[PFFacebookUtils session]];
}

基本的な設定をAppDelegateで行います。
Facebookの固有情報はここではなくてinfo.plistで設定します。

FacebookAppIDという項目を作成し、ここにFacebookのアプリケーションIDを設定。
FacebookDisplayNameという項目を作成し、ここにDisplay Nameを設定。
あとはURLスキームの項目を作成し上記のアプリケーションIDの先頭にfbをつけたモノを設定します。(例:アプリケーションIDが1234567890の場合fb1234567890をセット)

plist.png

Twitter認証

//認証を行うviewControllerで以下をインポート
#import <Parse/Parse.h>
#import <FacebookSDK/FacebookSDK.h>
#import <AFNetworking/AFNetworking.h>



-(void)twitter{
    
    [PFTwitterUtils logInWithBlock:^(PFUser *user, NSError *error) {
        if (!user) {
            if (!error) {
                NSLog(@"Twitter ログインをユーザーがキャンセル");
            } else {
                NSLog(@"Twitter ログイン中にエラーが発生: %@", error);
            }
        } else if (user.isNew) {
            NSLog(@"Twitter サインアップ & ログイン完了!");
        } else {
            NSLog(@"Twitter ログイン完了!");
        }
        
        
        NSLog(@"sessionToken=%@",user.sessionToken);
        NSLog(@"isNew=%d",user.isNew);
        NSLog(@"username=%@",user.username);
        
    }];

}

サインアップおよびログインは上記のような形で行います。
user.isNewの値が1なら新規登録扱いになっています。
user.sessionTokenでトークンが取得できます。

Twitter各種情報取得

認証が完了したので、APIを叩いて(APIにアクセスして)各種情報を取得してみましょう。

//スクリーンネーム取得用
-(void)info{
    
    // AFHTTPRequestOperationManagerの定義
    AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    
    NSString* url = @"https://api.twitter.com/1.1/account/settings.json";
    
    //NSMutableURLRequestにメソッド(GET)、URLを設定
    NSMutableURLRequest *infoRequest = [manager.requestSerializer requestWithMethod:@"GET" URLString:url parameters:nil error:nil];

    //認証
    [[PFTwitterUtils twitter] signRequest:infoRequest];
    
    //送信!
    AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:infoRequest success:^(AFHTTPRequestOperation* operation, id responseObject){
        
        NSLog(@"success!");
        
        //いろいろな値が取れているのでここで確認してみる
        NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
        NSLog(@"dict=%@",dict);
        
        
        //いま、ほしい値はscreen_name
        NSLog(@"screenName=%@",dict[@"screen_name"]);
        
    }failure:^(AFHTTPRequestOperation* operation, NSError* error){
        
        NSLog(@"operation=%@",operation);
        NSLog(@"eror=%@",error);
        
    }];
    
    [manager.operationQueue addOperation:operation];

}

ここで得られたscreen nameを使って、以下のAPIを叩いてみましょう。

//ユーザーネームとかアイコンURLとか取得
-(void)lookup{
    
    // AFHTTPRequestOperationManagerの定義
    AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    
    NSString* url = @"https://api.twitter.com/1.1/users/lookup.json";

    //SCREEN_NAMEにはhttps://api.twitter.com/1.1/account/settings.jsonで取得したscreen nameを代入する
    NSMutableDictionary* param = @{@"screen_name":SCREEN_NAME}.mutableCopy;
    
    //NSMutableURLRequestにメソッド(POST)、URL、パラメータを設定
    NSMutableURLRequest *lookupRequest = [manager.requestSerializer requestWithMethod:@"POST" URLString:url parameters:param error:nil];
    
    //認証
    [[PFTwitterUtils twitter] signRequest:lookupRequest];
    
    //送信!
    AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:lookupRequest success:^(AFHTTPRequestOperation* operation, id responseObject){
        
        NSLog(@"success!");
        
        //いろいろな値が取れているのでここで確認してみる
        NSArray* array = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
        NSLog(@"array=%@",array);
        
        
        //ユーザーネーム
        NSLog(@"name=%@",array[0][@"name"]);
        //アイコン(小)URL
        NSLog(@"imageURL=%@",array[0][@"profile_image_url"]);
        //アイコン(大)URL
        NSLog(@"imageURL=%@",[array[0][@"profile_image_url"] stringByReplacingOccurrencesOfString:@"_normal" withString:@""]);
        
    }failure:^(AFHTTPRequestOperation* operation, NSError* error){
        
        NSLog(@"operation=%@",operation);
        NSLog(@"eror=%@",error);
        
    }];
    
    [manager.operationQueue addOperation:operation];

}

この出力はarray形式になっていますが、これはscreen nameをコンマ区切りで100個まで指定できるため、このようなかたちになっていると思います。

次回はfacebookアカウントでの認証。


  1. イントロダクション
  2. Twitterのアプリ登録
  3. Facebookのアプリ登録
  4. Parseの登録と設定
  5. Twitterアカウントでの認証
  6. Twitterのタイムライン投稿
  7. Facebookアカウントでの認証
  8. Facebookのフィード投稿

Twitter/Facebookのアカウントで認証して、アプリからタイムライン/フィードに投稿する[#4]〜Parseの登録と設定〜

Parseは最近話題のmBaaSのひとつで、プッシュ通知、ユーザー管理機能、データストアなどのサーバー側の機能を提供してくれます。
ここではユーザー管理機能のみを使いTwitterFacebookアカウントによる認証を行います。

登録

ParseのURLはこちら アクセスしたら右上のSignupから登録画面に入り、name,address,passwordを登録。GitHubFacebookのアカウントを使えばお手軽ですね。
続いてアプリ名、所属先、役職などの設定を行います。

Application ID と Client Key の取得

登録が完了したらApplication ID と Client Keyをメモっておきましょう。

parse1.png

次に、Settings > User authenticationで 先ほどメモったFacebookアプリケーションIDシークレットキー TwitterAPIキー(Twitter Consumer Keys)を入力します。

Parse2.png

SDKの入手

同じくParseのDownload画面iOSSDKをダウンロード。
続いてFacebookのSDKを入手

これら二つをプロジェクトにまるっとコピーします。 sdk.png

Flamework/Libraryのインポート

以下のFlamework/Libraryをプロジェクトに設定します。

  • CoreLocation.framework
  • StoreKit
  • QuartzCore
  • libz.1.1.3.dylib
  • Security
  • AudioToolbox
  • MobileCoreServices
  • SystemConfiguration
  • CFNetwork  

下準備はこんな感じです。
次はいよいよコードを書いていきます。


  1. イントロダクション
  2. Twitterのアプリ登録
  3. Facebookのアプリ登録
  4. Parseの登録と設定
  5. Twitterアカウントでの認証
  6. Twitterのタイムライン投稿
  7. Facebookアカウントでの認証
  8. Facebookのフィード投稿

Twitter/Facebookのアカウントで認証して、アプリからタイムライン/フィードに投稿する[#3]〜Facebookのアプリ登録〜

登録

Facebookの開発者ページに入り、右上の+Create New Appをクリック Display Name,Namespace(optional)を入力し、カテゴリを選択します。

設定

次に各種設定を行います。 アプリケーションIDアプリのシークレットキーをメモっておきます。
連絡先メールアドレスを入力するまでは開発モードからリリースモードにならないようです。

あとは、+Add PlatformiOSを選択しアプリに設定するものと同じバンドルIDを入力します。(例:com.yourcompany.appname)
store IDはアプリ申請後、ストアIDを入手したら設定しましょう。

facebook.png


Facebookの登録も難しくありませんね。 次はいよいよParseの登録と設定を行いましょう。


  1. イントロダクション
  2. Twitterのアプリ登録
  3. Facebookのアプリ登録
  4. Parseの登録と設定
  5. Twitterアカウントでの認証
  6. Twitterのタイムライン投稿
  7. Facebookアカウントでの認証
  8. Facebookのフィード投稿

Twitter/Facebookのアカウントで認証して、アプリからタイムライン/フィードに投稿する[#2]〜Twitterのアプリ登録〜

登録

Twitterの開発者ページに入り右上のSigninからサインインします。
サインイン後、右上のボタンからMy Applicationsを選択します。 Create New AppからName, Description, Website, CallbackURLを設定します。
Name,Websiteは認証画面の表示に反映、CallbackURLは有効なURLを設定する必要があるみたいです。

あとは利用規約の同意にチェックを入れてポチッとやれば完了です。

設定

アプリの登録ができたら、API keyAPI Secretをメモっておき、Access levelRead onlyからRead and writeに変更します。
私はここでハマってしまい、読み出しのみのAPIは叩けるけど、投稿系が一切受け付けてくれないという事態に陥りました。
あとは、お好みでアイコン画像の変更をしてください。

twitter.png


Twitter側の設定はこれで完了です。 簡単ですね! 次はFacebookアプリの登録です。


  1. イントロダクション
  2. Twitterのアプリ登録
  3. Facebookのアプリ登録
  4. Parseの登録と設定
  5. Twitterアカウントでの認証
  6. Twitterのタイムライン投稿
  7. Facebookアカウントでの認証
  8. Facebookのフィード投稿