Windows 8 Consumer Preview and Visual Studio 11 Beta – Data Sharing (Part 3/11)

February 29, 2012

Windows 8 enables data exchange between applications. This was possible in the past, but to make it happen two applications must have knowledge about each other which was always not possible especially for applications developed by different companies. Windows 8 enables easy data sharing between the application by introducing OS-level sharing mechanism. Metro applications can publish information from certain types (“Share Source” applications) from one hand, operation system is responsible of selecting applications which expressed “interest” in some specific type of info and those applications (“Share Target”) are responsible of processing data received upon activation.


In this post I will show how to share textual and image information from my sample application. When working on this sample I discovered that since my tablet is empty from other applications, I have no share target applications.


image


To work around this problem I wrote simple “Share Target” application which accepts all possible share types and simply presents them.


image


Let’s see how to build simple Sharing Target first.


When application is launched from start screen, it will present static EmptyPage without any real functionality:


image


This done by redirecting application’s root frame to this page:

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    // Create a Frame to act navigation context and navigate to the first page
    var rootFrame = new Frame();
    rootFrame.Navigate(typeof(EmptyPage));
    // Place the frame in the current Window and ensure that it is active
    Window.Current.Content = rootFrame;
    Window.Current.Activate();
}

When application is launched in “Share Target” mode I redirected control over the process to different page, which process the data and present it:

protected override async void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
    SharePage shareTargetPage = new SharePage();
    await shareTargetPage.ActivateAsync(args);
}

To enable sharing functionality application must declare supported share contracts:


image


Note: application must either declare supported format (from known or user-defined types) or support “any” file type.


Also, in application settings specify executable file and entry point:


image


The application code looks pretty simple and self-describing:

