Facebook App事始め−その2

さてさてWindows 10もインストールしたので、久しぶりにやる気を出して、Winストアアプリの開発に戻ってみることにした。
とりあえず課題として、Facebookのフォトブラウザなど作ってみることにした。
ところが、これが忘却曲線どころの話ではない。
.net環境でFacebook Appを作成するのには、Facebook SDK for .netを利用するのが手っ取り早いのだが、なんとサイトの内容がほとんど最新のSDKFacebook SDKの内容を反映していないのだ。
例えばこのhttp://facebooksdk.net/docs/windows/controls/login-ui-control/など、このままやると完璧なbad endなのだ。
おまけにhttp://facebooksdk.net/docs/windows/config/は不要ときたもんだ。
幸いなことにいろいろと情報が落ちていたのと、サンプルコードは動作したので、ここから手探りで動作するコードを作っていった。

Visual Studioでプロジェクトを作成する

  • Visual C# -> Sore Apps -> Winodws Apps、名前は"FacebookAho"。

AppをWindows Storeに関連付ける

  • Visual StudioのSolution Explorerでプロジェクトを右クリックして、Store -> Associate App with the Store...を選択する
  • "Next"で進むと、Windows Storeへのsign-inを促されるので従う、いちいちcode入力をさせられるのが面倒くさい
  • "Select an app name"になるので、"Reserve a new app name"欄で、Appの名前(FacebookAho)を入力して、"reserve"を押して、予約ができたら"Next"
  • 最後の画面で"Associate"を押して完了

AppのPackage Store IDを取得

  • https://dev.windows.com/にアクセスしてsign-inする、sign-inしたら"Dashboard"に移動
  • Dashboardには"My apps"がリストされているので、先ほど予約したAppの名前(FacebookAho)を選択する
  • "App Management" -> "App Identity"を選択、Package SIDがあるので、これをコピーしておく

Package Store IDをFacebook Appに登録する

  • こちらを参考に、Facebook Developerから自分のAppを登録する
  • 登録が終わったら、"Setting" -> "+ Add Platfrom"から"Windows App"を選択する
  • "Windows App"が追加されるので、先ほどコピーしたPackage SIDを張り付けて、"Save Change"を押す
  • 上の"Advanced"のタグを選び、"Embedded Browser OAuth Login"をYesにして、"Valid OAuth redirect URIs"に"https://www.facebook.com/connect/login_success.html"を設定する

Facebook SDK for .netをNuGetからインストー

  • Visual Studioの"Tools" -> "NuGet Package Manager" -> "Package Manager Console"を選択する
  • コンソールから下記の呪文を流し、Facebook SDK for .netをインストールする


Install-Package Facebook.Client -pre

画面の設計

  • MainPage.xamlのGridの内容を以下のように変更











グリッドを横に3つ切って、一番上にFacebookにloginするためのボタン、真ん中にプロフィール写真、下に名前を配置した

(XAMLエディタでButtonの記載行に移動して、"Properties"のイベントハンドラー一覧から"Click"のハンドラーとして"onClick"を登録する)
このボタンを押すとFacebookへのログインが開始する。

Facebookへのログイン、ユーザープロファイルの取得の実装

  • まずログインするメソッドを実装する


private async Task asyncLogin()
{
var scope = "public_profile";
//
var redirectUri = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
var FB = new FacebookClient();
var loginUrl = FB.GetLoginUrl(
new
{
client_id = clientID,
redirect_uri = redirectUri,
response_type = "token",
scope = scope
});
Uri startUri = loginUrl;
Uri endUri = new Uri(redirectUri, UriKind.Absolute);
WebAuthenticationResult waResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, startUri, endUri);
}


private async void onClick(object sender, RoutedEventArgs e)
{
await asyncLogin();
}
呼び出すメソッドがasyncなので、イベントハンドラーの修飾子に"async"を追加する。

  • 次にログインが完了した後に、Access Tokenを取得するメソッドを実装する。


