はつねの日記

Kinect, Windows 10 UWP, Windows Azure, IoT, 電子工作

Live SDK v5.3

Live SDKを使うとLive IDによるシングルサインオンSkyDrive連携、Hotmailのカレンダー連携などが行えます。

また、Windows RuntimeやWindows Phone Runtimeからも使えます。

ダウンロードとインストール

Live SDKの最新版は執筆時点ではV5.3になっています。V5.3のダウンロードは以下のURLから行います。

http://www.microsoft.com/en-us/download/details.aspx?id=35754

Live SDKのインストールファイルはmsi形式なのでダウンロードしたファイルをダブルクリックすればインストールできます。

プロジェクトからの参照設定

image

アプリの登録

Live SDKを使ったアプリを作成するためには、Live Connect Developer Centerに登録が必要です。

また、Windowsストアアプリの場合、事前にWindows Store Dashboardでアプリ名の登録が完了していなければなりません。

image

 

Live Connect Developer Centerに登録すると、OAuth2.0でログインするときに必要なIDも入手できます。image

しかし、Live SDKを使うとOAuth 2.0を意識することなくWindows 8にログインしたMicrosoftアカウントによるシングルサインオンが実現できます。

Live SDKによるシングルサインインの作成

Live SDKを使ってシングルサインインを実現するときも最初の1回だけアプリで明示的にログインが必要です。

次の例ではSignInAsync(False)で呼び出して(シングルサインインができていれば)ユーザ名を取得し、SignInAsync(True)で呼び出すことで明示的にサインインを行ってからユーザ名を取得するコードになります。

注意点は一度シングルサインインの設定が完了するとサインアウトができない点です。

Imports Microsoft.Live
Public Class AccountModel
     Implements INotifyPropertyChanged
     Private _UserName As String
     Public Property UserName As String
         Get
             Return _UserName
         End Get
         Private Set(value As String)
             _UserName = value
             NotifyPropertyChanged()
         End Set
     End Property
     Public Async Function SignInAsync(isLogin As Boolean) As Task
         Dim client As New LiveAuthClient
         Try
             Dim result As LiveLoginResult = Await client.InitializeAsync()
             If isLogin Then
                 result = Await client.LoginAsync(New String() {"wl.signin", "wl.basic", "wl.calendars"})
             End If
             If result.Status = LiveConnectSessionStatus.Connected Then
                 Dim connect As New LiveConnectClient(client.Session)
                 Dim data As LiveOperationResult = Await connect.GetAsync("me")
                 Me.UserName = data.Result("name").ToString
             Else
                 Me.UserName = ""
             End If
         Catch ex As Exception
         End Try
     End Function
     Public Async Function SignOutAsync() As Task
         Dim client As New LiveAuthClient
         Try
             Dim result As LiveLoginResult = Await client.InitializeAsync()
             If result.Status = LiveConnectSessionStatus.Connected Then
                 client.Logout()
             End If
             Me.UserName = ""
         Catch ex As Exception
         End Try
     End Function
     Public Event PropertyChanged(sender As Object,
                              e As PropertyChangedEventArgs) _
                          Implements INotifyPropertyChanged.PropertyChanged
     Private Sub NotifyPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)
         RaiseEvent PropertyChanged(Me,
                                    New PropertyChangedEventArgs(propertyName))
     End Sub End Class

Liveでの用語は「サインイン」、「サインアウト」なんですがSDKのメソッド名はLogin、Logoutなんですよねー。

Live SDKによるシングルサインイン実行

image

image

 

[Sign in]ボタンをクリックするとSignInAsync(True)が呼び出され、client.LoginAsync(New String() {"wl.signin", "wl.basic", "wl.calendars"})を実行するので権限確認ダイアログが自動表示されます。

image

Microsoftアカウントページでの確認

Live SDKまたはOAuth2.0でLiveIDを使ってアプリにログインすると、Microsoftアカウントページの「Apps and services」のリストにアプリが追加されます。

https://account.live.com/consent/Manage

image

本来は日本語で表示されるのですが、私の普段使いのアカウントはなぜか英語認定されているため画面ハードコピーは英語表記だったりします。

LiveSDKによるイベント一覧の取得

