はじめに
前回から少し時間が空いてしまいましたが、
デスクトップアプリのWindows Live統合
これまで連載で紹介したLive Connectの利用は、
Live Connectの例ではありませんが、

アプリの登録
まず、

認可フロー
Live Connectでは、
OAuthの認可フローによって、
①認可画面の表示
認可画面は、
認可画面のURLは次の通りです。
- https://
oauth. live. com/ authorize?client_ id=CLIENT_ ID &scope=SCOPES&response_type=token&redirect_ uri=https:// oauth. live. com/ desktop
ここでリダイレクト先を指定する必要がありますが、
②アクセストークンの取得
認可処理が完了すると、
- https://
oauth. live. com/ desktop#access_ token=[AccessToken]
上記のURLへ移動したら、
アクセストークンの更新
少しだけ補足します。アクセストークンの有効期限は、
これから紹介するサンプルアプリでは、
サンプルアプリの作成
それでは、
サンプルアプリは、
今回のサンプルアプリは、

それでは、
サインインウィンドウ
最初に、
新しい項目の追加から、
<Window x:Class="SignInWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="サインイン" Height="450" Width="560">
<Grid>
<WebBrowser x:Name="SignInWebBrowser" />
</Grid>
</Window>
SignInWindow.
Private ClientId As String
Private Scopes As New List(Of String)
Public Sub New(clientId As String, scope As IEnumerable(Of String))
Me.ClientId = clientId
Me.Scopes.AddRange(scope)
InitializeComponent()
End Sub
ウィンドウを開いた時にWebブラウザーコントロールに認証・
Private Const AuthorizeUriFormat As String = "https://oauth.live.com/authorize?client_id={0}&scope={1}&response_type=token&locale=ja&display=popup&redirect_uri=https://oauth.live.com/desktop"
Private Sub SignInWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
SignInWebBrowser.Navigate(
String.Format(AuthorizeUriFormat, Me.ClientId, String.Join("+", Me.Scopes)))
End Sub
サインインウィンドウ クラスに、
Private _AccessToken As String
ReadOnly Property AccessToken As String
Get
Return _AccessToken
End Get
End Property
ユーザーが認可処理を終えると、
Private Sub SignInWebBrowser_Navigated(sender As System.Object, e As System.Windows.Navigation.NavigationEventArgs) Handles SignInWebBrowser.Navigated
' 表示しているページの URL が https://oauth.live.com/desktop でなければ処理を抜ける
Dim redirectUri = New Uri("https://oauth.live.com/desktop")
If e.Uri.Host <> redirectUri.Host OrElse
e.Uri.AbsolutePath <> redirectUri.AbsolutePath Then
Exit Sub
End If
' URL のフラグメント部分から access_token の値を取得する
If e.Uri.Fragment.Contains("access_token") Then
Dim items = New Dictionary(Of String, String)
Dim param = e.Uri.Fragment.Substring(1).Split({"&"c, "="c})
For i = 0 To param.Length - 1 Step 2
items.Add(param(i), param(i + 1))
Next
If items.ContainsKey("access_token") Then
' URL に access_token が含まれていた場合
_AccessToken = items("access_token")
Me.DialogResult = True
End If
End If
' サインインウィンドウを閉じる
Me.Close()
End Sub
最後にウィンドウを閉じて完了です。以上で、
メインウィンドウ
次は、
<my:RibbonWindow x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
Title="アプリ" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<my:Ribbon FontFamily="Meiryo UI">
<my:RibbonTab Header="ホーム">
<my:RibbonGroup>
<my:RibbonButton
x:Name="SignInButton"
Label="サインイン"
LargeImageSource="signout.png" />
<my:RibbonMenuButton
x:Name="SignOutMenuButton"
LargeImageSource="signout.png"
Label="名前"
Visibility="Collapsed">
<my:RibbonMenuItem
x:Name="SignOutMenuItem"
Header="サインアウト" />
</my:RibbonMenuButton>
</my:RibbonGroup>
</my:RibbonTab>
</my:Ribbon>
</Grid>
</my:RibbonWindow>
上記のコード編集のとき、
サインインボタンをクリックしたときに、
Private Sub SignInButton_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles SignInButton.Click
Dim window = New SignInWindow("*** Client ID を指定***", New String() {"wl.share"}) With {
.Owner = Me,
.WindowStartupLocation = Windows.WindowStartupLocation.CenterOwner}
If window.ShowDialog <> True Then
Exit Sub
End If
End Sub
SignInWindowオブジェクトを生成する際に、
ここまでを一度実行してみましょう。作成したサインインウィンドウが表示されましたか?

