Live SDK筆記5-SkyDrive Explorer, Windows Phone 7版


一連寫了四篇筆記,介紹了Live SDK,也實際玩過取得使用者Live ID身分、連上SkyDrive等把戲:

埋了這些哽,其實背後我最想做的,是從WP7程式連上SkyDrive!

手機基於儲存空間的限制,以及跨裝置/平台共享的需求,非常需要結合網路儲存空間做為後盾,而WP7配上微軟體系的SkyDrive,感覺上是很棒的組合。

Live SDK有提供WP7專用的元件庫,下載安裝Live SDK後,可在WP7專案參照中找到Microsoft.Live及Microsoft.Live.Controls,學習中心有篇WP7整合Live SDK教學,是很好的入門。

Live SDK提供SignInButton控制項,表面上是顆登入登出鈕,背地則幫我們處理掉在App內嵌瀏覽器載入Live帳號登入網頁以及同意網頁等繁瑣細節,是整合Live SDK最簡便的做法。如果在Visual Studio工具箱沒看到它,可自行找到Microsoft.Live.Controls.dll加入工具箱(如下圖)。

不過,有一點要注意,由於在App運作時,不像在ASP.NET範例中會有Callback.aspx負責接入Authorization Code再呼叫API取得Access Token。請參考註冊App一文第3點提及的做法,申請Client ID時,Redirect Domain請留白,然後勾選"Mobile client app"為"Yes",如此,此Client ID即可使用httqs://oauth.live.com/desktop做為Redirect Page,並直接取得Access Token,如此在行動裝置上即可獨立運作。

我想試做的玩具是一個SkyDrive簡易瀏覽器,功能跟上一篇的ASP.NET版差不多,取得使用者對wl.skydrive範圍的同意權後,列出使用者SkyDrive下的目錄,點選目錄可展開列出其下的子項目,若是檔案則可進行檢視,不過WP7能支援的檔案格式比PC少,我只先選擇對圖片(jpg, png)及影片(wmv, mp3, mp4)提供檢視功能。

MainPage.xaml放入一個SignInButton及ListBox:

排版顯示 純文字
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="Mini SkyDrive Explorer" 
                       Style="{StaticResource PhoneTextNormalStyle}"/>
            <my:SignInButton x:Name="btnSignIn" Branding="Skydrive" 
             SessionChanged="btnSignIn_SessionChanged" CientId="0000000016888888" 
             RedirectUri="https://oauth.live.com/desktop" 
             Scopes="wl.signin wl.basic wl.skydrive"/>
        </StackPanel>
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <ListBox x:Name="DirList" FontSize="36" 
                     MouseLeftButtonUp="DirList_MouseLeftButtonUp">
            </ListBox>
        </Grid>
    </Grid>

MainPage.xaml.cs則加入程式邏輯,主要原理是在使用者完成登入及同意後(btnSignIn_SessionChanged事件)建立一個LiveConnectClient,即可使用它呼叫REST API執行各種操作。呼叫結果由client_GetCompleted事件解析,相關的註解說明我附加在程式裡,所以直接看Code:

排版顯示 純文字
using System;
using System.Collections.Generic;
using System.Windows.Input;
using Microsoft.Phone.Controls;
using Microsoft.Live;
using Microsoft.Live.Controls;
 
