Pull to refresh

Интеграция приложения на Windows Phone со SkyDrive

Reading time7 min
Views4.9K
Привет, %username%!

Если честно, я не ожидал, что столько людей добавят в избранное мой предыдущий пост. На самом деле это не может не радовать: платформа активно развивается и пиарится, что привлекает внимание разработчиков. Сегодня я хочу освятить тему работы со 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 в целом не ограничиваются тем, о чем я вам рассказал. Почерпнуть дополнительную информацию вы можете из следующих источников:


Скачать пример из статьи.
В данном примере берется изображение с камеры и загружается на SkyDrive. Во время загрузки на странице приложения отображается статус. Не забудьте указать свой ClientID в файле MainPage.xaml! Без этого приложение не заработает!

Всем творческих подвигов и успешного прохождения сертификации! Для тех, кто не в курсе — на днях начался новый конкурс приложений для Windows Phone.

UPD: С Habrastorage небольшая беда, картинки скоро вернутся на свои места.
Tags:
Hubs:
+16
Comments2

Articles