サインインができたらLiveSDKでイベント(hotmailのカレンダー情報)を取得してみましょう。

    Public Async Function GetDataAsync() As Task

        Try             Dim client As New LiveAuthClient
            Dim result As LiveLoginResult = Await client.InitializeAsync()
             result = Await client.LoginAsync(New String() {"wl.signin", "wl.basic", "wl.calendars"})
             If result.Status = LiveConnectSessionStatus.Connected Then
                 Dim items As New List(Of TLiveEventItem)
                 Dim liveClient As New LiveConnectClient(result.Session)
                 Dim operationResult As LiveOperationResult = Await liveClient.GetAsync("me/events")
                 Dim events = operationResult.Result("data")
                 For index As Integer = 0 To events.Count - 1
                     If Not CType(events(index)("is_all_day_event"), Boolean) Then
                         items.Add(New TLiveEventItem With {
                                       .id = events(index)("id").ToString,
                                       .name = events(index)("name").ToString,
                                       .description = events(index)("description").ToString,
                                       .start_date = events(index)("start_time").ToString.Substring(0, 7),
                                       .start_time = events(index)("start_time").ToString,
                                       .end_time = events(index)("end_time").ToString,
                                       .location = events(index)("location").ToString,
                                       .is_all_day_event = CType(events(index)("is_all_day_event"), Boolean),
                                       .reminder_time = CType(events(index)("reminder_time"), Integer)
                                   })
                     End If
                 Next
                 Dim categories = _
                     From liveEvent In items
                     Where Not liveEvent.is_all_day_event
                     Group liveEvent By liveEvent.start_date Into eventCount = Count()
                     Select start_date
                 For Each category In categories
                     Dim group As New EventModelGroup(category,
                                                      category,
                                                      "",
                                                      "",
                                                      "")
                     Dim eventItems = From liveEvent In items
                                      Where liveEvent.start_date = category
                     For Each item In eventItems
                         group.Items.Add(New EventModelItem(item.id,
                                                            item.name,
                                                            "",
                                                            "",
                                                            item.description,
                                                            "",
                                                            item.start_date,
                                                            item.start_time,
                                                            item.end_time,
                                                            item.location,
                                                            item.is_all_day_event,
                                                            group))
                     Next
                     Me._allGroups.Add(group)
                 Next
             End If
         Catch ex As Exception
             Throw New Exception("Error posting data to LiveCalendar:" & ex.Message)
         Finally
             RaiseEvent Completed(Me._allGroups)
         End Try
     End Function
     Public Event Completed(ByVal group As ObservableCollection(Of EventModelGroup))

LiveSDKによるイベント一覧取得の実行結果
このコードをWindowsストアアプリのテンプレートから作成したプロジェクトに組み込んだ実行結果は次のようになります。

image

OAuth2.0によるサインインの作成

Live SDKでのサインインの他にOAuth2.0でもLiveにサインインすることができます。こちらの方法はLive SDKのインストールや参照などは不要ですがLive SDKのように専用メソッドなどがある訳ではないので少しだけ手間がかかります。

Imports Windows.Security.Authentication.Web
Public Class AuthModel
     Implements INotifyPropertyChanged
     Private Const OAuth2Url As String = "https://oauth.live.com/authorize" &
                                         "?client_id={0}" &
                                         "&scope={1}" &
                                         "&response_type=token" &
                                         "&redirect_uri={2}" &
                                         "×tamp={3}"
     Public Property AccessToken As String
         Get
             Return Settings.AccessToken
         End Get
         Set(value As String)
             Settings.AccessToken = value
             Call NotifyPropertyChanged()
             Call NotifyPropertyChanged("IsLogin")
         End Set
     End Property
     Public ReadOnly Property IsLogin As Boolean
         Get
             Return (Settings.AccessToken IsNot Nothing)
         End Get
     End Property
     Public ReadOnly Property AuthUrl As String
         Get
             Return String.Format(OAuth2Url,
                                  Settings.ClientId,
                                  "wl.signin%20wl.basic%20wl.calendars",
                                  Settings.RedirectUrl,
                                  Date.Now.ToString("yyyyMMddHHmmss"))
         End Get
     End Property
     Public Async Function OAuthLogin() As Task
         Dim loginUrl As String = AuthUrl
         Dim result As WebAuthenticationResult =
             Await WebAuthenticationBroker.AuthenticateAsync(
                                                 WebAuthenticationOptions.None,
                                                 New Uri(loginUrl),
                                                 New Uri(Settings.RedirectUrl))
         If result.ResponseStatus = WebAuthenticationStatus.Success Then
             Dim accessToken As String = result.ResponseData.ToString
             Dim prefix As String = Me.CallbackPrefix
             If accessToken.StartsWith(prefix) Then
                 accessToken = accessToken.Substring(prefix.Length)
                 If accessToken.IndexOf("&") >= 0 Then
                     accessToken = accessToken.Substring(0, accessToken.IndexOf("&"))
                 End If
                 Me.AccessToken = accessToken
             End If
         End If
     End Function
     Public ReadOnly Property CallbackPrefix As String
         Get
             Return Settings.RedirectUrl & "#access_token="
         End Get
     End Property
     Public Event PropertyChanged(sender As Object,
                              e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
     Protected Sub NotifyPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)
         RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
     End Sub End 
