Ways You can Leverage Share Contracts in your Windows Store Game

9/18/2012 9:35:48 AM

For more detailed information and examples, see Adding share (Metro style apps using JavaScript and HTML) article and the two share sample applications, Share Source and Share Target.  Make sure you take advantage of 30 Days.

 

One of the great new features available to developers creating Windows Store games is the Share Contract. The Share Contract, or sharing, provides an easy way for you to share data from your game to other applications the user has on their system.

Why is sharing useful? Games are, by their nature, social. Perhaps you are starting to play a game of Ultimate Zombie Battles and you want to let your friends know you are playing so they can come join you. You may want to let the world know that you just achieved a personal high score on Find the Chicken. Or better yet, you just downloaded a new game and you think it is so cool, you want to let your friend and family know about it so they can play it too.

As a game developer, you want to enable all these scenarios. It provides a great Windows 8 gaming experience, differentiates your game from those that don’t share, and it can create more awareness about your game. Ideally, you want to enable these scenarios because they are features your user wants and makes your game that much more enjoyable.

The Basics

sharebrokerLet’s start off by gaining a basic understanding of how sharing works and the steps required for an app to share data. Later, we will look at some specific scenarios, like those mentioned above, and how you would implement them in your game.  Fundamentally, sharing is a very simple operation. A share operation consists of three parts: the source application that is sharing some data, the data to be transferred via the share broker, and the target application that will receive and process the data. The share broker is provided by Windows 8 and mediates the data exchange between the source and target apps. The picture to the right shows how this process works.

The code below shows how an application that is a share source would provide data to be shared.

 

var share = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
share.ondatarequested = function (e) {
// Title of Share Options
e.request.data.properties.title = "New High Score";
 
// Description of what is being shared
e.request.data.properties.description = "You Scored 1,000pts";
 
// Share plain text
e.request.data.setText("Bob’s New High Score is 1,000pts in Zombie Battles");
};

sharepaneYou should always set the title and description properties. These properties provide context to the user when they are looking at the Share UI and give them confidence in what they are about to share. You can set a variety of different data types to share. In the example code, we are only sharing simple text data via the setText() function. You could however, share multiple data types in a single share request, and you are encouraged to do so.

In addition to sharing text, HTML, and images, there are a variety of other formats you can share, including custom data formats. The supported formatted are listed below:

  • Plain Text
  • Formatted text
  • URIs
  • HTML
  • Images
  • Files
  • Custom data formats

By providing multiple data types, you expand the total number of target applications the user can share your application’s data with, and you allow the target application to choose which data type it can use the best. For instance, if a target app can understand both text and HTML, it would likely prefer to use the HTML data format since it provides for more engaging way to display text.

Sharing Different Data Formats

When sharing a high score, we may want to provide something more engaging than a simple text string. You can craft a share request to use a variety of formats to provide a much nicer experience. In addition to text, you could provide HTML. This would allow the user to send the high score via email, share the high score image on a social network, etc. The variety of formats provides a richer experience for your users. Our share source example could be updated as shown:

 

   1:  var share = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
   2:   
   3:  share.ondatarequested = function (e) {
   4:   
   5:  e.request.data.properties.title = "New High Score";
   6:  e.request.data.properties.description = "You Scored 1,000pts";
   7:  e.request.data.setText("Bob set a New High Score of 1,000pts is Zombie Battles");
   8:   
   9:  var HTMLstr = "<b>Bob</b> <h3>New High Score</h3> is 1,000pts in <i>Zombie Battles</i>";
  10:   
  11:  // Format HTML 
  12:  e.request.data.setHTMLFormat(
  13:       Windows.ApplicationModel.DataTransfer.HTMLFormatHelper.createHTMLFormat(HTMLstr));
  14:  };

Notice, in the setHTMLFormat() function the need to call createHTMLFormat(). This prepares the HTML for use by the target application, and failure to call this on an HTML string will result in the target app not being able to display the transferred HTML.

Text and HTML are nice, but pictures are worth a thousand words. Sharing an image can add additional pizazz to your game’s share operation. Imagine your game is based on the player advancing from one level of difficulty to another. You may want to have an image, or a badge, that can be shared to show the player’s success. You have placed these badge images into your project just like any other asset so you can easily display them in an <img> tag on screen when congratulating your user. But how do you share an image that is part of your game’s install package with another application?

