How to support pull operations (HTML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

Most of the time, the app supplies the share data immediately from its datarequested event handler. Sometimes, however, your app may need time to get the data ready for sharing. At those times, you can provide a list of supported formats, but delay preparing and providing the content until the target app requests it. Deferring to provide content until the target app requests it is called a pull operation (or delayed sharing).

To support pull operations, you first create a function that packages the data that the user wants to share. Then, instead of supplying the actual data to the target app, you supply a delegate function. When the target app tries to get the data, the system calls your delegate function. The advantage here is that your app can share the data behind the scenes, allowing the user to continue using your app for other activities.

What you need to know

Technologies

Prerequisites

  • You should be familiar with Visual Studio and its associated templates.
  • You should be familiar with JavaScript.
  • You should understand how to get files and other data, such as by using FileOpenPicker. You can learn more in Accessing files with file pickers.

Instructions

Step 1: Create a button handler function to let the user choose an image file

The following button handler code lets the user to pick an image file. This file is used in the remaining steps of this quickstart.

Note  

The following code uses pickSingleFileAsync. On Windows Phone 8.1, pickSingleFileAndContinue should be used instead.

var imageFile = null;
function pickImageFile() {
    var picker = new Windows.Storage.Pickers.FileOpenPicker();
    picker.fileTypeFilter.replaceAll([".jpg", ".bmp", ".gif", ".png"]);
    picker.pickSingleFileAsync().done(function (file) {
        imageFile = file;
    });
}

Step 2: Create a delegate function to provide the content that the user wants to share.

The exact nature of the delegate function depends on your app. Here's one example.

function onDeferredImageRequested(request) {
    if (imageFile) {
        var imageStreamRef = Windows.Storage.Streams.RandomAccessStreamReference.createFromFile(imageFile);
        request.setData(imageStreamRef);
    }
}

Notice that the delegate function uses setData to add the content, instead of a format-specific function, like setBitmap or setStorageItems. Any time you use a delegate function, you must use setData to supply the content.

Step 3: Set up your app as a share source

The DataTransferManager object is the main starting point for any share operation. Add a DataRequested event handler to fire when the user wants to invoke Share. In a Windows Store app, this occurs automatically when the user invokes the Share charm. If you're developing for Windows Phone, there is no built-in Share charm, so you'll need to add a control for the user to tap and trigger the handler.

var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
dataTransferManager.addEventListener("datarequested", sharePullHandler);

The remaining steps are for implementing the sharePullHandler function.

Step 4: Get a DataRequest object

When a datarequested event occurs, your app receives a DataRequest object. This object contains a DataPackage that you'd typically use to provide the content that the user wants to share. In pull operations, however, you specify a delegate function instead of the actual data.

var request = e.request;

Step 5: Set the title and description properties

request.data.properties.title = "Share Pull Example";
request.data.properties.description = "Demonstrates how to pull operations in share.";

Step 6: Set the file types, if needed.

If you're using a delegate function to share files, you need to specify the file types that your app supports.

request.data.properties.fileTypes.replaceAll([".jpg", ".bmp", ".gif", ".png"]);

Step 7: Add the delegate function to the DataPackage object

The setDataProvider method specifies the delegate function that you created to supply the actual content.

request.data.setDataProvider(Windows.ApplicationModel.DataTransfer.StandardDataFormats.bitmap, onDeferredImageRequested);

At this point, when the user taps the Share charm, the app can respond instantly with a DataPackage object containing the delegate function. The share operation can now continue behind the scenes, freeing the user to continue with whatever other activities they want to do.

Keep in mind that if you're using the setStorageItems method to share files, this method creates read-only StorageFile objects for sharing and holds onto the original objects. This means that if you add expanded properties to the original file after you call setStorageItems, those new expanded properties won't be included in the StorageFile objects being shared. That's why we recommend you don't add the files until you're completely ready.

Remarks

A that shares data using delayed rendering should be a single-page app to avoid navigation between pages. Also, if your app supports navigation within frames, it should use the top-level script context to register delegate functions instead of registering delegates at a frame level. Navigation causes the script context to be lost, which invalidates the delegate functions and causes delayed rendering to fail.

Complete example

var imageFile = null;
function pickImageFile() {
    var picker = new Windows.Storage.Pickers.FileOpenPicker();
    picker.fileTypeFilter.replaceAll([".jpg", ".bmp", ".gif", ".png"]);
    picker.pickSingleFileAsync().done(function (file) {
        imageFile = file;
    });
}

function onDeferredImageRequested(request) {
    if (imageFile) {
        var imageStreamRef = Windows.Storage.Streams.RandomAccessStreamReference.createFromFile(imageFile);
        request.setData(imageStreamRef);
    }
}

function sharePullHandler(e) {
    var request = e.request;
    request.data.properties.title = "Share Pull Example";
    request.data.properties.description = "Demonstrates how to support pull operations in share.";
    request.data.properties.fileTypes.replaceAll([".jpg", ".bmp", ".gif", ".png"]);
    request.data.setDataProvider(Windows.ApplicationModel.DataTransfer.StandardDataFormats.bitmap, onDeferredImageRequested);
}

app.onactivated = function (args) {
    if (args.detail.kind === activation.ActivationKind.launch) {
        if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
            // This app is newly launched; register it as a share source.
            var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
            dataTransferManager.addEventListener("datarequested", sharePullHandler);
            // Set up the button handler to pick an image file.
            document.getElementById("chooseImageButton").addEventListener("click", pickImageFile, false);
        } else {
            // TODO: This app was reactivated from suspension.
            // Restore the app state here.
        }
        args.setPromise(WinJS.UI.processAll());
    }
};

Sharing content source app sample

Sharing and exchanging data

How to produce requested data asynchronously

Quickstart: Sharing content

DataPackage

Windows.ApplicationModel.DataTransfer

Windows.ApplicationModel.DataTransfer.Share