Home > Windows Phone > Backup your Windows Phone Isolated Storage data to SkyDrive using Live Connect API

Backup your Windows Phone Isolated Storage data to SkyDrive using Live Connect API

As a Windows Phone developer you know that you can store your application local data to Isolated Storage. Isolated Storage restricts all your I/O operations so other applications cannot access or corrupt your data, which provides very efficient security of app’s and user’s data. You can store WP7 local data to IsolatedStorageSettings, database or folders and files.

You also know that you have to backup your data in case of data loss or something else. Classic backup scenario includes simple data upload to your web application or cloud service. But if you tried to implement solution that includes upload to SkyDrive, DropBox or any other free cloud hosting service, you know that situation is not so simple, primarily because there are not any official API providers for Windows Phone platform. Off course, there are some community libraries that can help you, but in most cases they are not suitable for WP7 solutions or are very hard to implement. For example, there is community SkyDrive API library called SkyDrive .NET API Client, based on SkyDrive WebDAV web services, which works fine in web or desktop environment, but not for WP7. SkyDrive’s problem was lack of official Microsoft documentation and API. But few months ago Microsoft finally announced REST APIs for Windows Live platform. It was called “Messenger Connect”, but problem was that was primarily targeted to web client script developers, because APIs were exposed as JavaScript APIs. But no matter what, it was good sign. It was matter of time when we can expect managed (C#) API for Windows Live. On September 13th, Microsoft as a part of BUILD conference preliminary release of Windows 8, also published Live Connect, the new API that supports Metro style apps and Windows Phone apps. You can check out Live Connect now by visiting http://dev.live.com. Final release of Live Connect is expected in November 2011. You can download Live SDK Developer Preview from here.

 

Referencing the APIs with C#

When you download and unpack Live Connect SDK Developer Preview you will find Live Connect MSI setup file (LiveSDK.msi) and preliminary CHM documentation (LiveConnectPrelim.chm). When you install LiveSDK, you will find two new assemblies in Visual Studio .NET reference list: Microsoft.Live and Microsoft.Live.Controls:

image

Also, API ships with Live Connect Sign In control that will help you with user sign-in scenarios. If the control is not visible in your Toolbox you can register it by browsing Windows Phone\References\Microsoft.Live.Controls.dll assembly in Live SDK installation folder.

image

 

Getting a client ID and configuring your app

Before you continue with your development and call Live Connect APIs, you must configure your app with a unique identifier, which we call a client ID. You get a client ID and you can specify a redirect domain (if needed), at the Live Connect app management site. Sign in with your Microsoft account credentials, click Create application, type the app’s name and then click I accept. Live Connect creates and then displays the client ID. It should look something like this 00000000603E0BFE:

image

image

 

Sign-in user

To enable user to upload data to SkyDrive (or use any other Windows Live service like Hotmail, Contacts, Messenger or settings), the user must be signed in to Live Connect. A standard way to do this is by adding sign-in functionality to your app. This functionality (typically a button or a hyperlink) enables a user to provide their Microsoft account credentials. After the Live Connect APIs verify these credentials, it returns an access token to your app. This access token confirms that the user successfully signed in, and it specifies which parts of the user’s info your app can work with and for how long.

image

Best way to prompt a user to sign in in your WP7 app is to use the Live Connect sign-in control. You do this by setting the sign-in control’s properties in XAML code as is shown in code above. You must declare following namespace in your XAML page:

<phone:PhoneApplicationPage 
    …

xmlns:my="clr-namespace:Microsoft.Live.Controls;assembly=Microsoft.Live.Controls">

Also, you must set the Scopes, ClientId, RedirectUri and SessionChanged properties of Sign in control:

Scopes defines permissions from the user who owns the info to access his or her info or to create new objects on his or her behalf. In our scenario wl.skydrive_update scope is required to access and update user’s SkyDrive folders and files.

ClientId property is client ID of your Windows Live Application.

RedirectUri property defines landing page for you application. However, in Windows Phone scenarios that is not needed. In our case we will set RedirectUri in SignIn control to https://oauth.live.com/desktop.

SessionChanged property sets event handler method. Here is example how to set SessionChanged and LoginCompleted events in SignIn control that you put into your XAML page:

 

void btnSignin_SessionChanged(object sender, LiveConnectSessionChangedEventArgs e)
{
    if (e.Session != null &&
        e.Session.Status == LiveConnectSessionStatus.Connected)
    {
        client = new LiveConnectClient(e.Session);
        infoTextBlock.Text = "Signed in.";
        client.GetCompleted +=
            new EventHandler<LiveOperationCompletedEventArgs>(btnSignin_GetCompleted);
        client.GetAsync("me", null);
    }
    else
    {
        infoTextBlock.Text = "Not signed in.";
        client = null;
    }
}

void btnSignin_GetCompleted(object sender, LiveOperationCompletedEventArgs e)
{
    if (e.Error == null)
    {
        infoTextBlock.Text = "Hello, signed-in user!";
    }
    else
    {
        infoTextBlock.Text = "Error calling API: " +
            e.Error.ToString();
    }
}

For more information about user’s sign in, check “Signing users in” chapter in Live Connect documentation.

So, if you successfully set your XAML page and sign in code, following screenshots show user’s “sign in scenario”:

1) Click Sign in button:

