Привет, %username%!

Если честно, я не ожидал, что столько людей добавят в избранное мой предыдущий пост. На самом деле это не может не радовать: платформа активно развивается и пиарится, что привлекает внимание разработчиков. Сегодня я хочу освятить тему работы со SkyDrive из приложения. Статья, как и в прошлый раз, будет основана на реальном кейсе: мне нужно было дать возможность пользователю расшарить файл в социальные сети.
Для тех, кто не в курсе – SkyDrive – аналог Dropbox от Microsoft: облачное хранилище, объемом 25 ГБ. SkyDrive довольно тесно интегрирован с Windows Phone: во многих маркетинговых компаниях он ставится в замену отсутствующей возможности использования карт памяти, этакая «облачная флешка». Например, если вы хотите расшарить фотографию в твиттер – фотография зальется на скайдрайв и ссылка на неё запостится в твиттер. Давайте такую же функциональность реализуем в нашем приложении.
Для работы нам, прежде всего, понадобится Live SDK, который можно скачать по ссылке. С помощью этого SDK мы можем делать следующее:
Далее нам необходимо получить Client ID и Client Secret для нашего приложения. Это сделать можно по следующей ссылке. Не забываем указать на вкладке API Settings, что наше приложение – мобильный клиент. Всё, теперь можно начинать разрабатывать приложение.
В первую очередь нам необходимо авторизовать наше приложение для использования SkyDrive. После установки Live SDK у вас появится возможность использовать новый элемент интерфейса: SignInButton.

Давайте рассмотрим основные параметры:
Branding – иконка, отображающаяся на кнопке (может так же принимать значения «Windows», «Hotmail», «Messenger»);
ClientId – ID вашего приложения, полученный выше;
RedirectUri – адрес перенаправления;
Scopes – разрешения, необходимые приложению. Здесь мы указали, что будем авторизоваться, использовать SkyDrive, использовать API для работы с галереями и кое-что ещё. Подробнее о различных видах Scopes вы можете почитать по ссылке;
SessionChanged – наш обработчик авторизации;
TextType – текст на кнопке. Так же может быть нескольких видов: SignIn, Login, Connect и кастомный.
Теперь давайте рассмотрим обработчик:
Я предпочитаю хранить сессию в App.xaml.cs: так можно будет работать с API из любой части приложения.
Не забываем указать пространство имен:
Теперь при нажатии на кнопку Sign In вам предложат войти под своим Live ID и разрешить приложению функции, которые мы указали в Scopes.

Для того чтобы размещать фотографию в какой-то папке или альбоме необходимо узнать его ID. Соответственно, при создании папки вам возвращается, в том числе, и её ID. Можно создать альбом, получить его ID, записать в IsolatedStorageSettings и потом загружать фотографии, используя его. Но если пользователь удалит папку, или папка с заданным именем будет уже существовать, то загрузить подобным способом фотографию не получится. Поэтому я предпочитаю всегда сначала получать список папок, проверять на наличие нужной папки. И, если она присутствует – загружаем файлы, если отсутствует – сначала создаём папку, а потом загружаем файл.
Получение списка файлов и проверка:
Для парсинга я использую промежуточный класс SkyDriveContent, в котором хранятся имена папок и их ID. Мы проверяем имена всех папок, которые лежат в корне нашего SkyDrive. Если встречается название папки «SkyDriveTest, то мы берем её ID, если такой папки не находим – создаём с помощью POST запроса:
Когда мы создаём папку, сервер в ответ присылает нам её свойства в формате JSON, в том числе и ID. Для десериализации я использую Json.NET, который доступен в NuGet.
Теперь, когда у нас есть ID папки, мы можем загрузить фотографию. Фотографию в примере мы получаем с камеры:
Непосредственно загрузка:
Как вы можете видеть, загрузка фотографии практически ничем не отличается. Мы так же как и в прошлом случае получаем в ответ ID загруженного изображения, который понадобится нам для его расшаривания. По-умолчанию все файлы, загруженные в нерасшаренную папку, имеют модификатор доступа Private. Теперь давайте расшарим наше изображение. Это делается с помощью добавления к ID нашего изображения параметра "/shared_read_link".

