Integrating your cloud service with the file picker contracts

In the past, users organized, shared, and maintained their documents, photos, videos, and music on the local PC. But the cloud is quickly providing users with much richer ways to access, experience, and manage the files they care about. Windows 8 embraces these new scenarios by allowing you to deeply integrate cloud services directly into your apps to create completely new experiences that were not possible before.

You can see many of these scenarios highlighted in the SkyDrive app which uses the file picker contracts. The file picker contracts are designed to make user’s documents, photos, videos, & music stored in your app available to all other Windows 8 apps. In this post, we use the SkyDrive app (which implements all three of the file picker contracts as introduced in Connecting your apps, files, PCs and devices to the cloud with SkyDrive and Windows 8) to show you:

  • What the file picker contracts are and how you can use them to bring a new set of experiences to your app
  • How to choose the right file picker contract(s) for your app
  • Tips and tricks for implementing the file picker contracts

File Open Picker support in the SkyDrive app

File Open Picker support in the SkyDrive app

Overview of file picker contracts

As the name suggests, the file picker contracts extend the file picker by allowing Windows 8 apps to provide files, save locations, and even file updates to all other Windows 8 apps. For example, you can see in the screenshot we just looked at that all of my files on SkyDrive are accessible right inside the file picker.

The file picker contracts consist of 3 independent contracts: File Open Picker, File Save Picker, Cached File Updater. You need to implement only those that make sense for your app. When thinking about which contracts to implement, use the following as a guide:

  • File Open Picker: Use when your app provides a unique and/or valuable view of files that are not easily accessible in another way. For example, the SkyDrive app implements this contract so it can provide all Windows 8 apps with access to files that are stored on its service.
  • File Save Picker: If your app supports the File Open Picker contract, use this contract when users would also expect to be able to save to your app as a location. For example, the SkyDrive app implements this contract so users can easily save to its service from any Windows 8 app. For some apps, you’ll need to decide whether to implement the File Save Picker or Share Target (or both) contracts for moving data to your app. The Sharing and exchanging data topic can help you make this decision.
  • Cached File Updater: Use this contract when your app also automatically tracks and updates files to keep them in sync with your app’s central repository. The SkyDrive app implements this contract so any file that is picked/saved to the SkyDrive app can easily be updated or refreshed without the user having to go through the file picker. For example, using my favorite photo app, I can open a picture on SkyDrive and any changes I make to that picture are automatically sent back to SkyDrive (without my having to go through the file picker).

It’s helpful to think of these contracts as a progression. For example, we recommend that Windows 8 apps implement the File Open Picker contract first and then determine if it makes sense to implement the File Save Picker contract and so on.

 

The progression of file picker contracts

The progression of file picker contracts

Now that you have an overview of the contracts, let’s dive into how each one can be implemented. To help illustrate the concepts, we’ll continue to use the SkyDrive app as an example.

Scenario 1: File Open Picker contract

The File Open Picker contract is the way users can use the files they store, create, and manage in your app in other Windows 8 apps. For example, by SkyDrive implementing the File Open Picker contract, I have access to all of my files on SkyDrive in every other Windows 8 app. From setting my account picture to opening a document on SkyDrive, all of my SkyDrive content is accessible no matter what I’m doing or what Windows 8 app I’m using!

When your app implements the contract, it can be launched and displayed within the open mode of the file picker. An entry point to your app is displayed within the file picker menu any time the user is picking a type of file your app provides:

File open picker

SkyDrive in the file picker menu

When it’s launched, your app is placed within the view area of the file picker and the file picker frame takes on the color scheme specified in your manifest:

skydrive_thailand

The SkyDrive app hosted within the file picker for the File Open Picker contract

Implementing the contract

You can incorporate the File Open Picker contract into your app by following the Quickstart. When your app has incorporated the contract, the next step is setting up your app to display files that the user can pick. You can use the built-in Visual Studio template to build your picking view after you add the File Open Picker contract to your manifest. Alternatively, if you’ve already built a view in your main app you can use that as a basis for your picking view. As shown next, SkyDrive reuses their existing view from their main app, which saved time and also provided consistency with the main app view.

skydrive_view1The SkyDrive app provides similar views and navigation models

The SkyDrive app provides similar views and navigation models
between their main and hosted versions of the app

Also, as the user will be selecting files in your app, it’s important that your app provides a selection mechanism. If you’re already using the built-in HTML ListView or XAML GridView controls, selection mechanics and visuals are already built into the controls.

Selection visual in the SkyDrive app

Selection visual in the SkyDrive app

