在 Windows 8 中使用 Live SDK - C# + JavaScript






4.92/5 (11投票s)
Live SDK 提供了一系列控件和 API,使应用程序能够与 Microsoft 帐户进行单一登录 (SSO),并访问 Windows Phone 和 Windows 8 上的 SkyDrive、Hotmail 和 Windows Live Messenger 中的信息。
引言
Live SDK 提供了一系列控件和 API,使应用程序能够与 Microsoft 帐户进行单一登录 (SSO),并访问 Windows Phone 和 Windows 8 上的 SkyDrive、Hotmail 和 Windows Live Messenger 中的信息。
Live SDK 支持多种平台,如 iOS、Android,当然还有使用 C# 和 JS 的 Windows Phone 和 Windows 8 应用程序。
在本演示中,我将展示如何在 Windows 8 中使用 Live SDK,因此,为了能跟上本文的进度,您需要安装以下软件:
- Windows 8 – 下载
- Live SDK -Live SDK 下载
您也可以参考 Interactive Live SDK
第一步:构建我们的应用程序
我创建了一个 C#\JavaScript 的空白应用程序,名为“LiveSdkDemo”,并添加了对我们刚刚安装的“Live SDK”的引用。
第二步:添加“登录”按钮
在我们使用 Live SDK 执行任何操作之前,我们首先需要使用我们的 Window Live ID 进行“登录”。要做到这一点,我们需要添加 Live SDK 附带的“SignInButton”控件。但就在我们添加控件之前,让我们来谈谈使用 Live SDK 时的一个非常重要的事情:
作用域:
在您的应用程序调用 Live Connect API 来处理 Live Connect 信息之前,在大多数情况下,您必须获得用户的许可才能访问这些信息,或者以用户的名义创建新对象。在 Live Connect API 中,这种许可被称为作用域。每个作用域都授予不同的权限级别。
在此演示中,我使用了三个作用域:
- wl.signin - 单一登录行为。通过单一登录,已登录 Live Connect 的用户也可以登录到您的网站。
- wl.basic - 读取用户基本配置文件信息。还允许读取用户联系人列表。
- wl.skydrive_update - 读取和写入用户存储在 SkyDrive 中的文件的权限。
除了作用域,我还注册了“onSessionChange”事件,这将让我们知道何时成功连接以及何时收到登录错误。
JavaScript
我创建了一个名为“signin”的 html 元素,在 JS 中,我们需要从代码中填充该元素。
<p id="signin"></p>
现在,在我们用 Live SDK 按钮填充“signin”元素之前,我们需要调用 WL.init 并传入此会话的作用域。此函数初始化 JavaScript 库。应用程序必须在此函数调用库中的其他函数之前调用它,除了订阅/取消订阅事件。
WL.Event.subscribe("auth.login", onLoginComplete);
WL.Event.subscribe("auth.sessionChange", onSessionChange);
WL.init({ scope: ["wl.signin", "wl.basic", "wl.skydrive_update"] });
WL.ui({
name: "signin",
element: "signin"
});
C#
因此,我添加了对 Microsoft.Live.Controls 的 using 声明,并添加了“SignInButton”控件。
我还添加了一个 TextBlock 来显示登录操作中可能出现的任何错误。
<Page
x:Class="LiveSdkDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LiveSdkDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:live="using:Microsoft.Live.Controls"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<live:SignInButton x:Name="btnSignin" Scopes="wl.signin wl.basic wl.skydrive_update"
Branding="Skydrive" SessionChanged="OnSessionChanged"
VerticalAlignment="Top" Width="141" HorizontalAlignment="Left"
Margin="100,100,0,0" />
<TextBlock x:Name="txtStatus" HorizontalAlignment="Center" Margin="0"
TextWrapping="Wrap" VerticalAlignment="Center" Foreground="Red" FontSize="24"/>
</Grid>
</Page>
现在,让我们运行我们的应用程序,看看会发生什么。
您会注意到收到以下错误:
"应用程序未正确配置为使用 Live Connect 服务。要配置您的应用程序,请按照 http://go.microsoft.com/fwlink/?LinkId=220871 上的说明进行操作。"
原因在于,在我们开始构建此应用程序之前,您需要将其注册到 Windows Live。您可以通过访问应用程序管理站点来注册您的应用程序。
然后,您需要执行两个步骤来注册您的应用程序:
1. 您需要输入应用程序名称和发布者(您可以在项目解决方案下的“Package.appxmanifest”中找到)。
在您点击“我接受”后,我们将收到一个新的“程序包名称”和客户端密钥(我将在后续帖子中讨论这一点)。
目前,您只需要将站点上的“程序包名称”复制过来,并在 Package.appxmanifest 中替换当前的即可。
现在让我们再次运行应用程序,在您点击“登录”按钮后,您将看到此消息:(此消息只会出现一次)
点击“是”后,您应该会看到“登录”已更改为
第三步:获取用户数据
成功登录后,我们就可以开始使用 Live SDK 了。我将展示的第一件事是如何从用户的 Live 帐户获取用户数据。
JavaScript
使用全局 WL (Windows Live) 对象,我们可以调用“api”函数来执行 Ajax 请求到 Live SDK REST 服务。您始终可以使用其他 Ajax 库来使用 Live SDK REST,只需调用此 URL 并传入访问令牌即可:
https://apis.live.net/v5.0/me/albums?access_token=ACCESS_TOKEN
- path - 必需。包含 REST API 对象的路径。有关指定 REST 对象路径的信息,请参阅 REST 参考。
- method - 可选。一个 HTTP 方法,指定 API 调用所需的操作。这些操作是标准的 REST API 操作:“COPY”、“GET”、“MOVE”、“PUT”、“POST”和“DELETE”。
- body - 可选。一个 JSON 对象,指定 REST API 请求正文。body 属性仅用于“POST”和“PUT”请求。
WL.api("me", function (data) {
$("#txtStatus").innerHTML = "Full Name:" + data.name +
"<br/>First Name:" + data.first_name +
"<br/>Last Name:" + data.last_name +
"<br/>Profile Link:" + data.link +
"<br/>Gender:" + data.gender +
"<br/>Locale:" + data.locale;
$("#btnBrowse").disabled = false;
});
添加获取我的个人资料图片,这里也是一样,首先定义我想获取其图片的用户的 ID,然后是字符串“picture”。
WL.api("me/picture", function (data) {
$("#userImg").src = data.location;
});
完整代码
function onSessionChange(response) {
var session = WL.getSession();
if (!session.error) {
WL.api("me", function (data) {
$("#txtStatus").innerHTML = "Full Name:" + data.name +
"<br/>First Name:" + data.first_name +
"<br/>Last Name:" + data.last_name +
"<br/>Profile Link:" + data.link +
"<br/>Gender:" + data.gender +
"<br/>Locale:" + data.locale;
$("#btnBrowse").disabled = false;
});
WL.api("me/picture", function (data) {
$("#userImg").src = data.location;
});
}
else {
$("#txtStatus").textContent = session.error.message;
}
}
C#
使用**LiveConnectClient**对象(使用我们的访问令牌),我们可以获得以下能力:
- GET—返回资源的表示。
- POST—向集合添加新资源。
- PUT—在 URL 指向的位置更新资源,或者如果资源不存在,则创建新资源。
- DELETE—删除资源。
- MOVE—移动资源的位置。
- COPY—复制资源。
现在,我将使用 **GetAsync** 方法,传入字符串“me”,告知 Live SDK 我想接收我的信息。
this.liveClient = new LiveConnectClient(e.Session);
var myData = await this.liveClient.GetAsync("me");
txtStatus.Text = string.Format("Full Name:{0}\nFirst Name:{1}\nLast Name:{2}\nProfile Link:{3}\nGender:{4}\nLocale:{5}", myData.Result["name"],
myData.Result["first_name"],
myData.Result["last_name"],
myData.Result["link"],
myData.Result["gender"],
myData.Result["locale"]);
添加获取我的个人资料图片,这里也是一样,首先定义我想获取其图片的用户的 ID,然后是字符串“picture”。
var myPic = await this.liveClient.GetAsync("me/picture");
var bmp = new BitmapImage(new Uri(myPic.Result["location"].ToString()));
imgProfile.Source = bmp;
完整代码
private LiveConnectClient liveClient;
private async void OnSessionChanged(object sender, LiveConnectSessionChangedEventArgs e)
{
if (e.Status == LiveConnectSessionStatus.Connected)
{
this.liveClient = new LiveConnectClient(e.Session);
var myData = await this.liveClient.GetAsync("me");
txtStatus.Text = string.Format("Full Name:{0}\nFirst Name:{1}\nLast Name:{2}\nProfile Link:{3}\nGender:{4}\nLocale:{5}", myData.Result["name"],
myData.Result["first_name"],
myData.Result["last_name"],
myData.Result["link"],
myData.Result["gender"],
myData.Result["locale"]);
var myPic = await this.liveClient.GetAsync("me/picture");
var bmp = new BitmapImage(new Uri(myPic.Result["location"].ToString()));
imgProfile.Source = bmp;
}
else
{
if (e.Error != null)
{
txtStatus.Text = e.Error.Message;
}
}
}
结果
访问用户的公共信息
在您必须先获得用户许可才能访问其信息这一规则存在一个例外:您的应用程序可以在不请求任何作用域的情况下访问用户公开可用的信息。公共信息包括用户的 ID、名字和姓氏、显示名称、性别、区域设置和图片。如果用户选择将其公开,Messenger 联系人列表也可用。
例如:我已将“me”更改为我的朋友 Gil Fink 的 Live Id,这是结果:
第四步:将文件上传到用户文件夹
在这一部分,我们将看到如何使用 Live SDK 将文件上传到 SkyDrive。首先,我添加了另外两个按钮和一个进度条,以便我们可以看到上传进度。
第一个按钮用于选择文件,第二个按钮用于开始上传过程。
选择文件
由于 SkyDrive 对文件的限制,您可以上传任何您想要的文件(您基本可以,但需要将文件扩展名更改为 txt、doc 或任何图片扩展名),所以现在我创建了一个仅用于文本文件和 Word 文档的文件选择器。
JavaScript
function openFile() {
// Create the picker object and set options
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.list;
openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.documentsLibrary;
// Users expect to have a filtered view of their folders depending on the scenario.
// For example, when choosing a documents folder, restrict the filetypes to documents for your application.
openPicker.fileTypeFilter.replaceAll([".txt", ".docs", ".doc"]);
// Open the picker for the user to pick a file
openPicker.pickSingleFileAsync().then(function (file) {
if (file) {
// Application now has read/write access to the picked file
_file = file;
$("#btnStart").disabled = false;
WinJS.log && WinJS.log("Picked photo: " + file.name, "sample", "status");
} else {
_file = undefined;
$("#btnStart").disabled = true;
WinJS.log && WinJS.log("Operation cancelled.", "sample", "status");
}
});
}
C#
private async void btnPickFile_Click(object sender, RoutedEventArgs e)
{
var fp = new FileOpenPicker();
fp.ViewMode = PickerViewMode.List;
fp.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
fp.FileTypeFilter.Add(".txt");
fp.FileTypeFilter.Add(".doc");
fp.FileTypeFilter.Add(".docx");
var file = await fp.PickSingleFileAsync();
if (file != null)
{
_file = file;
txtFilePath.Text = file.Path;
btnStartUpload.IsEnabled = true;
}
else
{
_file = null;
txtFilePath.Text = string.Empty;
btnStartUpload.IsEnabled = false;
}
}
开始上传
JavaScript
要使用 Live SDK 上传文件,我们将使用 - WL.backgroundUpload 方法。
- path - 必需。要上传的文件的路径。
- file_name - 可选。要上传的文件的名称。
- file_input (StorageFile) - 可选。用于读取文件的文件输入对象。
- stream_input - 可选。用于读取文件的文件输入流。
- overwrite - 可选。指示上传的文件是否应覆盖现有副本。指定 true 或“true”表示覆盖,false 或“false”表示不覆盖并且 WL.backgroundUpload 方法调用将失败,或者“rename”表示不覆盖并允许 SkyDrive 为上传的文件分配一个新名称。
backgroundUpload 返回一个 Promise,因此我们可以实现 onError 和 onProgress(用于更新进度条)的代码。
WL.backgroundUpload({
path: "me/skydrive",
file_name: _file.fileName,
file_input: _file,
overwrite: "true" //rename etc...
}).then(function (args) {
$("#txtStatus").textContent = "Upload Completed!";
toggle(true);
},
function (err) {
$("#txtStatus").textContent = e.response;
$("#pb").className = "hidden";
},
function (e) {
$("#pb").value = Math.round(e.progressPercentage);
});
C#
一旦我们获得要上传的文件,我们将首先创建一个新的 LiveOperationProgress 类型的 Progress 对象。使用此对象,我们将看到上传进度并将其分配给我们的 ProgressBar。
为了上传文件,我们需要获取文件流,所以只需调用 – OpenStreamForReadAsync 来获取文件流。
最后,我们将使用内置方法“BackgroundUploadAsync”,传入以下参数:
- 上传位置
- 文件名
- 文件流
- 覆盖选项
- 取消标记
- 进度处理程序
private CancellationTokenSource cts;
private async void btnStartUpload_Click(object sender, RoutedEventArgs e)
{
if (_file == null) return;
btnPickFile.IsEnabled = btnStartUpload.IsEnabled = false;
txtStatus.Text = string.Format("Uploading Backup...");
this.pb.Value = 0;
var progressHandler = new Progress<LiveOperationProgress>(
(progress) => { this.pb.Value = progress.ProgressPercentage; });
var stream = await _file.OpenStreamForReadAsync();
this.cts = new CancellationTokenSource();
LiveOperationResult result =
await this.liveClient.BackgroundUploadAsync("/me/skydrive", _file.Name, stream.AsInputStream(), OverwriteOption.Overwrite, this.cts.Token, progressHandler);
txtStatus.Text = string.Format("Upload Completed!");
btnPickFile.IsEnabled = btnStartUpload.IsEnabled = true;
}
结果
第五步:获取 SkyDrive 文件
现在,在从 SkyDrive 下载文件之前,您需要知道它们的文件 ID。文件名不足以通过 Live SDK 进行下载,因此为了简化事情,让我们首先获取 SkyDrive 中的所有文件。
使用 Live SDK 获取所有文件也将带回文件 ID,因此我们将能够将这些文件本地保存。
JavaScript
我在我们的 body 中添加了一个 ListView 来展示文件。
<div id="fileTemplate" data-win-control="WinJS.Binding.Template">
<div class="file">
<span data-win-bind="textContent: id"></span>
-
<span data-win-bind="textContent: type"></span>
-
<span data-win-bind="textContent: name"></span>
-
<span data-win-bind="textContent: created_time"></span>
</div>
<div id="fileList" data-win-control="WinJS.UI.ListView"
data-win-options="{ selectionMode: 'single',layout: { type: WinJS.UI.ListLayout},
itemTemplate:select('#fileTemplate')}">
</div>
现在,我们只需要使用“api”方法,传入“me/skydrive/files”,这将返回我主文件夹下的所有文件夹和文件。一旦我们从服务器接收到文件列表,我就将响应转换为 List 并将其 dataSource 分配给我们的 ListView itemDataSource 属性。
function getFiles() {
toggle(false);
WL.api("me/skydrive/files", function (response) {
var skyDriveFiles = response.data;
var dataList = new WinJS.Binding.List(skyDriveFiles);
var files = $('#fileList').winControl;
files.itemDataSource = dataList.dataSource;
toggle(true);
});
}
C#
首先,我创建了一个名为 – SkyDriveFile 的新对象来保存我们从 SkyDrive 获取的重要数据。
public class SkyDriveFile
{
public string ID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Link { get; set; }
public DateTime CreationDate { get; set; }
public SkyDriveFile(dynamic fileData)
{
this.Name = fileData.name;
this.ID = fileData.id;
this.Link = fileData.link;
this.Type = fileData.type;
this.CreationDate = Convert.ToDateTime(fileData.created_time);
}
}
我在 XAML 中添加了一个 ListView 来展示文件。现在,我们只需要使用 GetAsync 方法,传入“me/skydrive/files”,这将返回我主文件夹下的所有文件夹和文件。
private async void btnGetFiles_Click(object sender, RoutedEventArgs e)
{
this.cts = new CancellationTokenSource();
LiveOperationResult Aresult =
await this.liveClient.GetAsync("me/skydrive/files", this.cts.Token);
var fileList = new List<SkyDriveFile>();
dynamic data = Aresult.Result;
foreach (var dd in data)
{
foreach (var d in dd.Value)
{
fileList.Add(new SkyDriveFile(d));
}
}
listFiles.ItemsSource = fileList;
}
结果
第六步:下载文件
现在我们已经获得了所有文件 ID,我们可以继续将它们下载到我们的机器上。
JavaScript
要使用 Live SDK 下载文件,我们将使用“backgroundDownload”方法,这与使用“backgroundUpload”方法几乎相同,但这次我们需要传入想要下载的文件 ID,并在其后添加“/content”。
首先,让我们从 fileList 中获取选定的文件,并在 Temp 文件夹下创建一个具有相同名称的新文件。
list.selection.getItems().then(function (selectedFiles) {
var fileToDownload = selectedFiles[0].data;
list.selection.clear();
//Creating new file
Windows.Storage.ApplicationData.current.temporaryFolder.createFileAsync(fileToDownload.name,
Windows.Storage.CreationCollisionOption.replaceExisting).then(function (localFile) {
现在我们可以在 temp 文件夹下创建新文件,我们可以开始下载了。
//Starting download
var properties = { path: fileToDownload.source, file_output: localFile, overwrite: "true" };
WL.backgroundDownload(properties).then(function (args) {
$("#txtStatus").textContent = "Download Completed! - " + localFile.path;
toggle(true);
}, function (err) {
$("#txtStatus").textContent = e.response;
$("#pb").className = "hidden";
}, function (progress) {
$("#pb").value = Math.round(progress.progressPercentage);
});
});
C#
要使用 Live SDK 下载文件,我们将使用“**BackgroundDownloadAsync**”方法,这与使用“**BackgroundUploadAsync**”方法几乎相同,但这次我们需要传入想要下载的文件 ID,并在其后添加“/content”。
我在 Temp 文件夹下创建了一个新文件,并使用 Stream.CopyToAsync 方法将我从 SkyDrive 获得的文件流复制到了我创建的新文件中。
private async void btnDownloadFile_Click(object sender, RoutedEventArgs e)
{
this.pb.Value = 0;
var progressHandler = new Progress<LiveOperationProgress>(
(progress) => { this.pb.Value = progress.ProgressPercentage; });
var file = listFiles.SelectedItem as SkyDriveFile;
txtStatus.Text = string.Format("Downloading Backup...");
LiveDownloadOperationResult result =
await this.liveClient.BackgroundDownloadAsync(string.Format("{0}/content", file.ID), this.cts.Token, progressHandler);
var stream = await result.GetRandomAccessStreamAsync();
var temp = Windows.Storage.ApplicationData.Current.TemporaryFolder;
//Creating new file under application temp folder.
var localFile = await temp.CreateFileAsync(file.Name, CreationCollisionOption.GenerateUniqueName);
//Get new file stream
var fileStream = await localFile.OpenStreamForWriteAsync();
//Copying SkyDrive file stream into local file.
await stream.AsStreamForRead().CopyToAsync(fileStream);
await fileStream.FlushAsync();
fileStream.Dispose();
stream.Dispose();
txtStatus.Text = string.Format("File Save! - " + localFile.Path);
}
结果 