Здесь мы получаем от сервера ссылку на наш файл и передаём её в ShareLinkTask. Всё, на этом работа закончена!
Конечно же, возможности как REST API для SkyDrive, так и Live SDK в целом не ограничиваются тем, о чем я вам рассказал. Почерпнуть дополнительную информацию вы можете из следующих источников:
Скачать пример из статьи.
В данном примере берется изображение с камеры и загружается на SkyDrive. Во время загрузки на странице приложения отображается статус. Не забудьте указать свой ClientID в файле MainPage.xaml! Без этого приложение не заработает!
Всем творческих подвигов и успешного прохождения сертификации! Для тех, кто не в курсе — на днях начался новый конкурс приложений для Windows Phone.
UPD: С Habrastorage небольшая беда, картинки скоро вернутся на свои места.

Если честно, я не ожидал, что столько людей добавят в избранное мой предыдущий пост. На самом деле это не может не радовать: платформа активно развивается и пиарится, что привлекает внимание разработчиков. Сегодня я хочу освятить тему работы со SkyDrive из приложения. Статья, как и в прошлый раз, будет основана на реальном кейсе: мне нужно было дать возможность пользователю расшарить файл в социальные сети.
SkyDrive
Для тех, кто не в курсе – SkyDrive – аналог Dropbox от Microsoft: облачное хранилище, объемом 25 ГБ. SkyDrive довольно тесно интегрирован с Windows Phone: во многих маркетинговых компаниях он ставится в замену отсутствующей возможности использования карт памяти, этакая «облачная флешка». Например, если вы хотите расшарить фотографию в твиттер – фотография зальется на скайдрайв и ссылка на неё запостится в твиттер. Давайте такую же функциональность реализуем в нашем приложении.
Live SDK
Для работы нам, прежде всего, понадобится Live SDK, который можно скачать по ссылке. С помощью этого SDK мы можем делать следующее:
- Создавать/Открывать/Обновлять/Удалять папки
- Делать то же самое с альбомами (специальный вид папок, содержащий медиафайлы)
- Добавлять/Удалять файлы
- Читать/Изменять свойства файлов/папок/альбомов
- Перемещать/Копировать файлы/папки/альбомы
- Расшаривать файлы/папки/альбомы
Далее нам необходимо получить Client ID и Client Secret для нашего приложения. Это сделать можно по следующей ссылке. Не забываем указать на вкладке API Settings, что наше приложение – мобильный клиент. Всё, теперь можно начинать разрабатывать приложение.
Авторизация
В первую очередь нам необходимо авторизовать наше приложение для использования SkyDrive. После установки Live SDK у вас появится возможность использовать новый элемент интерфейса: SignInButton.

<my:SignInButton Name="signInButton" Height="72" Margin="143,511,153,0" VerticalAlignment="Top" Branding="Skydrive" ClientId="ваш_id" Content="Button" RedirectUri="http://oauth.live.com/desktop" Scopes="wl.basic wl.photos wl.skydrive wl.offline_access wl.signin wl.skydrive_update" SessionChanged="signInButton1_SessionChanged" TextType="SignIn" />
Давайте рассмотрим основные параметры:
Branding – иконка, отображающаяся на кнопке (может так же принимать значения «Windows», «Hotmail», «Messenger»);
ClientId – ID вашего приложения, полученный выше;
RedirectUri – адрес перенаправления;
Scopes – разрешения, необходимые приложению. Здесь мы указали, что будем авторизоваться, использовать SkyDrive, использовать API для работы с галереями и кое-что ещё. Подробнее о различных видах Scopes вы можете почитать по ссылке;
SessionChanged – наш обработчик авторизации;
TextType – текст на кнопке. Так же может быть нескольких видов: SignIn, Login, Connect и кастомный.
Теперь давайте рассмотрим обработчик:
private void signInButton1_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e) { if (e.Session != null && e.Status == LiveConnectSessionStatus.Connected) { App.Session = e.Session; } }
Я предпочитаю хранить сессию в App.xaml.cs: так можно будет работать с API из любой части приложения.
private static LiveConnectSession session = null; public static LiveConnectSession Session { get { return session; } set { session = value; } }
Не забываем указать пространство имен:
using Microsoft.Live;
Теперь при нажатии на кнопку Sign In вам предложат войти под своим Live ID и разрешить приложению функции, которые мы указали в Scopes.