サインインウィンドウで認可処理を行うとウィンドウが閉じます。その後の処理は、
サインインウィンドウのクラスからアクセストークンを得て、
' 必要な Imports
' Imports System.Net
' Imports System.Threading.Tasks
' Imports Newtonsoft.Json
' Imports Newtonsoft.Json.Linq
' Developer Preview の REST API URI
Private Const LiveUriFormat As String = "https://beta.apis.live.net/v5.0/{0}?access_token={1}"
Private AccessToken As String
Private Sub SignInButton_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles SignInButton.Click
Dim window = New SignInWindow(ClientId, New String() {"wl.share"}) With {
.Owner = Me,
.WindowStartupLocation = Windows.WindowStartupLocation.CenterOwner}
If window.ShowDialog <> True Then
Exit Sub
End If
' (メソッド内は下記のコードを追加)
Me.AccessToken = window.AccessToken
Task.Factory.StartNew(
Function() As JObject
' REST API の呼び出し
Using client = New WebClient With {.Encoding = System.Text.Encoding.UTF8}
' ユーザーの情報を JSON データを取得
Dim json = client.DownloadString(String.Format(LiveUriFormat, "me", Me.AccessToken))
Return JObject.Parse(json)
End Using
End Function).ContinueWith(
Sub(o As Task(Of JObject))
' UI の変更 (サインインボタンの非表示、ユーザーのアイコン表示など)
Me.SignInButton.Visibility = Windows.Visibility.Collapsed
Me.SignOutMenuButton.Visibility = Windows.Visibility.Visible
Me.SignOutMenuButton.Label = o.Result("name").Value(Of String)()
Dim iconUri = New Uri(String.Format(LiveUriFormat, "me/picture", Me.AccessToken))
Dim bmp = New BitmapImage(iconUri)
Me.SignOutMenuButton.LargeImageSource = bmp
End Sub, TaskScheduler.FromCurrentSynchronizationContext)
End Sub
追加した主なコードは、
UIの変更では、
サインアウト処理も書いておきましょう。実は、
Private Sub SignOutMenuItem_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles SignOutMenuItem.Click
Me.AccessToken = Nothing
Me.SignInButton.Visibility = Windows.Visibility.Visible
Me.SignOutMenuButton.Visibility = Windows.Visibility.Collapsed
End Sub
ちなみに、
以上で、

コードからわかる通り、
表示メッセージの更新
次は、

Activityオブジェクト
Live Connectで利用する場合、
{
"description": "デスクトップアプリからの利用を紹介します。",
"link": "http://gihyo.jp/dev/serial/01/wl-sdk/0047",
"message": "第47回 デスクトップアプリでWindows Live統合",
"name": "使ってみよう! Windows Live SDK/API",
"picture": "http://image.gihyo.co.jp/assets/images/ICON/2008/thumb/TH64_137_wl-sdk.png"
}
Activityオブジェクトの内容は次の通りです。
プロパティ | 型 | 説明 |
---|---|---|
message | string | メッセージ |
link | string | 共有する内容のURL |
description | string | 共有する内容の説明 |
picture | string | 共有する内容のサムネイル画像のURL |
name | string | 共有する内容のタイトル |
source | string | 動画の共有の場合、 |
上記の内容に加えて、
{
"from": {
"name": "梓 中野",
"id": "xxxxx"
},
"message": "第47回デスクトップアプリでWindows Live統合",
"link": "http://gihyo.jp/dev/serial/01/wl-sdk/0047",
"description": "デスクトップアプリからの利用を紹介します。",
"picture": "http://image.gihyo.co.jp/assets/images/ICON/2008/thumb/TH64_137_wl-sdk.png",
"name": "使ってみよう! Windows Live SDK/API",
"source": null
}
値は次の通りです。
プロパティ | 型 | 説明 |
---|---|---|
from | string | 共有した |
id | string | ユーザーのID |
サンプルアプリ
さきほど作ったサンプルアプリに、
メインウィンドウのXAMLコードに追記し、
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Top" Margin="5">
<TextBox x:Name="StatusTextBox" Width="300" />
<Button x:Name="PostButton" Content="投稿" Width="80" Margin="10 0 0 0" />
</StackPanel>
投稿ボタンをクリックしたときの処理を、
Private Sub PostButton_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles PostButton.Click
Dim message = StatusTextBox.Text
task.Factory.StartNew(
Function() As JObject
' Activity の作成
Dim activity = New JObject
activity("message") = message
' REST API 呼出し(投稿)
Using client = New WebClient With {.Encoding = System.Text.Encoding.UTF8}
client.Headers(HttpRequestHeader.ContentType) = "application/json"
Dim json = client.UploadString(String.Format(LiveUriFormat, "me/share", Me.AccessToken),
JsonConvert.SerializeObject(activity, Formatting.None))
Return JObject.Parse(json)
End Using
End Function).ContinueWith(
Sub(o)
MessageBox.Show("投稿しました")
End Sub, TaskScheduler.FromCurrentSynchronizationContext)
End Sub
編集は以上です。実行して確認してみてください。上記コードでは、
次のようにほかの値も指定すると画像の共有なども可能です。こちらも試してみてください。
' Activity の作成
Dim activity = New JObject
activity("message") = "第47回 デスクトップアプリでWindows Live統合"
activity("link") = "http://gihyo.jp/dev/serial/01/wl-sdk/0047"
activity("description") = "デスクトップアプリからの利用を紹介します。"
activity("picture") = "http://image.gihyo.co.jp/assets/images/ICON/2008/thumb/TH64_137_wl-sdk.png"
activity("name") = "使ってみよう! Windows Live SDK/API"
live.

おわりに
今回は以上です。いかがでしたでしょうか。デスクトップアプリからのLive Connectの利用について紹介しました。モバイルアプリも同じようにWebブラウザーコントロールを使用してアクセストークンを取得します。注釈で少しふれていますが、
Liveサービスとの連携では、