Users share a variety of information when they're online. Successful apps take the time to analyze the types of information that users are most likely to share with others, and package that information so that the receiving apps can process it correctly. In many cases, the information users want to share falls into one of the six standard formats that Windows supports. However, there are many instances in which having a more targeted data type can create a better user experience. For these situations, your app can support custom data formats.
Why custom formats?
The share feature in Windows 8 supports six standard data formats:
- text
- HTML
- bitmap
- StorageItems
- URI
- RTF
These formats are very versatile, which makes it easy for your app to quickly support sharing and receiving shared content. The drawback to these formats is that they don't always provide a rich description of the data for the receiving app. To illustrate this, consider the following string, which represents a postal address:
1234 Main Street, New York, NY 98208
An app can share this string using DataPackage.setText. But because the app that receives the text string won't know exactly what the string represents, it is limited in what it can do with that data. By using a custom data format, the source app can define the data being shared as a "place" using the http://schema.org/Place format. This gives the receiving app some additional information that it can use to process the information in way the user expects. Using existing schema formats allows your app to hook into a larger database of defined formats.
Custom formats can also help you provide more efficient ways of sharing data. For example, a user has a collection of photos stored on Microsoft SkyDrive, and decides to share some of them on a social network. This scenario is tricky to implement using the standard formats, for a few reasons:
- You can only use the Uniform Resource Identifier (URI) format to share one item at a time.
- SkyDrive shares collections as stream-backed StorageItems. Using StorageItems in this scenario would require that your app download each picture, and then share them.
- Text and HTML let you provide a list of links, but the meaning of those links is lost—the receiving app won't know that these links represent the pictures the user wants to share.
Using an existing schema format or a custom format to share these pictures provides two main benefits:
- Your app can share the pictures faster, because you could create a collection of URIs, instead of downloading all the images locally.
- The receiving app would understand that these URIs represent images, and could process them accordingly.
Defining a custom format
If you decide that your app can benefit from defining a custom format, there are a few things you should consider:
- Be sure you understand the standard data formats, so you don't create a custom format unnecessarily. You should check to see if there is an existing format on http://www.schema.org that would suit your scenario. It is more likely that another app would use an existing format over your custom format, which means that a greater audience could achieve your desired end-to-end scenarios.
- Consider the experiences you want to enable. It's important that you think about what actions your users want to take, and what data format best supports those actions.
- Don't rely on format combinations. For example, don't expect an app to understand that if sees one format, it should also look for a second format. Each format must be self-contained.
- If you create your own custom format, make the definition of that format available to other app developers.
- After you publish a custom format, don't change it. Consider it like an API: elements might get added or deprecated, but backward-compatibility and long-term support are important.
- When naming your format, make sure the name matches the contents of the format. For example,
UriCollectionindicates that any URI is valid, whileWebImageCollectionindicates that it contains only URIs that point to online images. - Carefully consider the meaning of the format. Have a clear understanding of what the format represents and how it should be used.
- Review the structure of the format. Think through whether the format supports multiple items or serialization, and what limitations the format has.
Choosing a data type
One of the most important decisions you’ll make when defining a custom format is the WinRT data type used for transferring it between source and target applications. The DataPackage class supports several data types for a custom format:
- Any scalar type (integer, string, DateTime, and so on) through IPropertyValue.
- IRandomAccessStream
- IRandomAccessStreamReference
- IUri
- IStorageItem
- A homogenous collection of any of the above items
When defining a format, select the type appropriate for that data. It is very important that all consumers and recipients of this format use the same data type—even if there are different options—otherwise it may lead to unexpected data type mismatch failures in target applications.
If you choose string as the data type for your format, you can retrieve it on the target side using the GetTextAsync(formatId) form of the GetTextAsync function. This function performs data-type checking for you. Otherwise, you have to use GetDataAsync, which means you must protect against potential data-type mismatches. For example, if a source application provides a single URI, and the target attempts to retrieve it as a collection of URIs, a mismatch occurs. To help prevent these collisions, you can add code similar to this:
Populating the DataPackage
System.Uri[] uris = new System.Uri[2]; uris[0] = new System.Uri("http://www.msn.com"); uris[1] = new System.Uri("http://www.microsoft.com"); DataPackage dp = new DataPackage(); dp.SetData("UriCollection", uris);
Retrieving the data
if (dpView.Contains("UriCollection")) { System.Uri[] retUris = await dpView.GetDataAsync("UriCollection") as System.Uri[]; if (retUris != null) { // Retrieved Uri collection from DataPackageView } }
Custom format example: WebFileItems
To better illustrate how to think about creating a custom format, consider the following example: WebFileItems.
At the fictional company, Fabrikam, a developer writes an app that shares files stored online. One option would be to use stream-backed StorageItems, but that could be time-consuming and inefficient because the target app would end up downloading the files locally to read them. Instead, the developer decides to create a custom format for use with these file types.
First, the developer considers the definition of the new format. In this case, it's a collection of any file type (document, image, and so on) that is stored online. Because the files are on the web instead of the local machine, the developer decides to name the format WebFileItems.
Next, the developer needs to decide on the specifics of the format, and decides on the following:
- The format should consist of an IPropertyValue that contains an InspectableArray that represents the URIs.
- The format must contain at least 1 item, but there is no limit as to how many items it can contain.
- Any valid URI is allowed.
- URIs that are not accessible outside of the source application's boundary (such as authenticated URIs) are discouraged.
With this information mapped out, the developer now has enough information to create and use a custom format.
Adding custom formats to your app
After you define a custom format, use these tips for adding the format to your app:
- Test the format with other apps. Make sure that the data is processed correctly from the source app to the target app.
- Stick to the intended purpose of the format. Don't use it in unintended ways.
- If you're writing a source app, provide at least one standard format as well. This ensures that users can share data with apps that don't support the custom format. The experience may not be as ideal for the user, but it is better than not letting them share data with the apps they want. You should also document your format online so that other applications can know to adopt it.
- If you're writing a target app, consider supporting at least one standard format. This way, your app can receive data from source apps—even if they don't use the custom format you prefer.
- If you want to accept a specific custom format from another app, particularly one from a different company, you should double-check to see that it is documented publicly online. Undocumented formats are more likely to change without notice, potentially creating inconsistencies or breaking your app.
Build date: 12/5/2012