Создание/проверка на наличие папки
Для того чтобы размещать фотографию в какой-то папке или альбоме необходимо узнать его ID. Соответственно, при создании папки вам возвращается, в том числе, и её ID. Можно создать альбом, получить его ID, записать в IsolatedStorageSettings и потом загружать фотографии, используя его. Но если пользователь удалит папку, или папка с заданным именем будет уже существовать, то загрузить подобным способом фотографию не получится. Поэтому я предпочитаю всегда сначала получать список папок, проверять на наличие нужной папки. И, если она присутствует – загружаем файлы, если отсутствует – сначала создаём папку, а потом загружаем файл.
Получение списка файлов и проверка:
public class SkyDriveContent { public string Name { get; set; } public string ID { get; set; } } List<SkyDriveContent> ContentList = new List<SkyDriveContent>(); private void CheckAlbum() { if (App.Session == null) { MessageBox.Show("You must sign in first."); Waiting.Visibility = Visibility.Collapsed; } else { txtStatus.Text = "Checking album"; LiveConnectClient client = new LiveConnectClient(App.Session); client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(clientDataFetch_GetCompleted); client.GetAsync("/me/skydrive/files"); } } void clientDataFetch_GetCompleted(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { List<object> data = (List<object>)e.Result["data"]; foreach (IDictionary<string, object> content in data) { SkyDriveContent skyContent = new SkyDriveContent(); skyContent.Name = (string)content["name"]; if (skyContent.Name == "SkyDriveTest") { albumID = (string)content["id"]; } ContentList.Add(skyContent); } if (albumID == "") CreateAlbum(); else UploadPhoto(); } else { MessageBox.Show("Error calling API: " + e.Error.ToString()); Waiting.Visibility = Visibility.Collapsed; } }
Для парсинга я использую промежуточный класс SkyDriveContent, в котором хранятся имена папок и их ID. Мы проверяем имена всех папок, которые лежат в корне нашего SkyDrive. Если встречается название папки «SkyDriveTest, то мы берем её ID, если такой папки не находим – создаём с помощью POST запроса:
private void CreateAlbum() { txtStatus.Text = "Creating album"; Dictionary<string, object> fileData = new Dictionary<string, object>(); fileData.Add("name", "SkyDriveTest"); LiveConnectClient client = new LiveConnectClient(App.Session); client.PostCompleted += new EventHandler<LiveOperationCompletedEventArgs>(CreateAlbum_Completed); client.PostAsync("me/albums", fileData); } void CreateAlbum_Completed(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { JObject jObject = JObject.Parse(e.RawResult); albumID = (string)jObject["id"]; UploadPhoto(); } else { MessageBox.Show("Error calling API: " + e.Error.ToString()); Waiting.Visibility = Visibility.Collapsed; } }
Когда мы создаём папку, сервер в ответ присылает нам её свойства в формате JSON, в том числе и ID. Для десериализации я использую Json.NET, который доступен в NuGet.
Загрузка и расшаривание фотографии
Теперь, когда у нас есть ID папки, мы можем загрузить фотографию. Фотографию в примере мы получаем с камеры:
void cameraCapture_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { bitImage.SetSource(e.ChosenPhoto); image1.Source = bitImage; stream = new IsolatedStorageFileStream("/image.jpg", System.IO.FileMode.OpenOrCreate, iso); WriteableBitmap wb = new WriteableBitmap(bitImage); System.Windows.Media.Imaging.Extensions.SaveJpeg(wb, stream, wb.PixelWidth, wb.PixelHeight, 0, 80); stream.Close(); } }
Непосредственно загрузка:
public void UploadPhoto() { txtStatus.Text = "Uploading photo"; LiveConnectClient uploadClient = new LiveConnectClient(App.Session); uploadClient.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(uploadClient_UploadCompleted); stream = iso.OpenFile("/image.jpg", System.IO.FileMode.Open, System.IO.FileAccess.Read); uploadClient.UploadAsync(albumID, "Image " + DateTime.Now.Millisecond + ".jpg", stream); } void uploadClient_UploadCompleted(object sender, LiveOperationCompletedEventArgs e) { stream.Close(); if (e.Error == null) { txtStatus.Text = "Sharing photo"; JObject jObject = JObject.Parse(e.RawResult); string name = (string)jObject["id"]; Share(name); } else { MessageBox.Show("Error calling API: " + e.Error.ToString()); Waiting.Visibility = Visibility.Collapsed; } }
Как вы можете видеть, загрузка фотографии практически ничем не отличается. Мы так же как и в прошлом случае получаем в ответ ID загруженного изображения, который понадобится нам для его расшаривания. По-умолчанию все файлы, загруженные в нерасшаренную папку, имеют модификатор доступа Private. Теперь давайте расшарим наше изображение. Это делается с помощью добавления к ID нашего изображения параметра "/shared_read_link".
private void Share(string filename) { LiveConnectClient client = new LiveConnectClient(App.Session); client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(GetSharedLink_Completed); client.GetAsync(filename + "/shared_read_link"); } void GetSharedLink_Completed(object sender, LiveOperationCompletedEventArgs e) { if (e.Error == null) { ShareLinkTask shareLinkTask = new ShareLinkTask(); shareLinkTask.Title = "Holiday Photo"; shareLinkTask.LinkUri = new Uri(e.Result["link"].ToString(), UriKind.Absolute); shareLinkTask.Message = "My super holiday photo via #HolidayPhoto!"; shareLinkTask.Show(); txtStatus.Text = "Done!"; Waiting.Visibility = Visibility.Collapsed; } else { MessageBox.Show("Error calling API: " + e.Error.ToString()); Waiting.Visibility = Visibility.Collapsed; } }

