既にMarketplaceから公開されているSensor Checkerを見ながら思った。計測結果をファイル化したいと。都合よくLive SDK v5.0が公開され思った。SkyDriveに計測結果をアップしたら便利だよなと、無料で25GBだし…ということで、計測結果をファイル化してSkyDriveにアップする機能拡張を行いました。既に機能追加版はMarketplaceにアップロードしたので、Rejectされなければ直ぐアップデートされるはずです。
SkyDriveへのファイルアップロードは、意外と簡単。方法を順番に説明していきます。
http://www.microsoft.com/download/en/confirmation.aspx?id=28195 からファイルをダウンロードして、ダブルクリック&インストールします。
を追加します。
Appクラスは、App.xaml.csにあります。
using Microsoft.Live;
を先頭に加え、
public LiveConnectSession LiveSession { get; set; }
を定義しておきます。
これで準備は万端です。
プロジェクトにページを一枚追加します。そのページの先頭のほうに、名前空間を以下の様に追加します。
<phone:PhoneApplicationPage … xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:live="clr-namespace:Microsoft.Live.Controls;assembly=Microsoft.Live.Controls" FontFamily="{StaticResource PhoneFontFamilyNormal}" …
そして、Windows Liveのサインインページにナビゲートする為のボタンを追加します。
<StackPanel Name="SigninPanel" Grid.Row="0"> <TextBlock Text="Signin to SkyDrive" FontSize="24" HorizontalAlignment="Center"/> <live:SignInButton Name="buttonSignin" Content="Sign-in to SkyDrive" ClientId="########" ← クライアントID Scopes="wl.basic wl.skydrive wl.offline_access wl.signin wl.skydrive_update" ←許可範囲 RedirectUri="http://oauth.live.com/desktop" Branding="Skydrive" SignInText="SignIn" SessionChanged="buttonSignin_SessionChanged" ←セッション情報変化の通知を受ける為のハンドラ登録 /> </StackPanel>
LiveのWindows Phone用部品としてサインイン用ボタンが用意されています。これを使えば簡単にSkyDriveにアクセスする為の認証が行えます。アトリビュートのClientIdは、https://manage.dev.live.com/ にアクセスして作成するアプリを登録すると、そこで表示されるので、その値をコピペします。Scopesは、サインインする際にアプリケーションに対して、アクセス要求の範囲を指定します。サインインの際、ユーザーに対して、これらのアクセスを許可するかの判断が任されます。詳しくは、http://msdn.microsoft.com/en-us/library/hh243646.aspx を見てください。ファイルのアップロードを行うには、wl.skydrive_updateを指定する必要があります。
実行すると以下のページが表示されます。
サインインをタップすると、以下の画面が表示され、Live IDとパスワードを入力し、サインインをタップすると、Scopesに対応した許可画面が表示されます。
→
右側の図で表示される項目はScopesの指定によって変わりますが、ここでユーザーが”はい”をタップすると、SkyDriveへのアクセスが可能になります。SessionChangedアトリビュートに登録したハンドラは、
private void buttonSignin_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e) { if (e.Session != null && e.Status == LiveConnectSessionStatus.Connected) { App.LiveSession = e.Session; … } else { MessageBox.Show("Signin Failed. "); } }
こんな感じで、接続が成功したら、AppクラスのLiveSessionプロパティにセッションを保存しておきます。
ファイルをアップロードする場合、アップロード先のフォルダー情報が必要です。フォルダー情報を取得するには、以下の様なコードを書きます。
LiveConnectClient client = new LiveConnectClient(App.LiveSession); client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_GetCompleted); client.GetAsync("me/skydrive/files?filter=folders", client);
フォルダー情報を取得するには、4.で取得したSession情報を使って先ずLiveConnectClientのインスタンスを作成します。clientのGetAsync()メソッドを、赤字で書いた文字列を引数にしてコールすると、応答が帰ってくると、GetCompletedに登録したハンドラがコールされます。赤字の部分を解読すると、LiveのAPIはREST形式のAPIなので、URLが"me/skydrive/files"で、引数が"filter=folders"で、検索条件としてfoldersを指定してクエリーをかけてると読めます。GetAsyncの2番目の引数は、GetCompletedがコールされた際に再利用する為の状態変数で、ここではclientを渡しています。
GetCompletedのハンドラは、以下の様なコードです。
void client_GetCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { try { string path = null; Dictionary<string, object> folderData = e.Result as Dictionary<string, object>; List<object> folders = (List<object>)folderData["data"]; foreach (var item in folders) { Dictionary<string, object> folder = item as Dictionary<string, object>; if (folder["name"].ToString() == uploadFolderName) { path = folder["id"].ToString(); break; } } if (path != null) { UploadFile(path, e.UserState as LiveConnectClient); } else { … } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
このハンドラに渡される引数eのResultは、文字列をキーとし、object型の変数を値とする結果が渡されてきます。実際どんな値が送られてくるかは、デバッグ時ステップ実行して確かめてください。基本は、"data”という文字列をキーにした値には、SkyDriveのドキュメント直下に存在するフォルダー情報を格納したリストが入っています。そのリストにはまたキーバリューペアが入っているのでDictionary型で受けます。"name"というキーにはフォルダー名が格納されていて、"id"にそのフォルダーのパス(path)が格納されています。フォルダーに対して取得できる情報については、http://msdn.microsoft.com/en-us/library/hh243648.aspx#folder を参考にしてください。
このコードでアップロード先のフォルダーのパスを取得して、ファイルをアップロードするわけです。次にUploadFileの中身を紹介します。
var storage = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication(); { fstream = storage.OpenFile(filename, System.IO.FileMode.Open); client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_UploadCompleted); client.UploadAsync(path, filename, fstream); }clientは、LiveConnectClientのインスタンス、pathは、5.で説明した、フォルダーのSkyDrive上のパス(id)です。filenameは、アップロードしたいファイル名で、このコードは、IsolatedStorageに格納されているファイルを同じファイル名でアップロードする事を前提としてコーディングされています。UploadAsync()メソッドをコールすると、実際にSkyDriveにアップロードが開始されるわけです。このメソッドの3番目の引数がStreamになっているので、カメラや音源など、予め作成しておいたファイルでなくてもアップロードが可能と思われます。
実際にやってみたところ、ファイル名の拡張子がxml、つまりXMLファイルの場合は、上手くアップロードできないようです。私はこれで半日嵌りましたので、皆さんご注意。
ちょっと長くなりましたが、SkyDriveへのファイルアップロードは完全なパターンコードです。SkyDriveはLive IDを登録するだけで、無料で25GBのストレージが使えます。アクセス権の設定なども可能なので、いろんな種類のファイルをアプリからアップロードしたい方、是非お試しを。