namespace MiniSkyDriveExplorer
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }
 
        private LiveConnectClient client = null;
        private void btnSignIn_SessionChanged(object sender, 
            LiveConnectSessionChangedEventArgs e)
        {
            if (e.Status == LiveConnectSessionStatus.Connected)
            {
                DirItem.LiveSession = e.Session;
                client = new LiveConnectClient(e.Session);
                client.GetCompleted += 
                    new EventHandler<LiveOperationCompletedEventArgs>(
                        client_GetCompleted);
                //呼叫me/skydrive,取得根目錄folderId
                client.GetAsync("me/skydrive", 
                    new MyUserState(ApiMethod.SkyDriveProp));
            }
        }
        private const string goUpperSymbol = "\t";
        //所有的REST API呼叫動作完成後,都會觸發此段解析回傳結果
        //為降低範例程式複雜度,以下並未包含防呆容錯的邏輯,實際開發時應補上
        void client_GetCompleted(object 
                                 sender, LiveOperationCompletedEventArgs e)
        {
            MyUserState state = e.UserState as MyUserState;
            if (state == null) return;
            switch (state.Method)
            {
                //取得SkyDrive主資料夾的folderId
                case ApiMethod.SkyDriveProp:
                    //取出id,列出根目錄下的項目
                    ListFiles(e.Result["id"].ToString());
                    break;
                //取得目錄清單
                case ApiMethod.SkyDriveDir:
                    //由data取得陣列
                    List<object> items =
                        e.Result["data"] as List<object>;
                    if (items != null)
                    {
                        DirList.Items.Clear();
                        DirList.DisplayMemberPath = "DisplayName";
                        //加入回上層的邏輯
                        if (folderIdStack.Count > 1)
                        {
                            DirItem di = new DirItem(goUpperSymbol, "[..]");
                            DirList.Items.Add(di);
                        }
 
                        foreach (Dictionary<string, object> item in items)
                        {
                            DirItem di  = new DirItem(
                                item["id"].ToString(),
                                item["name"].ToString()
                            );
                            //資料夾時額外取得子項目數
                            if (di.IsFolder)
                                di.Count = int.Parse(item["count"].ToString());
                            else //檔案則取得下載網址
                                di.SrcUrl = item["source"].ToString();
                            //加入清單
                            DirList.Items.Add(di);
                        }
                    }
                    break;
            }
        }
        //用以保存上層目錄的folderId
        private Stack<string> folderIdStack = new Stack<string>();
        private void ListFiles(string folderId)
        {
            if (client == null) return;
            if (folderId == goUpperSymbol)
            {
                folderIdStack.Pop();
                folderId = folderIdStack.Peek();
            }
            else folderIdStack.Push(folderId);
            client.GetAsync(folderId + "/files", 
                            new MyUserState(ApiMethod.SkyDriveDir));
        }
        private void DirList_MouseLeftButtonUp(object sender, 
                                               MouseButtonEventArgs e)
        {
            DirItem di = DirList.SelectedItem as DirItem;
            //資料夾的話,繼續展開
            if (di.IsFolder || di.Id == goUpperSymbol) ListFiles(di.Id);
            //否則試著下載回來檢視
            else
            {
                DirItem.Current = di; //將此DirItem設為Current
                NavigationService.Navigate(
                    new Uri("/Viewer.xaml", UriKind.Relative));
            }
        }
    }
}

為了讓程式更結構化一點,我宣告了一個很簡單的SkyDrive項目物件模型: (即上面MainPage.xaml.cs中所出現DirItem、MyUserState物件的由來)

排版顯示 純文字
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Live;
 
namespace MiniSkyDriveExplorer
{
    #region 用以記錄REST API呼叫資訊的狀態物件
    public enum ApiMethod
    {
        SkyDriveProp, // me/skydrive
        SkyDriveDir,  // folderId/files
        SkyDriveGetImage,
        SkyDriveGetMedia
    }
    public class MyUserState
    {
        public ApiMethod Method;
        public string FileName;
        public MyUserState(ApiMethod method)
        {
            Method = method;
        }
    }
    #endregion
 
    #region 簡單的目錄物件
    public class DirItem
    {
        //是否為資料夾
        public bool IsFolder
        {
            get { return Id.StartsWith("folder"); }
        }
        //顯示名稱
        public string Name;
        //foderId或fileId
        public string Id;
        //上層資料夾的folderId
        public string ParentId;
        //若為資料夾時,標示其下項目數
        public int Count;
        //下載來源URL
        public string SrcUrl;
        //顯示名稱,資料夾為[folderName](count),檔案則為fileName
        public string DisplayName
        {
            get
            {
                return IsFolder && !Name.Equals("..") ?
                    string.Format("[{0}]({1})", Name, Count) : Name;
            }
        }
        public DirItem(string id, string name)
        {
            Id = id;
            Name = name;
        }
        //用此靜態屬性當作頁面間的傳遞媒介
        public static DirItem Current = null;
        //供跨頁面共用LiveConnectSession
        public static LiveConnectSession LiveSession = null;
    }
    #endregion
}

除了SkyDrive清單展示,我另外做了一個Viewer.xaml,用來呈現SkyDrive中的圖片(png, jpg)及媒體檔(wmv, mp3, mp4)。 
註: Windows Phone模擬器不支援部分媒體格式,測試前可先看一下MSDN文件,其中有些已註明This codec is unsupported in Windows Phone Emulator的格式,測試前請認清,以免在模擬器上猛試不成白花時間! (謎之聲: 這條註解怎麼隱含著強烈的怨念?)

要從SkyDrive下載檔案,可以透過LiveConnectClient.DownloadAsync輕鬆達成,在client_DownloadCompleted事件中可以直接取得byte[],十分方便。媒體檔的部分,我還沒試出可以串流播放的做法,所以先採行的方式是先將下載結果存成IsolatedStorageFile,再叫出MediaPlayerLauncher進行播放。程式範例如下:

排版顯示 純文字
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Microsoft.Live;
using System.Windows.Media.Imaging;
using System.IO.IsolatedStorage;
using Microsoft.Phone.Tasks;
 
namespace MiniSkyDriveExplorer
{
    public partial class Viewer : PhoneApplicationPage
    {
        public Viewer()
        {
            InitializeComponent();
        }
 