After a user selects a file, you need to pass a StorageFile to the file picker so it can be displayed in the file picker basket. Based on your scenario, you can use a locally backed StorageFile or one that is URI or Stream-backed. URI and Stream-backed StorageFiles work best for files that are not located on the local machine because they allow the file download to be postponed until the app consuming the file accesses it. Choosing which one to use is dependent upon the implementation of your app—URI is a hands-off approach and Stream-backed allow you to configure how the file is downloaded when the file is accessed. For example, if the file was not publically accessible via a URI and required a form of authentication, the Stream-backed solution would allow the necessary credentials to be passed through. Here is a quick example of adding a URI-backed StorageFile to the file picker Basket:

JavaScript

 // Create thumbnail for the file
var thumbnailSource = Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(new Windows.Foundation.Uri(selectedItem.fileThumbnailUri));
// Add a file to the FileOpenPickerUI that is downloaded using BackgroundTransfer
Windows.Storage.StorageFile.createStreamedFileAsync(selectedItem.name, onDataRequested, thumbnailSource).done(function (streamedFile) {
   pickerUI.addFile(selectedItem.id, streamedFile);
});

function onDataRequested(outputStream) {
   var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
   var download = downloader.createDownload(new Windows.Foundation.Uri(selectedItem.fileUri), null);
   download.startAsync().done();
   var inputStream = download.getResultStreamAt(0);
   Windows.Storage.Streams.RandomAccessStream.copyAndCloseAsync(inputStream, outputStream).done(function () {
      inputStream.close();
   });
}

C#

 // Create thumbnail for the file
var thumbnailSource = RandomAccessStreamReference.CreateFromUri(new Uri(selectedItem.FileThumbnailUri));
// Add a file to the FileOpenPickerUI that is downloaded using BackgroundTransfer
StorageFile file = await StorageFile.CreateStreamedFileAsync(selectedItem.Name, OnDataRequested, thumbnailSource);
_openUI.AddFile(selectedItem.Id, file);

protected async void OnDataRequested(StreamedFileDataRequest outputStream)
{
   var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
   var download = downloader.CreateDownload(new Uri(_selectedItem.FileUri), null);
   var downloadTask = download.StartAsync();
   using (var inputStream = download.GetResultStreamAt(0))
   {
      await RandomAccessStream.CopyAndCloseAsync(inputStream, outputStream);
   }
   await downloadTask;
}

Building a picking user experience

An important part of subscribing to the File Open Picker contract is providing a picking experience that is tailored, focused on picking, and aligned to your main app design and personality. The Guidelines and checklist for file pickers outlines the key areas to focus on when designing this experience.

In terms of implementation, here are a few quick ways to easily align to the guidelines:

  • Commanding: As the app bar is not supported in the file picker, use the built-in command row provided in the Visual Studio template. Illustrated by #1 in the next diagram.
  • Navigation: Align your navigation model and affordances with what you already use in your main app. Also, ensure that you set the contents of the Title property in a way that is consistent with how you show the current location in your app. Illustrated by #2 in the diagram below.
  • Selection: As the file picker supports both single and multiple selection, use the SelectionMode property to determine if your app should allow the selection of multiple files. Illustrated by #3 in the diagram below.
  • View filtering: Use the AllowedFileTypesproperty to filter your view and show only the types of files the user can pick.
  • Launch: Use the SettingsIdentifier property to launch your app back to the location it was navigated to the last time the user picked from your app.
  • Authentication: If necessary, allow the user to log in to your app in a method consistent with your main app.
  • Organization: Organize and display files to optimize for browsing content. Use Semantic Zoom and lightweight filters instead of more heavyweight affordances (e.g. search) if possible.

User interface overview of the SkyDrive app implementing the File Open Picker contract

User interface overview of the SkyDrive app implementing the File Open Picker contract

End-to-end flow

To summarize, here is an overview of the end-to-end File Open Picker flow. In this diagram, the app implementing the File Open Picker contract (e.g. SkyDrive) is labeled the “Providing app.”

End-to-end File Open Picker flow

Scenario 2: File Save Picker contract

The File Save Picker contract allows your app to be a save location for Windows 8 apps. For example, by SkyDrive implementing the File Save Picker contract, I can save files directly to SkyDrive from any other Windows 8 app. This way I can add files to SkyDrive while staying in the app I’m currently using and also place files on SkyDrive that may not be accessible by the SkyDrive app itself (as SkyDrive may not have access to the location a particular app is using to store files).

As mentioned above, when thinking about implementing the File Save Picker contract, your app must already implement the File Open Picker contract, which ensures that the user can pick from the same locations they can save to.

After you incorporate the File Save Picker contract into your app, your app can be launched and displayed within the save mode of the file picker. An entry point to your app is displayed in the file picker menu any time the user is saving a type of file your app supports. Like the File Open Picker contract, your app is placed within the view area of the file picker when it is launched:

The SkyDrive app hosted within the file picker for the File Save Picker contract

The SkyDrive app hosted within the file picker for the File Save Picker contract