Class

OAuth2.0によるサインイン実行

image

 

設定チャームの[アカウント]から直接OAuth2.0認証を呼び出しているのでサインインダイアログが表示されます。

image

 

[Sign In]ボタンをクリックすると権限確認ダイアログが自動表示されます。

image

以降はこの時に取得できたアクセストークンを使ってREST APIで情報を取得できます。

REST APIによるイベント一覧の取得

LiveSDKではなくREST APIでイベント(hotmailのカレンダー情報)を取得してみましょう。

    Private Const CalendarsUrl As String = https://apis.live.net/v5.0/me/events?access_token={0}×tamp={1}


 
    <DataContract()>
     Private Class TEventResults
         <DataMember(name:="data")>
         Public Property data As List(Of TData)
     End Class
     <DataContract()>
     Private Class TData
         <DataMember(name:="id")>
         Public Property id As String
         <DataMember(name:="name")>
         Public Property name As String
         <DataMember(name:="description")>
         Public Property description As String
         <DataMember(name:="start_time")>
         Public Property start_time As String
         <DataMember(name:="end_time")>
         Public Property end_time As String
         <DataMember(name:="location")>
         Public Property location As String
         <DataMember(name:="is_all_day_event")>
         Public Property is_all_day_event As Boolean
     End Class



     Public Async Function GetDataAsync() As Task
         Dim urlString As String = String.Format(CalendarsUrl,
                                                 Settings.AccessToken,
                                                 Date.Now.ToString("yyyyMMddHHmmss"))
         Try
             Dim client As New HttpClient
             Using response As HttpResponseMessage = Await client.GetAsync(urlString)
                 Dim responseDataStream As Stream = Await response.Content.ReadAsStreamAsync
                 Using stream As New MemoryStream()
                     responseDataStream.CopyTo(stream, responseDataStream.Length)
                     stream.Position = 0
                     Dim serializer As New System.Runtime.Serialization.Json.DataContractJsonSerializer(GetType(TEventResults))
                     Dim jsonDataValue As TEventResults = CType(serializer.ReadObject(stream), TEventResults)
                     Dim items As IEnumerable(Of TLiveEventItem) = _
                                From liveEvent In jsonDataValue.data
                                Where Not liveEvent.is_all_day_event
                                Select New TLiveEventItem With {
                                             .id = liveEvent.id,
                                             .name = liveEvent.name,
                                             .description = liveEvent.description,
                                             .start_date = liveEvent.start_time.Substring(0, 7),
                                             .start_time = liveEvent.start_time,
                                             .end_time = liveEvent.end_time,
                                             .location = liveEvent.location,
                                             .is_all_day_event = liveEvent.is_all_day_event
                                    }
                     Dim categories = _
                         From liveEvent In items
                         Where Not liveEvent.is_all_day_event
                         Group liveEvent By liveEvent.start_date Into eventCount = Count()
                         Select start_date
                     For Each category In categories
                         Dim group As New EventModelGroup(category,
                                                          category,
                                                          "",
                                                          "",
                                                          "")
                         Dim eventItems = From liveEvent In items
                                          Where liveEvent.start_date = category
                         For Each item In eventItems
                             group.Items.Add(New EventModelItem(item.id,
                                                                item.name,
                                                                "",
                                                                "",
                                                                item.description,
                                                                "",
                                                                item.start_date,
                                                                item.start_time,
                                                                item.end_time,
                                                                item.location,
                                                                item.is_all_day_event,
                                                                group))
                         Next
                         Me._AllGroups.Add(group)
                     Next
                 End Using
             End Using
         Catch ex As Exception
             Throw New Exception("Error posting data to Foursquare:" & ex.Message)
         Finally
             RaiseEvent Completed(Me._allGroups)
         End Try
     End Function
     Public Event Completed(ByVal group As ObservableCollection(Of EventModelGroup))

REST APIによるイベント一覧取得の実行結果
REST APIでの実行結果も当たり前ですがLive SDKのときと同じになります。