ShareOperation shareOperation = null;
const string dataFormatName = “Valentine-Love-Catcher“;
//…
//—————————————————————–
public async Task ActivateAsync(ShareTargetActivatedEventArgs args)
{
    //If application activated in Share Target mode process further
    if (args.Kind == ActivationKind.ShareTarget)
    {
        //Get share operation object from event args
        shareOperation = args.ShareOperation;
        //Fill UI fields with data
        txtTitle.Text = shareOperation.Data.Properties.Title;
        txtDesc.Text = shareOperation.Data.Properties.Description;
        if (!String.IsNullOrEmpty(shareOperation.QuickLinkId))
            txtLinkID.Text = shareOperation.QuickLinkId;
        else
            stkLink.Visibility = Visibility.Collapsed;
        if (shareOperation.Data.Contains(StandardDataFormats.Uri))
        {
            Uri uri = await shareOperation.Data.GetUriAsync();
            if (uri != null)
                txtURI.Text = uri.AbsoluteUri;
        }
        else
            stkURI.Visibility = Visibility.Collapsed;
        if (shareOperation.Data.Contains(StandardDataFormats.Text))
        {
            string text = await this.shareOperation.Data.GetTextAsync();
            if (text != null)
                txtText.Text = text;
        }
        else
            stkText.Visibility = Visibility.Collapsed;
        if (shareOperation.Data.Contains(StandardDataFormats.StorageItems))
        {
            IReadOnlyList<IStorageItem> storageItems = null;
            storageItems = await this.shareOperation.Data.GetStorageItemsAsync();
            string fileList = String.Empty;
            for (int index = 0; index < storageItems.Count; index++)
            {
                fileList += storageItems[index].Name;
                if (index < storageItems.Count – 1)
                    fileList += “, “;
            }
            txtFiles.Text = “StorageItems: ” + fileList;
        }
        else
            stkFiles.Visibility = Visibility.Collapsed;
        if (shareOperation.Data.Contains(dataFormatName))
        {
            string receivedStrings = await shareOperation.Data.GetTextAsync(dataFormatName);
            JsonObject customObject = null;
            if (JsonObject.TryParse(receivedStrings, out customObject))
            {
                if (customObject.ContainsKey(“type“))
                {
                    if (customObject[“type“].GetString() == “http://schema.org/LoveVibe“)
                    {
                        // This sample expects the custom format to be of type http://schema.org/LoveVibe
                        receivedStrings = “Type: ” + customObject[“type“].Stringify();
                        JsonObject properties = customObject[“properties“].GetObject();
                        receivedStrings += Environment.NewLine + “Name: ” + properties[“name“].Stringify()
                                        + Environment.NewLine + “Soulmate: ” + properties[“soulmate“].Stringify()
                                        + Environment.NewLine + “Image: ” + properties[“image“].Stringify();
                    }
                }
            }
            txtCustomData.Text = receivedStrings;
        }
        else
            stkCustomFormat.Visibility = Visibility.Collapsed;
        if (shareOperation.Data.Contains(StandardDataFormats.Html))
        {
            string htmlFormat = await this.shareOperation.Data.GetHtmlFormatAsync();
            string htmlFragment = HtmlFormatHelper.GetStaticFragment(htmlFormat);
            webView.NavigateToString(“<html><body>” + htmlFragment + “</body></html>“);
        }
        else
            webView.Visibility = Visibility.Collapsed;
        if (this.shareOperation.Data.Contains(StandardDataFormats.Bitmap))
        {
            IRandomAccessStreamReference imageReceived = await this.shareOperation.Data.GetBitmapAsync();
            IRandomAccessStreamWithContentType stream = await imageReceived.OpenReadAsync();
            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.SetSource(stream);
            imageHolder.Source = bitmapImage;
        }
        else
            imageHolder.Visibility = Visibility.Visible;
    }
    //Activate the window
    Window.Current.Content = this;
    Window.Current.Activate();
}
private void ReportComplete(object sender, RoutedEventArgs e)
{
    shareOperation.ReportStarted();
    //Simulate some sharing process. Different report types supported here, but at the end of the process application must report completed operation
    //…
    shareOperation.ReportCompleted();
}

Sharing simple text from Sharing Source application:


image


Full application source can be downloaded from here.


Now let’s get back to “Share Source”. User initiates sharing process by selecting “Share” charm from right-swipe menu:


image


If application supports sharing it must initialize DataTransferManager class as soon as sharing from application enabled:

public void InitializeShareSource()
{
    DataTransferManager datatransferManager;
    datatransferManager = DataTransferManager.GetForCurrentView();
    datatransferManager.DataRequested +=
            new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(OnDataRequested);
}

From now on application handles data requests by invoking the OnDataRequested function:

private async void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
    //Fill basic properties
    args.Request.Data.Properties.Title = “Valentine Love Catcher“;
    args.Request.Data.Properties.Description = “Spread the word about this lovely application“;
    args.Request.Data.Properties.Thumbnail =
            RandomAccessStreamReference.CreateFromUri(new Uri(“ms-appx:///Images/Love.png“));
    //Share bitmap image
    args.Request.Data.SetBitmap(RandomAccessStreamReference.CreateFromUri(new Uri(“ms-appx:///Images/Girl_1.png“)));
    //Share simple text
    args.Request.Data.SetText(“Just found my true soulmate!“);
    //Share multiple files from device’s storage
    List<StorageFile> items = new List<StorageFile>();
    StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(“ms-appx:///Images/Bouquet.png“));
    items.Add(file);
    file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(“ms-appx:///Images/NewYear.png“));
    items.Add(file);
    args.Request.Data.SetStorageItems(items);
}

Code snippet above shares bitmap image, text and list of files from storage.


Note: Each share target app handles shred information differently. In some case not all information is used by shared target.


In some cases application provides UI to start sharing process (instead of scenario when user initiates it by selecting share charm). To support this scenario DataTransferManager class provides special method which opens share UI:

//Force showing share UI
DataTransferManager.ShowShareUI();In some advanced scenarios, application cares about target application (for example share or not share some specific data with some specific apps). To handle this scenario DataTransferManager enables subscribing to TargetApplicationChosen event:
//If application makes distinction between target applications, subscribe to this event
datatransferManager.TargetApplicationChosen += datatransferManager_TargetApplicationChosen;
//…
void datatransferManager_TargetApplicationChosen(DataTransferManager sender, TargetApplicationChosenEventArgs args)
{
    //Application logic based of selected target application. Find select target application name in args.ApplicationName
    //…
}

Pretty simple, yet very powerful and opens many interesting scenarios.






That’s all I have to say about that © Forrest Gump

Win8 made sharing really simple…


Stay tuned to next part.


Alex

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

3 comments

  1. hannes preishuberApril 24, 2012 ב 20:16

    Hi Alex
    did the image loading in share dialog worked for you?
    I tried it with image and thumbnail for png and jpg and get no image

    Reply
  2. Alex GoleshMay 13, 2012 ב 17:59

    Hi Hannes,

    Yes it works. Will be glad to follow up offline 🙂

    PLS ping my by mail.

    //Alex

    Reply
  3. Ryan WatsonJune 27, 2012 ב 17:17

    I am just a beginner in programming i like the blog very much. Can you tell me any best silver light online tutorials.

    Reply