private void parseAuthenticationResult(WebAuthenticationResult result)
{
switch (result.ResponseStatus)
{
case WebAuthenticationStatus.ErrorHttp:
Debug.WriteLine("HTTP error");
break;
case WebAuthenticationStatus.UserCancel:
Debug.WriteLine("User cancelled the operation");
break;
case WebAuthenticationStatus.Success:
string keyAccessToken = "access_token=";
string keyExpiresIn = "&expires_in=";
int indexAccesssTokenStart = result.ResponseData.IndexOf(keyAccessToken) + keyAccessToken.Length;
int indexAccesssTokenEnd = result.ResponseData.IndexOf(keyExpiresIn, indexAccesssTokenStart);
int indexExpiresInStart = indexAccesssTokenEnd + keyExpiresIn.Length;
AccessToken = result.ResponseData.Substring(indexAccesssTokenStart, indexAccesssTokenEnd - indexAccesssTokenStart);
TokenExpiry = DateTime.Now.AddSeconds(double.Parse(
result.ResponseData.Substring(indexExpiresInStart, result.ResponseData.Length - indexExpiresInStart)));
break;
default:
break;
}
}
AcessTokenとTokenExpireはクラスのメンバーにしておく。

  • ユーザープロファイルを取得するメソッドを実装する。


private async Task getUserProfile()
{
var fbMyClient = new FacebookClient(AccessToken);
dynamic user = await fbMyClient.GetTaskAsync("me");
string UserProfilePictureURL =
string.Format(
"https://graph.facebook.com/{0}/picture?type={1}&access_token={2}",
user.id,
"normal",
AccessToken);
imgFBUserPhoto.Source = new BitmapImage(new Uri(UserProfilePictureURL));
txtblckFBUserName.Text = user.name;
}
これでログインが完了し、Access Tokenが取得できれば、ユーザープロファイルを取得した上で、ユーザー名とプロフィール写真を画面上に表示してくれる。


あとはいろいろガチャコンすれば出来上がり、最終的なMainPage.xaml.csは下記のようになる。


public sealed partial class MainPage : Page
{
//
public static string clientID = "(ここにFacebook Developerで登録した自分のAppのApp IDを記入)";
public string AccessToken;
public DateTime TokenExpiry;
//
public MainPage()
{
this.InitializeComponent();
//
AccessToken = string.Empty;
}

private async Task asyncLogin()
{
var scope = "public_profile";
//
var redirectUri = WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();
var FB = new FacebookClient();
var loginUrl = FB.GetLoginUrl(
new
{
client_id = clientID,
redirect_uri = redirectUri,
response_type = "token",
scope = scope
});
Uri startUri = loginUrl;
Uri endUri = new Uri(redirectUri, UriKind.Absolute);
WebAuthenticationResult waResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, startUri, endUri);
parseAuthenticationResult(waResult);
await getUserProfile();
}

private async Task getUserProfile()
{
var fbMyClient = new FacebookClient(AccessToken);
dynamic user = await fbMyClient.GetTaskAsync("me");
string UserProfilePictureURL =
string.Format(
"https://graph.facebook.com/{0}/picture?type={1}&access_token={2}",
user.id,
"normal",
AccessToken);
imgFBUserPhoto.Source = new BitmapImage(new Uri(UserProfilePictureURL));
txtblckFBUserName.Text = user.name;
}

private void parseAuthenticationResult(WebAuthenticationResult result)
{
switch (result.ResponseStatus)
{
case WebAuthenticationStatus.ErrorHttp:
Debug.WriteLine("HTTP error");
break;
case WebAuthenticationStatus.UserCancel:
Debug.WriteLine("User cancelled the operation");
break;
case WebAuthenticationStatus.Success:
string keyAccessToken = "access_token=";
string keyExpiresIn = "&expires_in=";
int indexAccesssTokenStart = result.ResponseData.IndexOf(keyAccessToken) + keyAccessToken.Length;
int indexAccesssTokenEnd = result.ResponseData.IndexOf(keyExpiresIn, indexAccesssTokenStart);
int indexExpiresInStart = indexAccesssTokenEnd + keyExpiresIn.Length;
AccessToken = result.ResponseData.Substring(indexAccesssTokenStart, indexAccesssTokenEnd - indexAccesssTokenStart);
TokenExpiry = DateTime.Now.AddSeconds(double.Parse(
result.ResponseData.Substring(indexExpiresInStart, result.ResponseData.Length - indexExpiresInStart)));
break;
default:
break;
}
}

private async void onClick(object sender, RoutedEventArgs e)
{
await asyncLogin();
}

}

  • いろいろ足りたいと文句を言われるので、以下のnamespaceを参照として追加


using System.Threading.Tasks;
using Facebook;
using Windows.Security.Authentication.Web;
using System.Diagnostics;
using Windows.UI.Xaml.Media.Imaging;
さて、これでビルド、デプロイすれば実行できたぬき!


(追記 on 20150907)このコードはエラー処理をちゃんとしていないので、適当なことをするとクラッシュします、Alpha以下の品質ということでよろしくおねがいしまつ。