There are two ways to approach this. The first is that you just want to share the image itself. The second is you want to take some HTML that is being displayed onscreen, including the badge image, and turn that into your share payload.

In the first scenario, all we need to do is acquire a stream to the image file and hand that stream to the share target application. Here is how you do that:

 

var deferral = e.request.getDeferral();
 
var imageUri = new Windows.Foundation.Uri('ms-appx:///images/highscore.png');
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(imageUri).then(function (imageFile) {
 
var streamReference = Windows.Storage.Streams.RandomAccessStreamReference.createFromFile(imageFile);
 
request.data.properties.thumbnail = streamReference;
request.data.setStorageItems([imageFile]);
request.data.setBitmap(streamReference);
 
deferral.complete();

Going through this code, there are few things worth pointing out. First, since we will be performing an asynchronous call, it is a good idea to grab a deferral from the DataTranferManager request. This lets the DTM know that we are doing something that could take a while. In our case, we could probably skip this since we are making a relatively quick call to local assets, If you had a longer running process it is a good thing to do.

highscoreNext, notice how we craft the Uri to the local image. We prefix the file path with “ms-appx://”, letting WinRT know that we are accessing a local resource. We turn that into an Uri, and then use the getFileFromApplicationUriAsync() call to obtain the file itself, which we then turn into a stream. Since we are passing an image, it is a good idea to a) set the thumbnail property for apps that would like to use a thumbnail, and pass the stream reference via setStorageItems(). We do this because some apps will want to deal with images files as streams instead of actual bitmaps, thus giving our use a wider range of applications they can share with and more flexibility for the target app when working with our share payload.

Now, let’s handle sharing parts of our UX. You have crafted a nice “reward page” showing someone that they have achieved a new level, set a new high score, whatever. Inside that page is some HTML like the following:

<div id="HTMLFragment" class="HTMLFragment" style="margin-top: 20px;">
 
<h2>Top Score of the Day</h2>
 
<img id="fragmentImage" src="/images/highscore.png">
 
<p>Congratulations!</p>
 
</div>

This example is admittedly simple, but it has all the elements we need to demonstrate the technique. The important thing to realize is that we are including an <img> that’s src property is set to a local image file. We process the HTML for sharing like this:

var request = e.request;
var range = document.createRange();
var fragment = document.getElementById("HTMLFragment");
range.selectNode(fragment);
 
request.data = MSApp.createDataPackage(range);
request.data.properties.title = "Share Text Example";
request.data.properties.description = "Demo shows how to share text string";
 
var path = document.getElementById("fragmentImage").getAttribute("src");
var imageUri = new Windows.Foundation.Uri(path);
 
var streamReference = Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(imageUri);
 
request.data.resourceMap[path] = streamReference;

Start by creating a range and selecting the HTML root element we want to send via our share operation. We convert that HTML into a fragment. There are img tags that need to have actual image files included in the payload so the fragment will render correctly. We grab the src Uri and create a stream reference that is passed as part of the resourceMap. The resource map will allow the target app to find the actual image and render it properly. In our example, there is a single image. If you have more than one image, you will need to find all the images in the fragment and repeat this process for each one.

Invoking Share

You will need to decide how you want to expose the opportunity to share information to your player. Over time, users will become accustomed to sharing data by swiping from the right edge of the screen to invoke the Charm bar, by hovering the mouse in the top-right corner, or pressing Windows Key+C . At times, however, it may not be obvious in your game that there is content that can be shared, or perhaps you want to emphasize that a particular item can be shared.

You can invoke the Share UI at any time from within your application via:

Windows.ApplicationModel.DataTransfer.DataTransferManager.showShareUI();

Being a Share Target

It is a less likely, given the highly specialized nature of a game, that you will need to be a share target. There are scenarios when being a share target makes sense. An example would be a game that also has a companion app, like a game map designer, a character designer, or something similar. In cases like that, you may want have your game to be a share target.

declarationsTo become a share target, the first thing you must do is declare that capability in your game’s package.appxmanifest file. Double-clicking on that file in Solution Explorer will open an editor. Click on the Declarations tab and you will see the screen shown at the right.

In the Available Declaration drop-down, select Share Target and click the Add button. This is step one. You must now add, using the settings to the right of the Supported Declarations pane, the Data Formats or File Types that you can accept.

In our map editor scenario, you could either use a unique file extension for saved map files or define a custom data format. The file extension approach is easy to understand. You save a map in the map editor, perhaps using the “.map” extension. You then set the Share Target setting on your game to by adding a new Supported File Type entry and set the value to “.map”. Now, from you game editor, you could simply share the saved “.map” file directly to the game, without the user having to launch the game and open the file. You game is still responsible for processing the “.map” file, but the user doesn’t have to leave the map editor to get the data to your game.

We will look at the other scenario, of working with a custom data type. It shares the same approach as the file type example, so it we are killing two birds with one stone. Let’s pretend we have a character editor that lets me build characters for the main game. In our character editor, we will share a custom data type and pass the character info as a JSON string. I won’t cover that here since the techniques are similar to what we have already looked at. If you want to see an example of doing that, check out the Share Source sample application here.

In our main game, we start by adding a new Data Format setting. In the textbox, you will enter a unique URI for you custom data format. Let’s set that to “http://mycoolgame.com/character”. At the bottom of the Declarations tab, with Share Target selected as the Supported Declaration, you will see a text box called Start Page. Here, you can enter the name of the HTML page that will be opened when your game is selected at the target of a share operation. You should design this page to reflect your game’s branding, colors, etc. Simply add a new page to the root of your project named ‘target.html, style it as necessary, and then types its name in the Start Page text box.

The more interesting aspect is handling the share operation. In the script file for target.html, you will want to do two things. Start handling the WinJS.Application activated event as shown below:

 

WinJS.Application.onactivated = function(e) {
 
    if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.shareTarget) {
 
           eventObject.setPromise(WinJS.UI.processAll());
           shareOperation = eventObject.detail.shareOperation;
 
           WinJS.Application.queueEvent({ type: "shareready" });
     }
};

There are two important things to note. First, we check to make sure that we are arriving at target.html via a shareTarget activation. Next, after we grab the data payload of the operation, we place an event on the Application queue. This is a user-defined event, not one provided by default. The reason we add a shareready event (or whatever you want to call it) to the queue is we want to return control to the system as soon as possible. By doing this, we can run our longer processes for parsing the data without slowing down the UI. Note, the variable shareoperation is defined elsewhere so that it is accessible to both the onactivated handler and the shareready handler.

In shareready, we can extract the data and update the UI on target.html as necessary.

 

function shareReady(eventArgs) {
 
   document.getElementById("title").innerText = shareOperation.data.properties.title;
   document.getElementById("description").innerText = shareOperation.data.properties.description;
 
   if (shareOperation.data.contains(customFormatName)) {
      shareOperation.data.getTextAsync(customFormatName).done(function (customFormatString) {
          var customFormatObject = JSON.parse(customFormatString);
 
          // Update rest of the UI
          });
    }
};

In our shareready handler, we update our UI immediately with the title and description provided in the share operation payload. We then look to see if it contains our custom data format. If so, we extract the custom data, which in this case has been passed to us as a JSON string. We can then continue on loading the character data into our game for future use. This might be saving it as a local data file, for example.

Wrapping Up

Sharing is a great way to extend the value of your game and to get some free publicity, as well. Players that enjoy your game will want to let others know of their accomplishments, and sharing allows you to leverage all of the great social media, email, and networking clients that the user will already have installed on their system. Sharing is easy to add, so make sure you do it, and take your Windows 8 game experience to the next level.

Tags:

HTML | WinJS | Windows 8

Comments are closed

Powered by BlogEngine.NET 1.6.0.0
Theme by Mads Kristensen

About the author

Jeff Brand Jeff Brand

This is the personal web site of Jeff Brand, self-proclaimed .NET Sex Symbol and All-Around Good guy. Content from my presentations, blog, and links to other useful .NET information can all be found here.

E-mail me Send mail


Calendar

<<  August 2014  >>
MoTuWeThFrSaSu
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

View posts in large calendar

My Twitter Updates

XBOX
Live

Recent comments

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2014

Sign in