Здесь мы получаем от сервера ссылку на наш файл и передаём её в ShareLinkTask. Всё, на этом работа закончена!
Заключение
Конечно же, возможности как REST API для SkyDrive, так и Live SDK в целом не ограничиваются тем, о чем я вам рассказал. Почерпнуть дополнительную информацию вы можете из следующих источников:
- Live Connect Developer Center: msdn.microsoft.com/en-us/windowslive/default
- SkyDrive (photos, videos, and documents): msdn.microsoft.com/en-us/windowslive/hh528485
- The complete developer's guide to the SkyDrive API: channel9.msdn.com/Events/BUILD/BUILD2011/PLAT-134C
- REST API: msdn.microsoft.com/ru-ru/library/hh243648.aspx
- Interactive SDK: http://isdk.dev.live.com/ISDK.aspx?category=SkyDrive+(files+and+photos)&index=0
- Working with the code examples: msdn.microsoft.com/ru-ru/windowslive/hh561316#csharp
Скачать пример из статьи.
В данном примере берется изображение с камеры и загружается на SkyDrive. Во время загрузки на странице приложения отображается статус. Не забудьте указать свой ClientID в файле MainPage.xaml! Без этого приложение не заработает!
Всем творческих подвигов и успешного прохождения сертификации! Для тех, кто не в курсе — на днях начался новый конкурс приложений для Windows Phone.
UPD: С Habrastorage небольшая беда, картинки скоро вернутся на свои места.
