Facebook もそうですが、ログイン処理には WebView を使ってユーザにはブラウザでログインするのと同じ処理をしてもらい、その結果で返ってくる URL 情報によって以降のアクセスで利用する『アクセストークン』を取得します。 プログラム作成に先だって、APIs Console で自分の API キー等を取得しておきます。( アプリは Client ID for web applications で取得 )![]()
それぞれの API は API エクスプローラでテストする事ができます。例えばそのユーザが持ってるカレンダーの一覧は簡単に見る事ができます(右上の OAuth 2.0 をオンにしてログインする必要があります ) アプリに登録する『リダイレクト場所』は、WEB 上の自分が管理する URL にします。このログインでは直接利用しませんが、実際はログイン後にユーザになんらかの情報を受け渡す為に使うといいと思います。 注意する事として、Google のログインページは JavaScript を使用しますので、Android や Windows Phone で同様の処理をする場合は、ブラウザの JavaScript を有効にしておく必要があります LoginPage.xaml
<Page
x:Class="Win8_C_Sharp_GoogleLogin.LoginPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Win8_C_Sharp_GoogleLogin"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<!-- 戻るボタン -->
<Button
x:Name="backButton"
Style="{StaticResource BackButtonStyle}"
Click="backButton_Click"
VerticalAlignment="Top"
Margin="101,52,0,0"/>
<!-- 処理表示 -->
<TextBlock
HorizontalAlignment="left"
Margin="208,52,0,0"
TextWrapping="Wrap"
Text="ログイン処理"
VerticalAlignment="Top"
Height="60"
Width="260" FontSize="48"/>
<!-- ログイン認証WebView -->
<WebView
x:Name="webView"
HorizontalAlignment="left"
Height="689"
Margin="101,136,0,-57"
VerticalAlignment="Top"
Width="1039"
LoadCompleted="webView_LoadComplete"/>
</Grid>
</Page>
LoginPage.xaml
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Storage;
using System.Diagnostics;
using System.Net.Http;
using Newtonsoft.Json.Linq;
namespace Win8_C_Sharp_GoogleLogin
{
public sealed partial class LoginPage : Page
{
// ***************************************************
// コンストラクタ
// ***************************************************
public LoginPage()
{
this.InitializeComponent();
FacebookLogin();
}
// ***************************************************
// WebView の表示
// ***************************************************
private void FacebookLogin()
{
// 対象となる URL を取得
String url = App.gc.getLoginUrl();
//
webView.Navigate(new Uri(url));
}
// ***************************************************
// WebView がページを表示し終わった時の処理
// ***************************************************
private async void webView_LoadComplete(object sender, NavigationEventArgs e)
{
// URL を取得
String token = e.Uri.ToString();
if (token.IndexOf("code=") == 0)
{
// URL に含まれる仮のアクセストークンを取得する
int cur = token.IndexOf("=");
String code = token.Substring(cur+1);
// アクセストークンを取得
await App.gc.getAccessToken(code);
// ユーザ情報を取得
String info = await App.gc.getUserInfo();
// このページを呼び出したメインページのフィールドにセット
// 但し、メインページに戻る時は、GoBack を使ってはいけない
((TextBox)App.mainPage.FindName("PostBody")).Text = info;
}
}
// ***************************************************
// メインページに戻る処理
// ***************************************************
private void backButton_Click(object sender, RoutedEventArgs e)
{
// 前のページに戻る「this.Frame.GoBack()」を実行するとMainPageの結果が消えてしまうため、
// 一時変数を用意し、ページ遷移後に一時変数の中身をMainPageにセットする
MainPage mp = App.mainPage;
Frame rootFrame = Window.Current.Content as Frame;
rootFrame.Content = App.mainPage;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
}
ここでは、前のページに戻る処理が重要です。サンプル等で使われている GoBack() では、元のページのインスタンスが新たに作成されるようなので、『ログイン』のようなダイアログ的な処理で使うととても都合が悪くなります。また、それに伴って、FindName で元のページのフィールドを参照する方法は重要です。 メインページのインスタンスは、起動時に App.xaml.cs で static の プロパティとして設定しておいて、アプリ全体からいつでもアクセスできるようにしておきます。 ログインや API の処理をするクラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Windows.Data.Json;
namespace Win8_C_Sharp_GoogleLogin
{
public class NGCalendar
{
// API Console 情報
private String API_KEY = "";
private String client_id = "";
private String client_secret = "";
// ログイン処理
private String loginUrl = "https://accounts.google.com/o/oauth2/auth";
private String type = "code";
// redirect_uri は、API に登録した URL( ここでは Google Plus の プロフィールページでテスト )
private String redirect_uri = "";
// スコープ(権限)を設定 / 後で自分の情報を取得するのに、Gooogle Plus のスコープも設定
private String scope = "https://www.googleapis.com/auth/calendar+https://www.googleapis.com/auth/calendar.readonly+https://www.googleapis.com/auth/plus.me";
// 最終データ
private String code = "";
private String access_token = "";
private String token_type = "";
// Google API 取得先
private String oauth2_url = "https://accounts.google.com/o/oauth2/token";
private String g_calendar_list_url = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
private String g_galendar_event_url = "https://www.googleapis.com/calendar/v3/calendars/[id]/events";
// ***************************************************
// GoogleログインURLを取得する
// ***************************************************
public String getLoginUrl()
{
String access_url = "";
access_url = loginUrl;
access_url += "?response_type=" + type;
access_url += "&client_id=" + client_id;
access_url += "&redirect_uri=" + redirect_uri;
access_url += "&scope=" + scope;
return access_url;
}
// ***************************************************
// アクセストークンを取得する (POST)
// ***************************************************
public async Task<Boolean> getAccessToken(String code)
{
Boolean result = true;
try
{
// Webにアクセスする
HttpClient httpClient = new HttpClient();
HttpRequestMessage requestMsg = new HttpRequestMessage();
requestMsg.Method = new HttpMethod("POST");
String body = "";
body = "code=" + code;
body += "&grant_type=authorization_code";
body += "&redirect_uri=" + redirect_uri;
body += "&client_id=" + client_id;
body += "&client_secret=" + client_secret;
// 指定したURIを非同期で通信
requestMsg.Content = new StringContent(body);
requestMsg.Method = new HttpMethod("POST");
requestMsg.RequestUri = new Uri(oauth2_url, UriKind.Absolute);
requestMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
// 呼び出し( 非同期 )
var response = await httpClient.SendAsync(requestMsg);
// 情報取得( 非同期 )
String res = await response.Content.ReadAsStringAsync();
// Json文字列を整形( Freamwork の JSON 処理 )
JsonValue jv = JsonValue.Parse(res);
// JSON よりアクセストークンとトークンのタイプを取得する
this.access_token = jv.GetObject().GetNamedString("access_token");
this.token_type = jv.GetObject().GetNamedString("token_type");
}
catch (Exception Err)
{
result = false;
}
return result;
}
// ***************************************************
// カレンダー一覧を取得する (GET)
// ▼ API エクスプローラでテストできます
// https://developers.google.com/apis-explorer/#p/calendar/v3/calendar.calendarList.list
// ***************************************************
public async Task<String> getCalendarList()
{
try
{
String api_url = g_calendar_list_url + "?key=" + API_KEY;
HttpClient httpClient = new HttpClient();
HttpRequestMessage requestMsg = new HttpRequestMessage();
requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
requestMsg.Method = new HttpMethod("GET");
// ヘッダにアクセスする為の情報(アクセストークン)をセット
// API エクスプローラで実際の内容を見る事ができます
httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);
// 呼び出し( 非同期 )
var response = await httpClient.SendAsync(requestMsg);
// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
return await response.Content.ReadAsStringAsync();
}
catch (Exception Err)
{
throw;
}
}
// ***************************************************
// カレンダーに登録されたイベントを取得する ( GET )
// ***************************************************
public async Task<String> getCalendarEvent(String cid)
{
try
{
String api_url = g_galendar_event_url.Replace("[id]", Uri.EscapeDataString(cid)) + "?key=" + API_KEY;
HttpClient httpClient = new HttpClient();
HttpRequestMessage requestMsg = new HttpRequestMessage();
requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
requestMsg.Method = new HttpMethod("GET");
// ヘッダにアクセスする為の情報(アクセストークン)をセット
httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);
// 呼び出し( 非同期 )
var response = await httpClient.SendAsync(requestMsg);
// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
return await response.Content.ReadAsStringAsync();
}
catch (Exception Err)
{
throw;
}
}
// ***************************************************
// Google Plus よりユーザー情報を取得する ( GET )
// ***************************************************
public async Task<String> getUserInfo()
{
try
{
String api_url = "https://www.googleapis.com/plus/v1/people/me?key=" + API_KEY;
HttpClient httpClient = new HttpClient();
HttpRequestMessage requestMsg = new HttpRequestMessage();
requestMsg.RequestUri = new Uri(api_url, UriKind.Absolute);
requestMsg.Method = new HttpMethod("GET");
// ヘッダにアクセスする為の情報(アクセストークン)をセット
httpClient.DefaultRequestHeaders.Add("Authorization", token_type + " " + access_token);
// 呼び出し( 非同期 )
var response = await httpClient.SendAsync(requestMsg);
// 情報取得( 非同期 ) / 直接呼び出し元へ返しています( String )
return await response.Content.ReadAsStringAsync();
}
catch (Exception Err)
{
throw;
}
}
}
}
ここでは、JSON の処理を Framework で行っていますが、実際は Json.NET で行うととても便利です。Json.NET を使うと、ListBox 等の一覧処理が JSON 文字列からバインドまでを一気にできるようになります。 また、Windows8 では非同期処理でイベントを定義する必要がありません。async と await を駆使してコードを書くことができます。 関連する記事 Windows Phone(C#) のデータバインドを Json.NET を使って一行で実装する( しかも XML を JSON 変換して使う ) Windows8 の非同期処理(C#) Windows8(C#) の WebView の LoadComplete で取得した URL 内のアクセストークンを Split で取得
|
|
【Win8 ストアアプリの最新記事】
- C# : HttpClient で Post と Get する汎用 static クラス
- Win8.1 ストアアプリ(JS) : Visual Studio 2013 で Three.js(v65) の WebGLRenderer の動作を確認しました
- WinJS ストア : Three.js を組み込んで、『画像を飛ばす』テンプレート( Bird.js を利用 )
- WinJS ストア : 『背景画像をチェンジする2画面アプリ』のテンプレート
- VS2012ストア(C#) : WebView テンプレート
- VS2012(C#)ストア : ListView Twitter 検索テンプレート
- イラストを背景にして2ページの画面遷移を解りやすくした Windows Store テンプレート
- Twitter API の自分のアプリのトークンを使って投稿するだけの class VS2012_Twitter
- Win8 ストア(C#) / PDF viewer sample (Windows 8.1)
- ストアアプリの TextBox のスクロールバー
- Win8 ストアアプリの、メモリ上にページを残す画面遷移と、前画面のコントロールの参照
- Win8 ストアアプリで、『選択肢を応答するダイアログ』を簡単に使うための MessageBox クラス
- Win8 ストアから Post 投稿
- Win8ストア XAML の AppBarButtonStyle のContent に指定する 16進数 Unicode の取得
- Win8 ストア : UrlEncode と UrlDecode
- Win8 ストア : HttpClient + XDocument で RSS の取得
- Win8 ストア : リストボックス テンプレート
- Win8 ストア : ファイルアクセス テンプレート
- Win8 ストア : ストアブランク テンプレート
- AppBar テンプレート / Win8 ストアアプリ(C#)


それぞれの API は API エクスプローラでテストする事ができます。例えばその