image

 

2) User is redirected to Windows Live authentication page:

image

 

3) User is prompt to okay scopes that your application needs:

image

 

4) User is signed:

image

 

Upload data to SkyDrive

In this scenario I used Camera Capture feature of WP7 to capture camera image, save it to Isolated Storage and upload it to dedicated SkyDrive folder. CameraCaptureTask is used to capture desired image and save it to Isolated Storage. Following code describes capturing and image saving to Isolated Storage:

private LiveConnectClient client;
private CameraCaptureTask cameraCaptureTask;
private string cameraRollFileName = "MyCameraRollPicture.jpg";
private string skyDriveFolderName = "IsolatedStorageFolder";
private string skyDriveFolderID = string.Empty;

private void Camera_Click(object sender, EventArgs e)
{
    try
    {
        cameraCaptureTask.Show();
    }
    catch (System.InvalidOperationException ex)
    {}
}

private void cameraCaptureTask_Completed(object sender, PhotoResult e)
{
    if (e.TaskResult == TaskResult.OK)
    {
        BitmapImage bmp = new BitmapImage();
        Stream capturedImageStream = e.ChosenPhoto;
        bmp.SetSource(capturedImageStream);
        this.SaveImageToIS(bmp);
    }
}

private void SaveImageToIS(BitmapImage bitmapImage)
{

    Uri uri = new Uri(cameraRollFileName, UriKind.Relative);
    string file = uri.ToString();
    using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
    {
        if (store.FileExists(file))
            store.DeleteFile(file);
        IsolatedStorageFileStream fileStream = store.CreateFile(file);
        StreamResourceInfo sri = null;
        sri = Application.GetResourceStream(uri);
        WriteableBitmap wb = new WriteableBitmap(bitmapImage);
        Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
        fileStream.Close();
    }
}

When user captures photo and clicks upload button, following scenario is happening:

1) Get info about user’s SkyDrive folders:

 

private void UploadPhoto_Click(object sender, EventArgs e)
{
   
    if (client == null || client.Session == null || client.Session.Status != LiveConnectSessionStatus.Connected)
    {
        MessageBox.Show("You must sign in first.");
    }
    else
    {
        client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(GetFolderProperties_Completed);
        // If you put photo to folder it becomes album.
        client.GetAsync("me/skydrive/files?filter=folders,albums");
    }
}

GetAsync is a helper function for making calls to the REST API. In our case we will get data about all folders and albums in user’s SkyDrive root folder.

 

2) Process data returned by GetCompleted handler:

private void GetFolderProperties_Completed(object sender, LiveOperationCompletedEventArgs e)
{

if (e.Error == null)
{
    Dictionary<string, object> folderData = (Dictionary<string, object>)e.Result;
    List<object> folders = (List<object>)folderData["data"];

    foreach (object item in folders)
    {
        Dictionary<string, object> folder = (Dictionary<string, object>)item;
        if (folder["name"].ToString() == skyDriveFolderName)
        skyDriveFolderID = folder["id"].ToString();
    }

    if (skyDriveFolderID == string.Empty)
    {
        Dictionary<string, object> skyDriveFolderData = new Dictionary<string, object>();
        skyDriveFolderData.Add("name", skyDriveFolderName);
        client.PostCompleted += new EventHandler<LiveOperationCompletedEventArgs>(CreateFolder_Completed);
        client.PostAsync("me/skydrive", skyDriveFolderData);
     }
     else
        UploadFile();
}
else
{
     MessageBox.Show(e.Error.Message);
}
}

REST will return “data” text value which holds information about SkyDrive root folder. Convert “data” information into collection of folders and iterate them to check if desired folder exists. In this case it is value of variable skyDriveFolderName.

 

private string skyDriveFolderName = "IsolatedStorageFolder";

If folder exists we will took its folderID value, because that value is needed to define upload folder in next steps. If folder does not exists, we have to create it using PostAsync method. When folder is created following method for handling CreateFolder_Completed event is executed and new folder ID value is assigned to skyDriveFolderID variable:

 

