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#)