2011-12-27
Windows Live SkyDrive でエクスプローラっぽい操作を行う方法 -画像操作編-

前回はSkyDrive上のテキストファイルを作成/更新/削除する操作処理を行いました。今回はSkyDrive上の画像ファイルを作成/更新/削除します。
実装
エクスプローラっぽい操作で、画像ファイルを新規作成したり画像、ファイルを選択して内容更新や削除を行います。具体的には以下のような操作になります。
- ディレクトリ表示時にApplicationBarIconButtonの"New"ボタンを押下して、PictureHubから画像選択したものを新規アップロード。
- 画像ファイル選択時にタイトルと画像をダイアログに表示させて、画像をタッチする事で画像変更して更新もしくは画像の削除を行います。
事前準備
前回の"Windows Live SkyDrive でエクスプローラっぽい操作を行う方法 -テキストファイル操作編-"の続きになりますので、こちらの実装は済ませておいてください。
利用権限の付与
SkyDriveのファイル/フォルダ情報を取得する事になります。SingInButtonに対して以下の権限付与を行なってください。
- wl.photos(画像を表示する権限)
- wl.skydrive_update(画像ファイル操作を行う権限)
前回と同じく、以下の一行をSingInButtonコントロールのScopesプロパティに設定すればOKです。
wl.basic wl.signin wl.signin wl.skydrive wl.photos wl.skydrive_update
画面レイアウト(MainPage.xaml)
画像を表示するダイアログの中身だけ、テキスト編集ではなく画像表示するよう変更しています。
<phone:PhoneApplicationPage …省略… > …省略… <Grid x:Name="dialog" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.RowSpan="3" Width="380" Height="350" Background="{StaticResource PhoneAccentBrush}" Visibility="Collapsed"> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.334*"/> <ColumnDefinition Width="0.333*"/> <ColumnDefinition Width="0.333*"/> </Grid.ColumnDefinitions> <i:Interaction.Behaviors> <ec:DataStateBehavior Binding="{Binding DialogTitle}" TrueState="VisualState0" FalseState="VisualState1"/> </i:Interaction.Behaviors> <Grid.RowDefinitions> <RowDefinition Height="0.18*"/> <RowDefinition Height="0.593*"/> <RowDefinition Height="0.227*"/> </Grid.RowDefinitions> <TextBox x:Name="txtDialogTitle" Margin="0,0,5,0" TextWrapping="Wrap" d:LayoutOverrides="Height" HorizontalAlignment="Center" Grid.ColumnSpan="3" BorderThickness="0" Width="300" Text="{Binding DialogTitle, Mode=TwoWay}"/> <Image x:Name="imgDialogDetail" Grid.Row="1" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" Source="{Binding DialogDetail}" Tap="imgDialogDetail_Tap" Width="250" Height="200" /> <Button x:Name="btnDialogDel" Content="削除" d:LayoutOverrides="Width, Height" Grid.Row="2" Click="btnDialogDel_Click" /> <Button x:Name="btnDialogClose" Content="閉じる" Grid.Row="2" Click="btnDialogClose_Click" Grid.Column="2" FontSize="25.333" /> <Button x:Name="btnDialogSave" Content="保存" Grid.Column="1" Grid.Row="2" d:LayoutOverrides="Width, Height" Click="btnDialogSave_Click" /> </Grid> …省略… </phone:PhoneApplicationPage>
メイン処理(MainPage.xaml.cs)
ほぼ前回と同じです。ダイアログを表示させる時にPictureHubを起動して画像選択させる箇所だけ違います。
…省略… namespace PhoneApp1 { public partial class MainPage : PhoneApplicationPage { private Stream stream; …省略… // ダイアログの保存ボタンが押下された時のイベント private void btnDialogSave_Click(object sender, System.Windows.RoutedEventArgs e) { // ファイル名に拡張子を付けないとアップロード時にエラーになるので、".jpg"と追加しておきます // 新規作成時は良いですが、更新時に拡張子が新たに追加されるので、そこは適当に処理してください model.saveDialog(txtDialogTitle.Text + ".jpg", stream); } …省略… // Newボタンが押下された時のイベント // 画像ファイルの新規作成ダイアログを開きます、と同時にPictureHubを起動して画像を選択してもらいます private void appBarIconBtnNew_Click(object sender, System.EventArgs e) { model.createFile(); getPicture(); } // ダイアログ上の画像をタップした時のイベント private void imgDialogDetail_Tap(object sender, System.Windows.Input.GestureEventArgs e) { getPicture(); } // PictureHubを起動して画像を選択します private void getPicture() { PhotoChooserTask photoChooserTask = new PhotoChooserTask(); photoChooserTask.Completed += new System.EventHandler<PhotoResult>(photoChooserTask_Completed); try { photoChooserTask.PixelHeight = 200; photoChooserTask.PixelWidth = 250; photoChooserTask.Show(); } catch { } } // PictureHubから画像取得した時のイベント // 取得した画像をダイアログ上に設定します void photoChooserTask_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { stream = e.ChosenPhoto; } } } }
データバインド用のビューモデル作成(FileViewModel.cs)
エクスプローラ上で画像ファイルが選択された事をハンドリングして、画像情報を取得する処理になります。
対象情報の取得方法が異なるだけで、データのアップロードや削除は全く同じ方法で行えます。
…省略… namespace PhoneApp1 { public class FileViewModel : INotifyPropertyChanged { // アイテムが選択された時のイベント public void selectItem(int index) { // 選択されたアイテムがフォルダの場合はディレクトリ移動します if ("folder".Equals(items[index].Type)) { // 選択されたディレクトリのIDと名前を履歴に保存しておきます …省略… } else if ("photo".Equals(items[index].Type)) { // 選択された画像をダウンロードしてダイアログに表示します getFileDetail(index); } } // 画像情報を取得します private void getFileDetail(int index) { currentIndex = index; // 後のファイル操作で使用します LiveConnectClient photoClient = new LiveConnectClient(session); photoClient.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(photoClient_GetCompleted); photoClient.GetAsync(items[index].Id); } // 画像情報の取得処理が完了した時のイベント // 画像をダイアログ上に表示させます void photoClient_GetCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null && e.Result.ContainsKey("source")) { if (e.Result["source"] != null) { DialogDetail = e.Result["source"].ToString(); DialogTitle = items[currentIndex].Name; } } } } }
画面キャプチャ
エクスプローラから"Photo"を選択する事で編集ダイアログが表示されます。
まとめ
テキストファイルも画像ファイルも大体同じ処理でOKですので、そこまで難しくはなかったかと思います。
参考
REST API -MSDN
技術部 かわかみひろき
2011-12-26
Windows Live SkyDrive でエクスプローラっぽい操作を行う方法 -テキストファイル操作編-

前回はSkyDriveをエクスプローラっぽい操作でフォルダ移動する所までやりました。今回はSkyDrive上のテキストファイルを作成/更新/削除します。
実装
エクスプローラっぽい操作で、ファイルを新規作成したり、ファイルを選択して内容更新やファイル削除を行います。具体的には以下のような操作になります。
- ディレクトリ表示時にApplicationBarIconButtonの"New"ボタンを押下して、新規ファイル作成。
- ファイル選択時にファイルタイトルとファイル内容をダイアログに表示させて、内容を編集して更新もしくはファイル削除。
事前準備
前回の"Windows Live SkyDrive でエクスプローラっぽい操作を行う方法 -フォルダ移動編-"の続きになりますので、こちらの実装は済ませておいてください。
利用権限の付与
SkyDriveのファイル/フォルダ情報を取得する事になります。SingInButtonに対して以下の権限付与を行なってください。
- wl.skydrive_update(ファイル操作を行う権限)
前回のと合わせると、以下の一行をSingInButtonコントロールのScopesプロパティに設定すればOKです。
wl.basic wl.signin wl.signin wl.skydrive wl.photos wl.skydrive_update
画面レイアウト(MainPage.xaml)
前回と比べて、ファイル内容を表示するダイアログと、ApplicationBarIconButtonに"New"ボタンが追加しました。
以下のコードは、前回と被っている部分を省略しています。
<phone:PhoneApplicationPage …省略… > …省略… <phone:PhoneApplicationPage.FontFamily> <StaticResource ResourceKey="PhoneFontFamilyNormal"/> </phone:PhoneApplicationPage.FontFamily> <phone:PhoneApplicationPage.FontSize> <StaticResource ResourceKey="PhoneFontSizeNormal"/> </phone:PhoneApplicationPage.FontSize> <phone:PhoneApplicationPage.Foreground> <StaticResource ResourceKey="PhoneForegroundBrush"/> </phone:PhoneApplicationPage.Foreground> <Grid Height="Auto" Width="Auto" d:DataContext="{d:DesignData /SampleData/FileViewModelSampleData.xaml}"> …省略… <Grid x:Name="dialog" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.RowSpan="3" Width="380" Height="350" Background="{StaticResource PhoneAccentBrush}" Visibility="Collapsed"> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.334*"/> <ColumnDefinition Width="0.333*"/> <ColumnDefinition Width="0.333*"/> </Grid.ColumnDefinitions> <i:Interaction.Behaviors> <ec:DataStateBehavior Binding="{Binding DialogTitle}" TrueState="VisualState0" FalseState="VisualState1"/> </i:Interaction.Behaviors> <Grid.RowDefinitions> <RowDefinition Height="0.18*"/> <RowDefinition Height="0.593*"/> <RowDefinition Height="0.227*"/> </Grid.RowDefinitions> <TextBox x:Name="txtDialogTitle" Margin="0,0,5,0" TextWrapping="Wrap" d:LayoutOverrides="Height" HorizontalAlignment="Center" Grid.ColumnSpan="3" BorderThickness="0" Width="300" Text="{Binding DialogTitle, Mode=TwoWay}"/> <TextBox x:Name="txtDialogDetail" TextWrapping="Wrap" d:LayoutOverrides="Height" Grid.Row="1" Grid.ColumnSpan="3" Text="{Binding DialogDetail, Mode=TwoWay}"/> <Button x:Name="btnDialogDel" Content="削除" d:LayoutOverrides="Width, Height" Grid.Row="2" Click="btnDialogDel_Click" /> <Button x:Name="btnDialogSave" Content="保存" Grid.Column="1" Grid.Row="2" d:LayoutOverrides="Width, Height" Click="btnDialogSave_Click" /> <Button x:Name="btnDialogClose" Content="閉じる" Grid.Row="2" Click="btnDialogClose_Click" Grid.Column="2" FontSize="25.333" /> </Grid> </Grid> <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/icons/appbar.new.rest.png" Text="New" x:Name="appBarIconBtnNew" Click="appBarIconBtnNew_Click" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar> </phone:PhoneApplicationPage>
メイン処理(MainPage.xaml.cs)
今回追加したApplicationBarIconButtonとダイアログのボタンをクリックした時のイベントを追加しています。メインの処理は後述するFileViewModel.csで行なっています。
以下のコードは、前回と被っている部分を省略しています。
…省略… namespace PhoneApp1 { public partial class MainPage : PhoneApplicationPage { // ダイアログの削除ボタンが押下された時のイベント // SkyDrive上から現在開いているファイルを削除してダイアログを閉じます private void btnDialogDel_Click(object sender, System.Windows.RoutedEventArgs e) { model.deleteDialog(); } // ダイアログの保存ボタンが押下された時のイベント // 現在開いているテキストをSkyDrive上に保存してダイアログを閉じます private void btnDialogSave_Click(object sender, System.Windows.RoutedEventArgs e) { // ファイル名に拡張子を付けないとアップロード時にエラーになるので、".txt"と追加しておきます model.saveDialog(txtDialogTitle.Text + ".txt", txtDialogDetail.Text); } // ダイアログの閉じるボタンが押下された時のイベント // ダイアログを閉じます private void btnDialogClose_Click(object sender, System.Windows.RoutedEventArgs e) { model.closeDialog(); } // Newボタンが押下された時のイベント // ファイルの新規作成ダイアログを開きます private void appBarIconBtnNew_Click(object sender, System.EventArgs e) { model.createFile(); } } }
データバインド用のListBoxアイテム作成(FileItemViewModel.cs)
テキストファイルの新規作成/更新/削除を行なっています。
前回はエクスプローラ上でフォルダを選択するとディレクトリ移動して、それ以外を選択しても何も処理させませんでしたが、今回は "folder" が選択された時にテキストファイルの中身を読み込む処理を行っています。
以下のコードは、前回と被っている部分を省略しています。
…省略… namespace PhoneApp1 { public class FileViewModel : INotifyPropertyChanged { private int currentIndex; // アイテムが選択された時のイベント public void selectItem(int index) { // 選択されたアイテムがフォルダの場合はディレクトリ移動します if ("folder".Equals(items[index].Type)) { // 選択されたディレクトリのIDと名前を履歴に保存しておきます …省略… } else if ("file".Equals(items[index].Type)) { // 選択されたファイルの中身をダイアログに表示します getFileDetail(index); } } …省略… // ファイル中身を取得します private void getFileDetail(int index) { currentIndex = index; // 後のファイル操作で使用します // テキストファイルの中身をダウンロードします WebClient wc = new WebClient(); wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted); wc.DownloadStringAsync(new Uri(items[index].Source)); } // ファイル中身のテキストがダウンロードされた時のイベント void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { if (e.Error == null) { DialogDetail = e.Result.ToString(); DialogTitle = items[currentIndex].Name; } } // 開いているファイルを削除してダイアログを閉じます public void deleteDialog() { LiveConnectClient fileDeleteClient = new LiveConnectClient(session); fileDeleteClient.DeleteCompleted += new EventHandler<LiveOperationCompletedEventArgs>(fileDeleteClient_DeleteCompleted); fileDeleteClient.DeleteAsync(items[currentIndex].Id); clearDialogInfo(); } // テキストファイルの削除処理が完了した時のイベント void fileDeleteClient_DeleteCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("テキストファイルの削除に失敗しました"); } } // 開いているファイルを保存してダイアログを閉じます public void saveDialog(string title, string detail) { // アップロード対象はStream型にしておきます var stream = new MemoryStream(Encoding.GetEncoding("UTF-8").GetBytes(detail)); // アップロードを行います。UploadAsyncの第一引数のPashは、保存ディレクトリのIDを設定する事に気をつけてください。 LiveConnectClient fileUpdateClient = new LiveConnectClient(session); fileUpdateClient.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(filesClient_UploadCompleted); fileUpdateClient.UploadAsync("/" + histryDirectoryId[histryDirectoryId.Count - 1], title, true, stream, null); clearDialogInfo(); } // ダイアログを閉じます public void closeDialog() { clearDialogInfo(); } // テキストファイルのアップロード処理が完了した時のイベント void filesClient_UploadCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("テキストファイルの更新に失敗しました"); } } // ダイアログ表示内容をクリア // Titleがクリアされる事によって、DataStateBehaviorがダイアログを非表示にします private void clearDialogInfo() { DialogTitle = null; DialogDetail = null; } // ダイアログを空の状態で表示します // データに空が設定される事でダイアログがビヘイビアによって表示されます public void createFile() { DialogDetail ""; DialogTitle = ""; } …省略… } }
テキストファイルの作成や読み込みではエンコードに注意してください。また、テキストファイルを作成する際に拡張子を付け忘れるとエラーになるので注意してください。
画面キャプチャ
テキストファイルの新規作成画面が左画像、テキストファイルの編集画面が右画像になります。
利用API
LiveConnectClient
| メソッド名 | 意味 |
|---|---|
| UploadAsync | ファイルのアップロードを行います 第一引数はアップロード先のフォルダIDか、パスを設定します 第二引数はファイル名 第三引数は上書きするかの設定 第四引数はよく分からないですがnullで問題なさそうです |
| DeleteAsync | ファイルの削除を行います 第一引数はファイルIDを設定します |
| イベント名 | 意味 |
| UploadCompleted | ファイルのアップロード処理が完了したら呼ばれるイベントです |
| DeleteCompleted | ファイルの削除処理が完了したら呼ばれるイベントです |
参考
REST API -MSDN
技術部 かわかみひろき
2011-12-22
Windows Live SkyDrive でエクスプローラっぽい操作を行う方法 -フォルダ移動編-

Windows Liveサービスの一つである Windows Live SkyDrive を、アプリ内にてエクスプローラ感覚で操作するための解説を行います。
Windows Live SkyDriveから取得する情報
今回は以下のファイルとフォルダの情報を取得して来ます。
- 名前
- 種類
Windows Live SkyDriveにデータが無いと大したこと出来ませんので、認証するWindows Live IDのSkyDriveに何かフォルダやファイルを置いてください。
https://skydrive.live.com/
実装
ListBox上にファイル/フォルダを表示させて、フォルダを選択した時は対象フォルダ階層をListBoxへ表示させます。カレントディレクトリは画面上部に表示します。
戻るボタンが押下された時は、前回表示していたフォルダ階層をListBox上に表示させます。
処理手順は以下の通りです。
- Windows Live認証を行う
- Windows Live SkyDriveからファイル情報を取得する
- 取得したデータの解析を行なって、画面上のコントロールにバインドする
- 一覧に表示されたフォルダが選択されたら、対象のフォルダ情報を取得する
- 3に戻る
事前準備
"Windows Liveの導入から認証までの方法" エントリーを読んで、SingInButtonコントロールの配置を行なってください。
利用権限の付与
SkyDriveのファイル/フォルダ情報を取得する事になります。SingInButtonに対して以下の権限付与を行なってください。
- wl.skydrive
- wl.photos
基本権限も合わせると、以下の一行をSingInButtonコントロールのScopesプロパティに設定すればOKです。
wl.basic wl.signin wl.signin wl.skydrive wl.photos
画面レイアウト(MainPage.xaml)
一応XAMLの中身を貼っていますが真似しなくても問題ありません。
後述するFileViewModel.csとデータバインドを行なっているため、そこだけ注意してください。Blendのデータから[クラスからのサンプルデータ作成]で、ProfileModel.csを対象に作成してコントロールにバインドすれば出来ます。よく分からない人は過去エントリーを参照ください。
<phone:PhoneApplicationPage …省略… xmlns:my="clr-namespace:Microsoft.Live.Controls;assembly=Microsoft.Live.Controls" > <phone:PhoneApplicationPage.Resources> <DataTemplate x:Key="FileItemViewModelTemplate"> <Grid Width="480"> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.22*"/> <ColumnDefinition Width="0.78*"/> </Grid.ColumnDefinitions> <TextBlock Text="{Binding Type}" Margin="0" FontSize="32" VerticalAlignment="Center"/> <TextBlock Text="{Binding Name}" FontSize="42.667" TextWrapping="Wrap" Grid.Column="1" VerticalAlignment="Center"/> </Grid> </DataTemplate> </phone:PhoneApplicationPage.Resources> <Grid Height="Auto" Width="Auto" d:DataContext="{d:DesignData /SampleData/FileViewModelSampleData.xaml}"> <Grid.RowDefinitions> <RowDefinition Height="0.094*"/> <RowDefinition Height="0.794*"/> <RowDefinition Height="0.112*"/> </Grid.RowDefinitions> <TextBlock TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="48" Foreground="{StaticResource PhoneAccentBrush}" Text="{Binding CurrentDirectory}" /> <ListBox ItemTemplate="{StaticResource FileItemViewModelTemplate}" ItemsSource="{Binding items}" x:Name="list" SelectionChanged="list_SelectionChanged" Grid.Row="1" /> <my:SignInButton Content="Button" Height="Auto" x:Name="signInButton" Width="Auto" Branding="Skydrive" ClientId="_ClientIdを設定してください_" RedirectUri="https://oauth.live.com/desktop" Scopes="wl.basic wl.signin wl.signin wl.skydrive wl.photos" SessionChanged="signInButton1_SessionChanged" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="7" Grid.ColumnSpan="2" Grid.Column="0" /> </Grid> </phone:PhoneApplicationPage>
メイン処理(MainPage.xaml.cs)
メインと言っても、ほとんどの処理はデータバインドを行う後述するFileViewModel.csで行います。
画面操作とビューモデルとの間のやり取りを行うクラスになっています。
using Microsoft.Phone.Controls; namespace PhoneApp1 { public partial class MainPage : PhoneApplicationPage { FileViewModel model; // コンストラクター public MainPage() { InitializeComponent(); // BindingデータをDataContextに設定 model = new FileViewModel(); DataContext = model; } // セッションの状態が変わった時のイベント private void signInButton1_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e) { if (e.Session != null) { model.LoadData(e.Session); } } // リストが選択された時のイベント private void list_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { var index = list.SelectedIndex; if (index != -1) { model.selectItem(list.SelectedIndex); } } // 戻るボタンが押下された時のイベント protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e) { // 前に表示していたファイルディレクトリに戻ります // 戻り先がない場合はアプリを終了させます e.Cancel = model.backItem(); } } }
データバインド用のビューモデル作成(FileViewModel.cs)
ファイル/フォルダ情報を取得して、画面上のコントロールにバインドさせます。ListBox内のアイテムは後述するFileItemViewModel.csクラス内の変数とバインドさせています。
フォルダ移動履歴を管理しており、戻るボタンが押下された時に過去表示していたフォルダが表示されるようになっています。
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using Microsoft.Live; namespace PhoneApp1 { public class FileViewModel : INotifyPropertyChanged { private LiveConnectSession session; public ObservableCollection<FileItemViewModel> items { get; private set; } // ファイルディレクトリの履歴管理情報 private List<string> histryDirectoryId; private List<string> histryDirectoryName; public FileViewModel() { items = new ObservableCollection<FileItemViewModel>(); histryDirectoryId = new List<string>(); histryDirectoryId.Add(""); histryDirectoryName = new List<string>(); histryDirectoryName.Add("Root Directory"); } // カレント ディレクトリ名 private string _currentDirectory; public string CurrentDirectory { get { return _currentDirectory; } set { if (value != _currentDirectory) { _currentDirectory = value; NotifyPropertyChanged("CurrentDirectory"); } } } // Windows Live SkyDrive からFilesのRootディレクトリ情報を取得します public void LoadData(LiveConnectSession session) { this.session = session; getRootDirectory(); } void filesClient_GetCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { // 既にアイテムが存在すればクリアします if (items.Count > 0) { items.Clear(); } // 保存されているカレント ディレクトリ名を画面上部へ表示します CurrentDirectory = histryDirectoryName[histryDirectoryName.Count - 1]; // フォルダ情報のデータ解析を行います List<object> data = (List<object>)e.Result["data"]; foreach (IDictionary<string, object> files in data) { var item = new FileItemViewModel(); // ID if (files.ContainsKey("id") && files["id"] != null) { item.Id = files["id"].ToString(); } // ファイル名 if (files.ContainsKey("name") && files["name"] != null) { item.Name = files["name"].ToString(); } // ファイルURL if (files.ContainsKey("link") && files["link"] != null) { item.Url = files["link"].ToString(); } // ファイル タイプ if (files.ContainsKey("type") && files["type"] != null) { item.Type = files["type"].ToString(); } // コレクションにitemを追加します items.Add(item); } } } // アイテムが選択された時のイベント public void selectItem(int index) { // 選択されたアイテムがフォルダの場合はディレクトリ移動します if ("folder".Equals(items[index].Type)) { // 選択されたディレクトリのIDと名前を履歴に保存しておきます histryDirectoryId.Add(items[index].Id); histryDirectoryName.Add(items[index].Name); getCurrentDirectory(); } } // 戻るボタンが押下された時のイベント // 戻り先がない場合はfalse、戻り先がある場合はtrue public bool backItem() { // 履歴が存在するかチェックします var count = histryDirectoryId.Count; if (count > 1) { // カレントディレクトリ情報を履歴から削除します count--; histryDirectoryId.RemoveAt(count); histryDirectoryName.RemoveAt(count); // 履歴が1件しか無ければルートディレクトリを表示します if (count <= 1) { getRootDirectory(); } else { getCurrentDirectory(); } return true; } else { return false; } } // ルートディレクトリを取得します private void getRootDirectory() { LiveConnectClient filesClient = new LiveConnectClient(session); filesClient.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(filesClient_GetCompleted); filesClient.GetAsync("/me/skydrive/files"); } // カレントディレクトリを取得します private void getCurrentDirectory() { LiveConnectClient filesClient = new LiveConnectClient(session); filesClient.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(filesClient_GetCompleted); filesClient.GetAsync("/" + histryDirectoryId[histryDirectoryId.Count - 1] + "/files"); } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } }
データバインド用のListBoxアイテム作成(FileItemViewModel.cs)
バインドするLitView内のアイテムになります。
using System; using System.ComponentModel; namespace PhoneApp1 { public class FileItemViewModel : INotifyPropertyChanged { // ファイルID private string _id; public string Id { get { return _id; } set { if (value != _id) { _id = value; NotifyPropertyChanged("Id"); } } } // ファイル名 private string _name; public string Name { get { return _name; } set { if (value != _name) { _name = value; NotifyPropertyChanged("Name"); } } } // ファイルURL private string _url; public string Url { get { return _url; } set { if (value != _url) { _url = value; NotifyPropertyChanged("Url"); } } } // ファイルのタイプ private string _type; public string Type { get { return _type; } set { if (value != _type) { _type = value; NotifyPropertyChanged("Type"); } } } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } }
SkyDriveのルートディレクトリのファイル/フォルダ情報は /me/skydrive/files 情報アクセスパスで取得、指定ディレクトリ内のファイル/フォルダ情報は /ファイルID/files 情報アクセスパスで取得出来ます。
画面キャプチャ
左画像の状態からリスト選択すると右画像のように表示が切り替わればOKです。
まとめ
今回はエクスプローラっぽい操作が行える、ファイル移動が出来るだけのアプリ作成でした。次回はファイルの中身を表示させる方法について解説します。
参考
REST API -MSDN
技術部 かわかみひろき
2011-12-21
Windows Live プロフィール から個人情報を取得する方法
今までは Windows Live サービスの説明や、どういったデータが扱えるかの話でした。
今回はWindows Liveサービスの一つである Windows Live プロフィール から個人情報を取得する方法を解説します。
Windows Live プロフィールから取得する情報
今回は以下のデータを取得して来ます。
- 氏名
- プロフィール画像
- 個人のメールアドレス
- 会社名
- 会社の電話番号
- 会社の住所
Windows Live プロフィールにデータが無いと取得して来れませんので、認証するWindows Live IDのプロフィール情報を確認しておいてください。
https://profile.live.com/
実装
処理手順は以下の通りです。
- Windows Live認証を行う
- Windows Live プロフィールからデータ取得を行う
- 取得したデータの解析を行なって、画面上のコントロールにバインドする
事前準備
"Windows Liveの導入から認証までの方法" エントリーを読んで、SingInButtonコントロールの配置を行なってください。
利用権限の付与
今回は扱うデータは User データになります。
その中でも今回は 電話番号/メールアドレス/仕事/住所 の取得を行うため、SingInButtonに対して以下の権限付与が必要になります。
- wl.phone_numbers(電話番号)
- wl.emails(メールアドレス)
- wl.work_profile(仕事)
- wl.postal_addresses(住所)
基本権限も合わせると、以下の一行をSingInButtonコントロールのScopesプロパティに設定すればOKです。
wl.basic wl.signin wl.signin wl.postal_addresses wl.emails wl.work_profile wl.phone_numbers
データバインド用のモデル作成(ProfileModel.cs)
名前/アイコン/メールアドレス/会社名/電話番号/住所 の画面にデータバインドを行うデータ群です。
namespace PhoneApp1 { public class ProfileModel : INotifyPropertyChanged { // 名前 private string _name; public string Name { get { return _name; } set { if (value != _name) { _name = value; NotifyPropertyChanged("Name"); } } } // アイコン private string _icon; public string Icon { get { return _icon; } set { if (value != _icon) { _icon = value; NotifyPropertyChanged("Icon"); } } } // メールアドレス private string _email; public string Email { get { return _email; } set { if (value != _email) { _email = value; NotifyPropertyChanged("Email"); } } } // 会社名 private string _work; public string Work { get { return _work; } set { if (value != _work) { _work = value; NotifyPropertyChanged("Work"); } } } // 電話番号 private string _phone; public string Phone { get { return _phone; } set { if (value != _phone) { _phone = value; NotifyPropertyChanged("Phone"); } } } // 住所 private string _addresse; public string Addresse { get { return _addresse; } set { if (value != _addresse) { _addresse = value; NotifyPropertyChanged("Addresse"); } } } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } }
画面レイアウト(MainPage.xaml)
一応XAMLの中身を貼っていますが真似しなくても問題ありません。
ProfileModel.csとデータバインドを行なっているため、そこだけ注意してください。Blendのデータから[クラスからのサンプルデータ作成]で、ProfileModel.csを対象に作成してコントロールにバインドすれば出来ます。よく分からない人は過去エントリーを参照ください。
<phone:PhoneApplicationPage …省略… xmlns:my="clr-namespace:Microsoft.Live.Controls;assembly=Microsoft.Live.Controls" > <Grid Height="Auto" Width="Auto" d:DataContext="{d:DesignData /SampleData/ProfileItemSampleData.xaml}"> <Grid.RowDefinitions> <RowDefinition Height="0.25*"/> <RowDefinition Height="0.1*"/> <RowDefinition Height="0.1*"/> <RowDefinition Height="0.1*"/> <RowDefinition Height="0.1*"/> <RowDefinition Height="0.1*"/> <RowDefinition Height="0.1*"/> <RowDefinition Height="0.15*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.3*"/> <ColumnDefinition Width="0.7*"/> </Grid.ColumnDefinitions> <my:SignInButton Content="Button" Height="Auto" x:Name="signInButton" Width="Auto" Branding="Skydrive" ClientId="_ClientIdを設定してください_" RedirectUri="https://oauth.live.com/desktop" Scopes="wl.basic wl.signin wl.signin wl.postal_addresses wl.emails wl.work_profile wl.phone_numbers" SessionChanged="signInButton1_SessionChanged" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center" Grid.Row="7" Grid.ColumnSpan="2" Grid.Column="0" /> <Image Margin="0" Grid.ColumnSpan="2" Width="150" Height="150" Name="imgProfile" Source="{Binding Icon}" /> <TextBlock Margin="0,0,10,0" Grid.Row="1" TextWrapping="Wrap" Text="氏名" FontSize="32" TextAlignment="Right" VerticalAlignment="Center"/> <TextBlock Grid.Column="1" Margin="0" Grid.Row="1" TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Center" d:LayoutOverrides="Width" FontSize="32" Foreground="{StaticResource PhoneAccentBrush}" Name="txtName" HorizontalAlignment="Center" /> <TextBlock Margin="0,0,10,0" Grid.Row="2" TextWrapping="Wrap" Text="メール" FontSize="32" TextAlignment="Right" d:LayoutOverrides="Height" VerticalAlignment="Center"/> <TextBlock Margin="0,18,10,20" Grid.Row="4" TextWrapping="Wrap" Text="電話番号" FontSize="32" TextAlignment="Right" d:LayoutOverrides="Height"/> <TextBlock Margin="0,32,10,29" Grid.Row="5" TextWrapping="Wrap" FontSize="32" TextAlignment="Right" d:LayoutOverrides="Height" Text="住所" VerticalAlignment="Center" Grid.RowSpan="2"/> <TextBlock Margin="0,20,10,19" Grid.Row="3" TextWrapping="Wrap" Text="会社名" FontSize="32" TextAlignment="Right" d:LayoutOverrides="Height"/> <TextBlock Text="{Binding Work}" Margin="0" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Grid.Row="3" Foreground="{StaticResource PhoneAccentBrush}" FontSize="24"/> <TextBlock Text="{Binding Phone}" Margin="0" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Grid.Row="4" Foreground="{StaticResource PhoneAccentBrush}" FontSize="32"/> <TextBlock Text="{Binding Email}" Margin="0" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Grid.Row="2" Foreground="{StaticResource PhoneAccentBrush}" FontSize="32"/> <TextBlock Text="{Binding Addresse}" Margin="10" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Grid.Row="5" TextWrapping="Wrap" FontSize="26.667" Grid.RowSpan="2" Foreground="{StaticResource PhoneAccentBrush}"/> </Grid> </phone:PhoneApplicationPage>
メイン処理(MainPage.xaml.cs)
コードは長いですが、色々情報を取得しているからなだけで行なっている事は単純です。
Windows Live認証が終わった後にsignInButton1_SessionChangedイベントが呼ばれるので、そこでWindows Live プロフィールからデータ取得します。取得されるデータはJson形式になっていますので、REST APIを参考にひたすらデータ解析を行うだけです。
using System; using System.Collections.Generic; using System.Diagnostics; using Microsoft.Live; using Microsoft.Phone.Controls; namespace PhoneApp1 { public partial class MainPage : PhoneApplicationPage { LiveConnectSession session; ProfileModel item; // コンストラクター public MainPage() { InitializeComponent(); // BindingデータをDataContextに設定 item = new ProfileModel(); DataContext = item; } // セッションの状態が変わった時のイベント // 取得したセッションを使って Windows Live プロフィール から情報を取得するようにします private void signInButton1_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e) { if (e.Session != null) { // アプリ全体で扱う場合はApp.xaml.csで変数持たせた方がいいです session = e.Session; // Windows Live プロフィールから情報取得 getWindowsLiveProfileInfo(); } } // Windows Live プロフィール から情報を取得します private void getWindowsLiveProfileInfo() { LiveConnectClient meClient = new LiveConnectClient(session); meClient.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(meClient_GetCompleted); meClient.GetAsync("/me/"); // Windows Live プロフィールから情報を取得するためのパスです } // Windows Live プロフィール から情報を取得した時のイベント // 取得情報を解析します void meClient_GetCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { // 名前の取得("name"でフルネームを取得出来るが、名性 順なので個々に取得します) var name = ""; if (e.Result.ContainsKey("last_name") && e.Result["last_name"] != null) { name = e.Result["last_name"].ToString() + " "; } if (e.Result.ContainsKey("first_name") && e.Result["first_name"] != null) { name += e.Result["first_name"].ToString(); } item.Name = name; // メールアドレスの取得 if (e.Result.ContainsKey("emails") && e.Result["emails"] != null) { var emails = (IDictionary<string, object>)e.Result["emails"]; if (emails.ContainsKey("personal") && emails["personal"] != null) { item.Email = emails["personal"].ToString(); } } // 会社名の取得 if (e.Result.ContainsKey("work") && e.Result["work"] != null) { // 会社情報の中から会社名のみ取得 var works = (List<object>)e.Result["work"]; if (works.Count > 0) { var work = (IDictionary<string, object>)works[0]; // workだけ他と異なりarrayなのに注意してください if (work.ContainsKey("employer") && work["employer"] != null) { var employer = (IDictionary<string, object>)work["employer"]; if (employer.ContainsKey("name") && employer["name"] != null) { item.Work = employer["name"].ToString(); } } } } // 電話番号の取得 if (e.Result.ContainsKey("phones") && e.Result["phones"] != null) { // 携帯の電話番号のみ取得 var phones = (IDictionary<string, object>)e.Result["phones"]; if (phones.ContainsKey("business") && phones["business"] != null) { item.Phone = phones["business"].ToString(); } } // 住所の取得 if (e.Result.ContainsKey("addresses") && e.Result["addresses"] != null) { // パーソナルの住所のみ取得 var addresses = (IDictionary<string, object>)e.Result["addresses"]; if (addresses.ContainsKey("business") && addresses["business"] != null) { var business = (IDictionary<string, object>)addresses["business"]; var address = ""; if (business.ContainsKey("postal_code") && business["postal_code"] != null) { address += "〒" + business["postal_code"].ToString() + "\n"; } if (business.ContainsKey("region") && business["region"] != null) { address += business["region"].ToString() + " "; } if (business.ContainsKey("state") && business["state"] != null) { address += business["state"].ToString() + " "; } if (business.ContainsKey("city") && business["city"] != null) { address += business["city"].ToString() + " "; } if (business.ContainsKey("street_2") && business["street_2"] != null) { address += business["street_2"].ToString() + " "; } if (business.ContainsKey("street") && business["street"] != null) { address += business["street"].ToString(); } item.Addresse = address; } } // プロフィール画像の取得 getProfIcon(item); } } // Windows Live プロフィール のアイコン画像を取得します private void getProfIcon(ProfileModel item) { LiveConnectClient meProfIconClient = new LiveConnectClient(session); meProfIconClient.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(meProfIconClient_GetCompleted); meProfIconClient.GetAsync("/me/picture"); // プロフィール画像を取得するためのパスです } // Windows Live プロフィール のアイコン画像を取得した時のイベント void meProfIconClient_GetCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null && e.Result.ContainsKey("location")) { if (e.Result["location"] != null) { item.Icon = e.Result["location"].ToString(); } } } } }
テキストベースの個人情報は /me/ 情報アクセスパスで取得、プロフィール画像は /me/picture 情報アクセスパスで取得します。
画面キャプチャ
参考
REST API -MSDN
技術部 かわかみひろき
2011-12-20
Windows Liveの情報取得方法
Windows Live から情報を取得する方法について解説します。具体的な取得方法は別エントリーで行います。
なお、Windows Live認証を行うまでの方法は "Windows Liveの導入から認証までの方法" エントリーを参照ください。
情報取得方法
必要な情報を取得するためには、以下の2つが必要になります。
- 該当権限の付与
- 情報アクセスパスを使っての情報取得処理
情報に対する利用権限の付与

Windows Live情報を取得するには、情報グループに応じてユーザー許諾が必要になり、許諾範囲は利用権限によって決められています。
Windows Live認証時のユーザー許諾画面に、利用権限に応じた取得情報の内容がユーザーへ開示され、ユーザーが同意して初めて対象情報グループへのアクセスが行える仕組みになっています。
利用権限はSignInButtonコントロールのScopesプロパティに半角スペースをセパレータにして以下のように設定します。
<phone:PhoneApplicationPage …省略… xmlns:my="clr-namespace:Microsoft.Live.Controls;assembly=Microsoft.Live.Controls" > <my:SignInButton Content="Button" Height="71" Name="signInButton1" Width="204" Branding="Skydrive" ClientId="_ClientID_" RedirectUri="https://oauth.live.com/desktop" Scopes="wl.basic wl.signin wl.signin" </phone:PhoneApplicationPage>
情報へのアクセス処理
ユーザーに利用許可して貰ったデータ群に対して、情報アクセスパスを使って取得する事になります。
sessionはSignInButtonで認証した時に取得したセッションを利用します。
…省略…
LiveConnectClient liveConnectClient = new LiveConnectClient(session);
liveConnectClient.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(liveConnectClient_GetCompleted);
liveConnectClient.GetAsync("情報アクセスパス");
}
void liveConnectClient_GetCompleted(object sender, LiveOperationCompletedEventArgs e) {
if (e.Error == null) {
// ここで情報アクセスパス先のデータである e.Result を解析します
}
}
利用権限と情報アクセスパスの重要性が分かって頂けたかと思います。
これ以降、利用権限と情報アクセスパスの詳細を解説していきます。
利用権限一覧
Windows Live情報の利用権限は、スコープ毎に用意されています。Core scopesは3つとも権限付与しておくのが無難で、Extended scopesは取得対象データを確認してから付与するか決めてください。
似たような権限が多くて分かりにくいですが、"Windows Live情報と利用権限の対照表" 見出しに書いてある表を見て権限付与するといいです。
Core scopes
| スコープ | 意味 |
|---|---|
| wl.basic | Windows Live プロフィールの情報への読取権限にします |
| wl.offline_access | いつでもWindows Livの情報へアクセス可能にする権限です |
| wl.signin | 自動的にサインインを行う事を可能にする権限です |
Extended scopes
| スコープ | 意味 |
|---|---|
| wl.birthday | Windows Live プロフィールの誕生日情報への読取権限です |
| wl.emails | Windows Live プロフィールのメールアドレス情報への読取権限です |
| wl.phone_numbers | Windows Live プロフィールの電話情報への読取権限です |
| wl.postal_addresses | Windows Live プロフィールの住所情報への読取権限です |
| wl.work_profile | Windows Live プロフィールの仕事情報の読取権限です |
| wl.share | Windows Live プロフィールのステータスメッセージの更新権限です |
| wl.contacts_birthday | Windows Live Hotmailの連絡先情報への読取権限です |
| wl.contacts_create | Windows Live Hotmailの連絡先情報を作成する権限です |
| wl.calendars | Windows Live Hotmailのカレンダー情報への読取権限です |
| wl.calendars_update | WIndows Live Hotmailのカレンダー情報への作成/読取/更新/削除権限です |
| wl.events_create | Windows Live Hotmailのカレンダー上のイベントの作成権限です |
| wl.contacts_calendars | Windows Live Hotmailで共有されているカレンダーの読取権限です |
| wl.photos | Windows Live SkyDriveの写真/動画/音楽やコメント/タグの読取権限です |
| wl.skydrive | Windows Live SkyDriveの写真/動画/音楽やタグの読取権限です |
| wl.skydrive_update | Windows Live SkyDriveの写真/動画/音楽の作成/読取/更新/削除権限です |
| wl.contacts_photos | Windows Live SkyDriveで共有されている写真/動画/音楽やコメント/タグの読取権限です |
| wl.contacts_skydrive | Windows Live SkyDriveで共有されているファイル/音楽/タグの読取権限です |
| wl.messenger | Windows Live Messengerの署名を有効にする権限です |
Developer scopes
| スコープ | 意味 |
|---|---|
| wl.applications | Client ID情報の読取権限です |
| wl.applications_create | Client ID情報の作成権限です |
Windows Live情報と利用権限の対照表
情報グループに対して必要な利用権限と、情報アクセスパスを以下の表にまとめました。
| 情報グループ | 意味 | 利用権限(Scopes) | 情報アクセスパス |
|---|---|---|---|
| User | ユーザーに関する情報の読取を行います Windows Live プロフィールの情報になります | link/updated_timeの読取:wl.basic 誕生日情報の読取:wl.birthday 仕事情報の読取:wl.work_profile メールアドレスの読取:wl.emails 住所の読取:wl.postal_addresses 携帯番号の読取:wl.phone_numbers | /me /USER_ID |
| Activity | Windows Live上で公開している活動情報です 名前/共有メッセージ/活動状態、などの情報になります | 活動情報の作成:wl.share | /me/share /USER_ID/share |
| Friend | Windows Liveに登録している友達情報を読取ます ユーザーID/公開している名前、情報になります | 友達情報の読取:wl.basic | /me/friends /USER_ID/friends |
| Contact | Hotmailの連絡先読取を行います | 誕生日情報の読取:wl.basic と wl.contacts_birthday 誕生日以外の情報読取:wl.basic | /me/contacts /USER_ID/contacts /CONTACT_ID |
| Calendar | Hotmailのカレンダーを作成/読取/更新/削除します | カレンダーの読込:wl.calendars カレンダーの作成/更新/削除:wl.calendars_update 共有されているカレンダーの読取:wl.contacts_calendars | /me/calendars /USER_ID/calendars /CALENDAR_ID |
| Event | Hotmailのカレンダー上のイベントを作成/読取/更新/削除します | イベント読取:wl.calendars イベント作成:wl.events_create イベント更新/削除:wl.calendars_update 共有されているイベントの読取:wl.contacts_calendars | /me/events /USER_ID/events /CALENDAR_ID/events |
| Album | SkyDrive上の写真/ビデオ/音楽ファイル及びフォルダ情報グループの読取を行います | フォルダ情報読取:wl.photos ファイル読取:wl.skydrive 共有されているファイル/フォルダの読取:wl.contacts_photos | /me/albums /USER_ID/albums /ALBUM_ID /ALBUM_ID/files, /me/skydrive/files, /me/skydrive/shared/files, /me/skydrive/shared/albums, /USER_ID/skydrive/files |
| Folder | SkyDrive上のフォルダの作成/読取/更新/削除を行います | フォルダ読取:wl.photos 共有されているフォルダの読取:wl.contacts_photos | /FOLDER_ID /FOLDER_ID/files, /me/skydrive/files, /me/skydrive/shared/files, /USER_ID/skydrive/files, /ALBUM_ID/files |
| File | SkyDrive上のファイルを作成/読取/更新/削除します | ファイル読取:wl.skydrive ファイル作成/更新/削除:wl.skydrive_update 共有されているファイルの読取:wl.contacts_skydrive | /FILE_ID /FOLDER_ID/files, /me/skydrive/files, /me/skydrive/shared, /me/skydrive/shared/files, /USER_ID/skydrive/files |
| Photo | SkyDrive上の写真ファイルの作成/読取/更新/削除を行います | 写真ファイルの読取:wl.photos 写真ファイルの作成/更新/削除:wl.skydrive_update 共有されている写真ファイル読取:wl.contacts_photos | /PHOTO_ID /ALBUM_ID/files, /ALBUM_ID/photos, /FOLDER_ID/files, /me/skydrive/files, /me/skydrive/shared/photos, USER_ID/skydrive/files |
| Audio | SkyDrive上の音楽ファイルの作成/読取/更新/削除を行います | 音楽ファイルの読取:wl.skydrive 音楽ファイルの作成/更新/削除:wl.skydrive_update 共有されている音楽データ読取:wl.contacts_skydrive | /AUDIO_ID /ALBUM_ID/files, /FOLDER_ID/files, /me/skydrive/files, /USER_ID/skydrive/files |
| Video | SkyDrive上のビデオを作成/読取/更新/削除します | ビデオの読取:wl.photos ビデオの作成/更新/削除:wl.skydrive_update 共有されているビデオの読取:wl.contacts_photos | /VIDEO_ID /ALBUM_ID/files, /ALBUM_ID/videos, /FOLDER_ID/files, /me/skydrive/files, /me/skydrive/shared/videos, USER_ID/skydrive/files |
| Comment | SkyDriveの写真/ビデオに対してユーザーが付けたコメントの読取を行います | コメントの読取:wl.photos 共有されているコメントの読取:wl.contacts_photos | /PHOTO_ID/comments /VIDEO_ID/comments /COMMENT_ID |
| Tag | SkyDrive上の写真/ビデオに対してユーザーが付けたタグの読取を行います | タグ読取:wl.photos & wl.skydrive 共有されているタグの読取:wl.contacts_photos & wl.contacts_skydrive | /PHOTO_ID/tags /VIDEO_ID/tags /TAG_ID |
| Application | ClientId情報の取得、新規作成が行えます | ClientId情報読取:wl.applications ClientId新規作成:wl.applications_create | /me/applications /USER_ID/applications /APPLICATION_ID |
| Permissions | ユーザーが同意した利用権限(Scopes)の読取を行います | /me/permissions /USER_ID/permissions | |
| Error | Windows Live APIから返されるエラー情報です |
参考
REST API -MSDN
Scopes and permissions -MSDN
技術部 かわかみひろき