private void CreateFolder_Completed(object sender, LiveOperationCompletedEventArgs e)
{
    if (e.Error == null)
    {
        infoTextBlock.Text = "Folder created.";
        Dictionary<string, object> folder = (Dictionary<string, object>)e.Result;
        skyDriveFolderID = folder["id"].ToString();
        UploadFile();
    }
    else
    {
        MessageBox.Show(e.Error.Message);
    }
}

3) Upload image to SkyDrive’s "IsolatedStorageFolder" folder:

When we are sure that desired folder exists in user’s SkyDrive, last step is uploading file from Isolated Storage.

 

private void UploadFile()
        {
            if (skyDriveFolderID != string.Empty)
            {
                string[] filePathSegments = cameraRollFileName.Split(‘\\’);
                string fileName = filePathSegments[filePathSegments.Length – 1];
                var scopes = new List<string>(1);
                this.client.UploadCompleted
                    += new EventHandler<LiveOperationCompletedEventArgs>(ISFile_UploadCompleted);

                IsolatedStorageFileStream fileStream = null;
                try
                {
                    using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        fileStream = store.OpenFile(cameraRollFileName, FileMode.Open, FileAccess.Read);
                    }

                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message);
                }
                this.client.UploadAsync(skyDriveFolderID, cameraRollFileName, true, fileStream, null);
            }
        }

private void ISFile_UploadCompleted(object sender, LiveOperationCompletedEventArgs args)
{
    if (args.Error == null)
    {
        Dictionary<string, object> file = (Dictionary<string, object>)args.Result;
        // For some reason SkyDrive link property is not part of result.
        this.infoTextBlock.Text = "File uploaded.";
    }
    else
    {
        this.infoTextBlock.Text =
            "Error uploading file: " + args.Error.ToString();
    }
}

And this is it.

User is notified that file is uploaded:

image

 

If you check you SkyDrive account, new folder with image will be there:

image

 

Complete working zip solution can be downloaded from here (don’t forget to put your app client ID in MainPage.xaml).