        private string[] imgExts = "png,jpg".Split(',');
        private string[] mediaExts = "wmv,mp3,mp4".Split(',');
        private LiveConnectClient client = null;
 
        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            if (DirItem.LiveSession == null || DirItem.Current == null)
                return;
            //建立LiveConnectClient
            client = new LiveConnectClient(DirItem.LiveSession);
            client.DownloadCompleted += 
                new EventHandler<LiveDownloadCompletedEventArgs>(
                client_DownloadCompleted);
            //清空內容
            ContentPanel.Children.Clear();
            //取得要檢視的檔案
            DirItem di = DirItem.Current;
            ApplicationTitle.Text = di.Name;
            //由副檔名決定開啟方式
            string ext = System.IO.Path.GetExtension(di.Name).ToLower().TrimStart('.');
            if (imgExts.Contains(ext))
                client.DownloadAsync(di.SrcUrl, new MyUserState(ApiMethod.SkyDriveGetImage));
            else if (mediaExts.Contains(ext))
            //針對媒體檔,比較貼心的方式是透過Streaming方式播放
            //此處只簡單示範整個檔案下載完畢後才撥放
                client.DownloadAsync(di.SrcUrl,
                    new MyUserState(ApiMethod.SkyDriveGetMedia) { FileName = di.Name });
            else
                ContentPanel.Children.Add(new TextBox() { Text = "Unsupported File Type" });
        }
 
        void client_DownloadCompleted(object sender, LiveDownloadCompletedEventArgs e)
        {
            MyUserState state = e.UserState as MyUserState;
            if (state == null) return;
            switch (state.Method)
            {
                case ApiMethod.SkyDriveGetImage:
                    BitmapImage bmp = new BitmapImage();
                    bmp.SetSource(e.Result);
                    Image img = new Image();
                    img.Source = bmp;
                    ContentPanel.Children.Add(img);
                    break;
                case ApiMethod.SkyDriveGetMedia:
                    //此處採用將檔案下載儲存後再播放的做法
                    IsolatedStorageFileStream fs =
                        IsolatedStorageFile.GetUserStoreForApplication()
                        .CreateFile(state.FileName);
                    e.Result.CopyTo(fs);
                    fs.Close();
                    MediaPlayerLauncher mpl = new MediaPlayerLauncher()
                    {
                        Location = MediaLocationType.Data,
                        Media = new Uri(state.FileName, UriKind.Relative)
                    };
                    mpl.Show();
                    break;
            }
        }
    }
}

程式實際執行結果如下,按下SignInButton後,畫面會變成Windows Live的登入畫面,使用者輸入Windows Live帳號並同意授權後:

 

程式便可透過me/skydrive REST API取得使用者SkyDrive根目錄的Id,接著使用folderId/files就可取回該目錄下所有子項目的資訊,以ListBox的方式展示出來。

  

檢視圖片及影片的範例:

  

很簡單吧!? 大家一起為WP7 App加入SkyDrive支援吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的海滨体育馆管理系统,源码+数据库+毕业论文+视频演示 本基于Spring Boot的海滨体育馆管理系统设计目标是实现海滨体育馆的信息化管理,提高管理效率,使得海滨体育馆管理工作规范化、高效化。 本文重点阐述了海滨体育馆管理系统的开发过程,以实际运用为开发背景,基于Spring Boot框架,运用了Java技术和MySQL作为系统数据库进行开发,充分保证系统的安全性和稳定性。本系统界面良好,操作简单方便,通过系统概述、系统分析、系统设计、数据库设计、系统测试这几个部分,详细的说明了系统的开发过程,最后并对整个开发过程进行了总结,实现了海滨体育馆相关信息管理的重要功能。 本系统的使用使管理人员从繁重的工作中解脱出来,实现无纸化办公,能够有效的提高海滨体育馆管理效率。 关键词:海滨体育馆管理,Java技术,MySQL数据库,Spring Boot框架 本基于Spring Boot的海滨体育馆管理系统主要实现了管理员功能模块和学生功能模块两大部分,这两大功能模块分别实现的功能如下: (1)管理员功能模块 管理员登录后可对系统进行全面管理操作,包括个人中心、学生管理、器材管理、器材借出管理、器材归还管理、器材分类管理、校队签到管理、进入登记管理、离开登记管理、活动预约管理、灯光保修管理、体育论坛以及系统管理。 (2)学生功能模块 学生在系统前台可查看系统信息,包括首页、器材、体育论坛以及体育资讯等,没有账号的学生可进行注册操作,注册登录后主要功能模块包括个人中心、器材管理、器材借出管理、器材归还管理、校队签到管理、进入登记管理、离开登记管理、活动预约管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值