Implementing the contract

Because you already implemented the File Open Picker contract, implementing the File Save Picker contract is very familiar (they share the same Quickstart). The first step is setting up your app to display locations the user can save to. Reusing the existing view you built for the File Open Picker contract saves time and also provides consistency with your other app views. In fact, the easiest way to accomplish this is to just reuse your File Open Picker view and remove the Basket code.

skydrive_documents

The SkyDrive app using the same view as the main app for the File Save Picker

After the user saves the file (you’ll receive the TargetFileRequested event), validate the filename and extension (using the FileName property) to ensure it is valid for your app. If it is not, then you can present an error to the user consistent with the UX guidelines . If it is, you create a new StorageFile and hand it back to the file picker which then passes it to the app that writes the contents (i.e. the app the called the file picker). Here is a quick code snippet illustrating the concept:

JavaScript

 function onTargetFileRequested (e) {
   var request = e.request;
   var deferral = e.request.getDeferral();
   if (doesfileExist(saveUI.fileName)) {
      var dialog = new Windows.UI.Popups.MessageDialog("The location already has a file named " + saveUI.fileName + ".", "Replace the existing file?");
      dialog.commands.append(new Windows.UI.Popups.UICommand("Replace", function () {
         createFileAndFinishRequest(request, deferral)
      }));
      dialog.commands.append(new Windows.UI.Popups.UICommand("Cancel", function () {
         // Cancel save by setting targetFile to null
         request.targetFile = null;
         deferral.complete();
      }));
      dialog.showAsync().done();
   } else {
      createFileAndFinishRequest(request, deferral);
   }
}
function createFileAndFinishRequest(request, deferral) {
   _currentLocalFolder.createFileAsync(saveUI.fileName, Windows.Storage.CreationCollisionOption.replaceExisting).done(function (newFile) {
      // Return the empty placeholder file so the calling app can add the file contents
      request.targetFile = newFile;
      deferral.complete();
   });
}

C#

 async void OnTargetFileRequested(FileSavePickerUI sender, TargetFileRequestedEventArgs args)
{
   var request = args.Request;
   var deferral = request.GetDeferral();
   if (DoesFileExist(_saveUI.FileName))
   {
      var dialog = new MessageDialog("The location already has a file named " + _saveUI.FileName + ".", "Replace the existing file?");
      dialog.Commands.Add(new UICommand("Replace", (command) =>
      {
         CreateFileAndFinishRequest(request, deferral);
      }));
      dialog.Commands.Add(new UICommand("Cancel", (command) =>
      {
         request.TargetFile = null;
         deferral.Complete();
      }));
      await dialog.ShowAsync();
   }
   else
   {
      CreateFileAndFinishRequest(request, deferral);
   }
}
async void CreateFileAndFinishRequest(TargetFileRequest request, TargetFileRequestDeferral deferral)
{
   request.TargetFile = await _currentFolder.CreateFileAsync(_fileSavePickerUI.FileName, CreationCollisionOption.ReplaceExisting);
   deferral.Complete();
}

Building a saving user experience

Like the File Open Picker contract, an important part of subscribing to the File Save Picker contract is providing an experience that is tailored, focused, and aligned to your main app design and personality. Here are a few quick ways to align your File Save Picker contract implementations to the guidelines:

  • Filter view: If the user changes the file type in the file picker's file-type list (you receive a FileNameChanged event), update your view to display only files that match the selected file type. Illustrated by #1 in the next diagram.
  • Error handling: Ensure the filename, file type, and location the user is saving to are valid. If it is not, display an error and allow the user to fix the issue. Show the errors with the same style and personality as errors in your main app (that should already be following the error guidance). Illustrated by #2 in the next diagram.
  • Filename: Automatically populate the filename (via the TrySetFileName method) when a user selects a file in your save page. Illustrated by #3 in the next diagram.

UX overview of the SkyDrive app implementing the File Save Picker contract

UX overview of the SkyDrive app implementing the File Save Picker contract

End-to-end flow

To summarize, here is an overview of the end-to-end File Save Picker flow. Similar to the File Open Picker diagram, the app implementing the file picker contract (e.g. SkyDrive) is labeled the “Providing app.”

Overview of the end-to-end File Save Picker flow

Scenario 3: Cached File Updater contract

The Cached File Updater contract is the way your app can keep the files you maintain up-to-date when they are updated by other Windows 8 apps. What does this mean? Let’s look again at the SkyDrive app. By SkyDrive implementing the Cached File Updater contract, it can ensure that any file I’m using (that lives on SkyDrive) is kept up-to-date and any changes I make are uploaded to SkyDrive. Let’s say I’m using my favorite photo editing app and I want to remove the red-eye from a picture I have stored on SkyDrive. In the photo editing app, I open the file picker and pick a photo from the SkyDrive app. I remove the red-eye and the photo editing app saves my changes. Through the Cached File Updater contract, those changes are automatically sent back to SkyDrive. In fact, any additional updates I make to that file will continue to be sent to SkyDrive for the lifetime of that file. I never have to manually export or upload my changes to SkyDrive—the Cached File Updater contract allows files on SkyDrive to be like files on my local PC where I always have the latest copy and can update it at any time.

This contract is specifically targeted for apps that act as a primary storage location where users regularly save and access files. For most apps, you don’t need the Cached File Updater contract. This contract requires a significant amount of state management, handling of complex data flows, conflict resolution, and UI work to enable so implementation is not trivial. If contracts had a rating, this one would be advanced.

After you incorporate the contract, your app is activated (but not necessarily displayed to the user) each time a file you maintain needs to be refreshed or updated. Your app can be activated at any time for this purpose, but all app activations are driven by the system and not the user directly. For example, if the user saves data to a file that your app services, the system activates your app so you can handle it appropriately (e.g. upload the changes to your cloud service).

Implementing the contract

You can start the implementation of the Cached File Updater contract by following the Quickstart. After your app implements the contract, it will automatically be activated to handle changes in files that you service.

You need to let the system know which StorageFiles you maintain. Using the setUpdateInformation method, you can set read/write permissions and control how and when your app is activated for servicing the file. In general, it’s best to set this info on any file the user picks from your app using the File Open Picker contract or saved to your app using the File Save Picker contract. You can find C#, C++, and JavaScript code for supporting the Cached File Updater contract in our File Picker Contracts SDK sample.

Also, when implementing the Cached File Updater contract, you might need to prompt the user to provide credentials or to handle a version conflict before you can service the file. For these cases, you can let the system know that UI is required and your app will be launched within the file picker.

skydrive_creds

The SkyDrive app asking for credentials during a Cached File Updater operation

In addition to the options your app sets, the app requesting an update or saving the file can control part of the Cached File Updater contract flow . Specifically, the calling app may block your app from showing UI in some cases. This choice isn’t bubbled up to your app, the call simply fails if the calling app wants to refresh or save a file and your app needs to show UI to complete the request.

Throughout the process, you can use the UIStatusenumeration to know which step you’re processing.

Building a refresh and save user experience

Although the UI portion of the Cached File Updater contract is limited, make sure your app aligns to the guidelines:

  • Showing UI: Request UI only in cases where user intervention (credentials, file conflicts, etc.) is absolutely required. Return failure cases to the calling app which will let the user know the refresh or save was not successful. In addition, show informational messages (e.g. “File saved successfully”) only in your main app (if necessary) the next time it is launched and not in the file picker UI or other UI surfaces (e.g. toasts).
  • Status: If your app handles a large number of refreshes and saves, consider showing progress for each task in the UI of your main app. This way users can track progress and resolve issues.

End-to-end flow

To summarize, here is an overview of the end-to-end Cached File Updater flow. Similar to the previous diagrams, the app implementing the file picker contract (e.g. SkyDrive) is labeled the “Providing app.”

end-to-end cahced file updater

In closing

In this post, I introduced you to the file picker contracts and showed how you can use them to make your app light-up new experiences in Windows 8. The File Open Picker contract provides a great starting point which allows users to use the files they store, create, and manage in your app in other Windows 8 apps. As your app provides more advanced functionality, the File Save Picker and Cached File Updater contracts provide a progression that allows your app to be part of more Windows 8 scenarios.

Here are a couple of key things to remember:

  • The file picker contracts are designed to be a progression. Start with the File Open Picker contract, then move to the File Save Picker and then the Cached File Updater contracts if desired.
  • Let your app’s personality shine through! Users will be familiar with using the normal version of your app so make sure to bring the personality, look and feel, and navigational affordances to the version hosted within the file picker.
  • Follow the UX guidelines which allow your app to show off its personality while also using all of the affordances provided by the file picker. This way users have a consistent, first-class experience when using your app in the file picker.

To learn more about the file picker contracts in Windows 8, you can follow these links or ask questions in our forums.

Link

Type

Highlights

Guidelines and checklist for file picker contracts

UX guidelines

Guidelines for implementing the file picker contracts

Quickstart: Integrating with file picker contracts

Quickstart

Explains how to incorporate the file picker contracts into your app

Windows.Storage.Pickers.Provider

API reference

Reference documentation for File Open Picker and File Save Picker contracts

Windows.Storage.Provider namespace

API reference

Reference documentation for Cached File Updater contract

File picker contracts

Code sample

Demonstrates usage of File Open Picker, File Save Picker, and Cached File Updater contracts

Thanks,

--Scott Hoogerwerf, Senior Program Manager, Windows User Experience

Contributions by: Derek Gebhard