You can download Live SDK Developer Preview from here.

  1. Henrik
    September 19, 2011 at 9:03 pm

    Hi,

    Nice article, thank you.

    I tried to run your solution on my WP7. I created client id and put it in the MainPage.xaml. When I press “Yes” on the allow access page, Visual Studio throws a web exception “Not Found” and I stay logged out.

    On the “My apps” page, I tried to set the “Mobile client app” to Yes,but that did not change anything.

    Any ideas? I’m running Mango build 7712.

  2. Luke
    September 21, 2011 at 9:42 pm

    Is it possible to upload WAV or MP3 file using Live Connect API?

    • September 27, 2011 at 3:32 pm

      Mp3 and wav are not supported file formats in Live Connect API (I don’t know why). However RAW format is supported. It is headerless waveform format like PCM, but if you add header data in it (like WAV header data) you can play it with any audio player.
      I suppose you want to save your WP7 microphone audio recordings to SkyDrive. Solution is to save microphone buffer data, add WAV header information, save it in Isolated Storage as RAW file, and then upload it to SkyDrive. I will try to do that in next few days, so I will write about my findings here on blog.

  3. September 26, 2011 at 6:01 am

    You have to get to this link to get to the Connect page: http://go.microsoft.com/fwlink/?LinkId=226223

  4. test
    October 18, 2011 at 7:19 am

    I am getting below error message, when i try to upload xml document. Any help on this is appreciated.

    {“The requested operation could not be completed. The provided file type is not supported. Only photos, videos and document file types are supported.”}

    • October 18, 2011 at 9:36 am

      XML format is currently not supported in Live Connect SkyDrive API (see CHM preliminary documentation, topic “SkyDrive core concepts”). Workaround is to change XML file type to TXT and upload TXT file instead of XML.
      Also, I suggest you to post message regarding your problem to Live Connect forums: http://dev.live.com/forums
      WAV format wasn’t also supported, but after few questions about that issue Live Connect development team added WAV to list of supporder formats few weeks ago.

  5. Misy
    October 20, 2011 at 8:11 am

    Anyone can provide sample on how to read file data from skydrive subfolder (MyDocuments/Document1.txt) ? That makes my life easy.

  6. Nine
    October 20, 2011 at 11:36 am

    Hi, Niko
    I just wrote a simple app using Live SDK JavaScript API for navigating my SkyDrive file system. It works ok.
    I saw you use ‘GetAsync(“me/skydrive/files?filter=folders,albums”);’ to get only folders and albums of items in your WP7, so I tried to use ‘WL.api({path: “me/skydrive/files?filter=folders,albums”}, callbackFn);’ in my codes, but it does not work.
    Also, I got an error message “The provided value for the input parameter ‘filter’ is not valid. A comma separated list of the following values is expected: ‘folders’, ‘albums’, ‘photos’, ‘videos’, ‘audio’.”
    But I am sure what I wrote is ‘folders’ and ‘albums’, or ‘folders,albums’.
    Is there any differences between using C# API and JavaScript API in this place?
    So I should write it in another way for using the filter parameter while coding with JavaScript?
    Thank you!

    • Nine
      October 21, 2011 at 5:51 am

      I’ve found the solution by myself🙂
      I should write ‘path: “FolderID/files”, method: “GET”, body: {filter: “folders,albums”}’
      thanks for the nice article anyway!

  7. Gonzo
    January 8, 2012 at 7:17 am

    is there a download example?😀

  8. January 8, 2012 at 3:29 pm
    • Gonzo
      January 11, 2012 at 1:18 pm

      hey nikovrdolj,
      i see my expression wasn’t convey clearly. i meant if there is a how-to download a file from skydrive =D
      i can’t determine the setting to GetAsync(string path, object userState) and i didn’t find any good documentation on that. have you any idea?
      (i dont want to download an image, but a created folder with files in it).
      hopefully you have an idea😀

  9. Hong
    June 19, 2012 at 4:03 am

    Thanks a lot for this excellent article! I believe RedirectUri has been removed for WP. I am wondering if the user can be kept signed in as long as the app is active. It is a nuisance that one has to go through the sign-in process every time he accesses the page requiring Live Connect.

  10. July 26, 2012 at 4:39 am

    Appreciation to my father who told me regarding this web site, this weblog is in
    fact awesome.

  11. dave
    September 27, 2012 at 6:52 am

    Cool article.

    It helped me more then SkyDrive forum

  12. October 16, 2012 at 8:00 pm

    I followed the code until section 3) User is prompt to okay scopes that your application needs. So After user prompt to login with live id and pass. Eventually I can’t log in completely. If I debug I can following information:-

    In function
    private void btnSignin_SessionChanged(object sender, LiveConnectSessionChangedEventArgs e)

    e.Error = {“The provided request must include a ‘client_secret’ input parameter, unless the app is configured as a mobile app. If you’re the client application developer and you’re creating a mobile app, you must configure it as one through the application management site at https://manage.dev.live.com/.”} System.Exception {Microsoft.Live.LiveAuthException}”

    e.Session is inactive.

    what is wrong with me. Please help me. Thanks in advnce

  13. Icarus
    January 4, 2013 at 11:36 am

    Thank you Niko. This was really helpful!
    Great article.

  14. Ing. Juan Mancilla
    January 4, 2013 at 8:51 pm
  15. January 16, 2013 at 10:34 pm

    I actually have a tendency to agree with every little thing that ended up being
    composed in “Backup your Windows Phone Isolated Storage data to SkyDrive
    using Live Connect API Niko Vrdoljak’s Blog”. Thanks a lot for all the facts.Thanks a lot,Frankie

  16. April 12, 2013 at 11:05 am

    Are you aware that your web site is coming up with errors in Opera?

    I needed to open up IE to finish reading. No big deal,
    but you might want to take a look at that. I’m positive it’s costing you a
    number of visitors.

  17. cuonv
    June 3, 2013 at 5:13 am

    Hi, thanks for your illustration very much! But I am wondering could you please tell me what can I do to keep signing in the SkyDrive? SInce every time I opened this app, I have to sign in or give authorization again and again….

    • August 15, 2013 at 6:49 pm

      If you want to automaticaly sign without entering username and password add “wl.signin” entry to Scopes property.

  18. suresh
    November 15, 2013 at 6:13 am

    can i backup my isolated data to my SD card or phone memory itself

    • November 15, 2013 at 8:37 am

      You can not backup to SD card since it is read-only accessible via storage API.

  19. March 4, 2014 at 12:41 pm

    Very descriptive post, I liked that bit. Will there be
    a part 2?

  20. April 7, 2014 at 2:44 am

    Excellent! That was wondertful🙂

  21. April 28, 2014 at 11:10 am

    Very nice post. I just stumbled upon your weblog and wished
    to say that I have really enjoyed surfing around your blog posts.
    After all I will be subscribing to your rss feed and I hope you write again soon!

  22. ozkar
    February 26, 2015 at 12:53 am

    the client.GetCompleted event don’t shoots

  1. September 16, 2011 at 10:17 am
  2. October 7, 2011 at 6:30 am
  3. November 9, 2011 at 5:31 am
  4. March 20, 2015 at 7:42 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: