How to Play Music in XNA games on Windows Phone 7 (and still pass Cert)

I’ve seen this come up in the forums a few times now: how do you properly handle music in an XNA game for Windows Phone 7? I got snagged by this in certification too, so I have some experience on how to handle it. Note that this is just my experience and there are always other ways to do things. This applies to XNA games on WP7.

What You Need To Consider

WP7 users can play music while playing your game. If your game plays music, you can’t simply interrupt the user’s current music. The relevant section in the Certification Requirements is “6.5 Applications that Play Media”.

6.5.1 Initial Launch Functionality
When the user is already playing music on the phone when the application is launched, the application must not pause, resume, or stop the active music in the phone MediaQueue by calling the Microsoft.Xna.Framework.Media.MediaPlayer class.
If the application plays its own background music or adjusts background music volume, it must ask the user for consent to stop playing/adjust the background music (e.g. message dialog or settings menu).

6.5.2 Configurable Functionality
If the application needs to play its own background music or adjust background music volume, it must provide the user with the configurable settings for its music.

 

The Basic Plan

Music in an XNA game should be played using the MediaPlayer class. If you use this class, you will automatically avoid the case where your music is playing at the same time as the user’s music. Note that if you try to use the SoundEffect class to play music, both your music and the user’s music can play simultaneously. This will fail certification and is specifically disallowed in the requirements.

Before we play music, however, we need to check if:

  1. The user is currently playing music
  2. We have permission to override the user’s music

 

The first case is simple. All we need to do is check if


MediaPlayer.GameHasControl

is true. If it is, then the user is not playing music and we have free reign to do what we want.
If the game does not have control though, we can’t call MediaPlayer methods (like Play, Stop, or Volume). At least, not unless the user says it’s okay. There are a few ways to approach this. We could prompt the user for permission when the game starts using something like a message box. That would work, but I would personally find that pretty intrusive.

Instead, I opted to have an option called “Allow game to override active music” in my options menu. If the user set this to true, I would re-enable my audio system and start playing music. Since it was part of the saved user settings, the game remembered the user’s choice for later.

Further Exceptions

If your game uses music for a cutscene, you can get away with interrupting the user’s music provided you resume it afterward. See section 6.5.3:

6.5.3 Applications that Play a Video or Audio Segment
An application may interrupt the currently playing music to play a non-interactive full motion video or audio segment (e.g. cut-scene or media clip) without asking for user consent. If music was playing prior to the segment, the application must resume music when the segment has completed.

Things To Remember

  • Don’t use SoundEffect to play music
  • Don’t change anything using MediaPlayer unless GameHasControl is true, or you have asked the user for permission in some way
  • Don’t simply check (MediaPlayer.State != MediaState.Playing) to see if you can play music. Use MediaPlayer.GameHasControl.
  • Perform your checks when resuming from tombstone, not just at launch. A user can tombstone, start music and then return to your game.

HOWTO: Track sales and downloads with XNA and Windows Phone 7 using Dotfuscator and Runtime Intelligence

Phew, that’s quite the headline. If you’re a Windows Phone 7 developer, you’re probably itching to get some real download and sales data, but Microsoft has stated that this won’t be available until the end of January 2011. Without that, you’re stuck checking the Zune marketplace rankings. These are just relative rankings however, and aren’t necessarily based on sales anyway. Some solutions for rolling our own analytics have been posted, notably here (overview of Microsoft Silverlight Analytics Framework) and here (walkthrough for Silverlight with Google Analytics).

You’ll notice that neither of those options work with XNA games (and you cannot mix XNA with Silverlight for WP7 and still pass cert). Fortunately, Microsoft announced that they would be partnering with PreEmptive Solutions to offer Dotfuscator and the Runtime Intelligence service for WP7 developers for free until the end March 2011. Nifty!

Unfortunately, I couldn’t find anywhere that really showed how to do this all the way through. I spent a couple of days on it though and now I can provide a guide based on my experiences, hopefully allowing you to avoid some of the gotchas. This is a long one, but hopefully you’ll get a good sense of what’s actually happening this way.

Overview

The plan here is to use Dotfuscator to instrument our existing game in such a way that it sends messages to the Runtime Intelligence server, where we can later log in and view analytic data. This guide focuses on using the Dotfuscator UI to instrument our project after it has been compiled, though you could theoretically tag your source code with the necessary attributes instead. By using the UI, we can tag methods in our game with attributes that specify what data we should send. The .xap is then rebuilt with the additional functionality, without modifying the source code.

In a nutshell:

  1. Get the required tools.
  2. Instrument our game and rebuild the .xap from the Dotfuscator UI.
  3. Run it.
  4. View analytics data on the Runtime Intelligence portal.

You’ll see that there’s a bit more to it than that, but this is all that is absolutely required.

Getting Started

First off, the partnership between Microsoft and PreEmptive for WP7 seems to be a bit last minute. In particular, there is no version of Dotfuscator specifically for WP7 yet (coming end of November). As such, some of these initial steps may not be valid a month from now.

To get started, you’ll need to get a copy of Dotfuscator with the appropriate license. For now, visit http://www.preemptive.com/windowsphone7.html . On the right is a note about “Can’t wait for the WP7-specific SKU?” with instructions on how to contact PreEmptive and obtain the software. If you want to instrument your app before the end of the month, you’ll need to do this (and to do so, you’ll need to make an account at PreEmptive). Otherwise, give the poor guys a break and don’t bother them if you don’t intend to use it. Grab a copy of the WP7 project template from the same page.

When you hear back from PreEmptive and follow their instructions, you should end up with:

  1. A copy of Dotfuscator Pro installed, with a temporary license.
  2. A Runtime Intelligence account, activated from within Dotfuscator. This is different from the Dotfuscator license.
  3. The project template, download from http://www.preemptive.com/windowsphone7.html (on the right)

Modify your game

Okay, I know I said we’d be instrumenting our game after it has been compiled, but there is one small thing we’ll need to change. I believe this will be handled automatically in the WP7-specific version of Dotfuscator, but I had to do this manually. Go to your WMAppManifest.xml and add ID_CAP_NETWORKING to your capabilities if it’s not there already:

<Capabilities>
<Capability Name="ID_CAP_NETWORKING" />
</Capabilities>

This is required by your instrumented game to send the analytics messages. Go ahead and build your game now too.

Instrument your XAP

Now comes the time to instrument your compiled game using the Dotfuscator UI. Don’t be confused by the name – we don’t need to use any of the obfuscation features (though you can if you want).

There is a handy video made by PreEmptive that you can watch that explains these steps nicely: http://www.youtube.com/watch?v=QvTueq7EJuY . I’ll run through them here as well.

Open up Dotfuscator. If you haven’t already entered your license key, do that. Then enter your Runtime Intelligence portal activation code under Help –> Activate Runtime Intelligence.

When prompted to “Select Project Type”, select “Open Existing Project”, highlight “More…” and press “OK”. Browse to where you saved “wp7app.template.xml”, which you downloaded from http://www.preemptive.com/windowsphone7.html.

Dotfuscator stores its project files in fairly intuitive XML. The “wp7app.template.xml” is a starting template that you will modify and then save a copy of for your particular game.

The first thing to do is go to the “Input” tab. Select the “${configdir}\Add_Your_XAP_here.xap” item and remove it. Then click “Add new input” and browse to your game’s .xap file. If you wanted to include/exclude specific .dlls from being instrumented or obfuscated, you can do that here. By default, everything is included (and nothing is obfuscated anyway), so we can move on.

Next, go to the “Instrumentation” tab. Here we need to add a few things as a little required housekeeping for the Runtime Intelligence service.

First, we need to setup some application-wide settings:

  1. In the tree view, find your main assembly and right-click on it. Select “Add Attribute”.
  2. Add *both* the “Application” and “Business” attributes. Select OK.
  3. Select the Business attribute you just added. In the right-hand pane, add the CompanyKey provided to you by PreEmptive. Add a CompanyName if you want, but it’s optional.
  4. Select the Application attribute. Give it a Name and a Version if you wish and the click the “…” to generate a GUID.

With that done, we need to decorate two methods so that our instrumented app knows when to send session information. The first is the SetupAttribute, which should go on your Game class’s LoadContent method. To do this:

  1. Drill down through the tree into your main assembly and find your Game class.
  2. Right-click on its LoadContent method and select “Add Attribute”.
  3. Choose “PreEmptive.Attributes.SetupAttribute”
  4. In the right-hand pane, set the CustomEndpoint to “Runtime Intellience Services for Windows Phone 7” by clicking the “…” and choosing it from the list.

Next, add the Teardown attribute:

  1. Right-click on your game’s “OnExiting” method and select “Add Attribute”.
  2. Choose “PreEmptive.Attributes.TeardownAttribute”.

Go ahead and save your project with a different name now. I just chose MyAppName.xml for simplicity.

Now hit the green play button to “Build Project”. This will take your .xap file and recompile it with the necessary code injected according to the attributes you placed. The resulting .xap file will live in “\Dotfuscated\YourAppName.xap”, based on where your original .xap lives.

At this point, we’ve done all that is absolutely required, so let’s see what happens.

Checking our data

Start up the WP7 emulator (“C:\Program Files\Microsoft SDKs\Windows Phone\v7.0\Tools\XDE Launcher\XdeLauncher.exe”) as well as the Application Deployment tool (“C:\Program Files\Microsoft SDKs\Windows Phone\v7.0\Tools\XAP Deployment\XapDeploy.exe”), both of which are part of the WP7 tools.

Deploy your instrumented .xap to the emulator (the one in the Dotfuscated subdirectory) and run it. There’s no indication that anything is different, so let’s check if we got our data.

Log into the Runtime Intelligence portal using the credentials you got from PreEmptive. You should see… nothing! Don’t panic.

There are a few caveats to working with the portal:

  1. By default, the filter is set to a day behind. Expand the filter and get it to include today’s date.
  2. It can take around an hour for messages to show up in the portal. They will show up as “Queued Data”. This just lets you know that the service is receiving messages from you.
  3. It can take 12-24 hours for messages to be processed. Once they’re processed, you can actually get information from them.

Yikes! 12-24 hour turnaround before you can see anything useful. Not good for testing and iteration. Worse yet, we’ve only really instrumented our app to send a message on startup and shutdown. That tells us, at best, how many times our app is run. We’re going to need more specific data, and a way of testing it faster.

Using Fiddler to view messages

I ended up using a tool called Fiddler to inspect messages as they were sent by the emulator. This post is long enough already, so I’ll point you to this blog post for instructions on how to get Fiddler to work with the emulator. A few notes: make sure you get Fiddler 2.3.0.7 (it’s a beta), and make sure you restart the emulator after starting Fiddler. If all goes well, you should be able to see traffic when you run Internet Explorer in the emulator.

It helps if you use Fiddler’s “Process Filter” and drag it onto the emulator. This way you avoid seeing packets from all the other programs that are running.

You should have Fiddler running and showing packets from the emulator at this point.

Now, go back to your Dotfuscator project and find the SetupAttribute in the Instrumentation tab again. Select the SetupAttribute and then find the “UseSSL” entry in the right-hand pane. Set it to false for the purposes of testing. Now when we inspect packets in Fiddler, we’ll be able to see the contents.

Save, rebuild the Dotfuscator project and re-deploy it to the emulator.

Now when you run your app, you should see a couple of messages appear in Fiddler:

If you use the XML view under “Inspectors”, you can see the contents of the message nicely. You should see that the event code for the messages are “Session.Start” and “Application.Start”, which seems pretty reasonable.

If you exit, you should see… no new messages! What??!

Start your app a second time and you’ll now see four messages: Session.Stop, Application.Stop and then the expected Session.Start and Application.Start.

This is unintuitive and has some implications. During the teardown method, the Runtime Intelligence code assumes the app is exiting. When WP7 apps are shutting down, network calls will appear to succeed, but nothing is actually sent. To deal with this, the Runtime Intelligence code instead writes the messages to IsolatedStorage and then sends them the next time the app is run. This means you will have a lot of incomplete sessions when viewing data on the portal. There is nothing you can do about this.

Reporting unique users

Right now, our app reports session data. While interesting, we could do a lot better. Let’s start by at identifying unique users.

To do this, we’ll make use of the phone’s unique id. This could lead to some duplicates if one user installs your game on multiple devices, but we’ll ignore that use case for now.

Adding an ID to session data is quite simple with Dotfuscator. To start, we’ll need to modify our game code so that we store the device’s unique id somewhere to access later. It needs to be available before the method tagged with “SetupAttribute” is called in order for Dotfuscator to use it (in our case, before Game.LoadContent is called). I just added the following to my game class:

#if WINDOWS_PHONE
using Microsoft.Phone.Info;
#endif

public class DatGame : Microsoft.Xna.Framework.Game
{

#if WINDOWS_PHONE
String phoneID = "0";
#endif

public DatGame()
{
[...]
var value = (byte[])DeviceExtendedProperties.GetValue("DeviceUniqueId");
phoneID = Convert.ToBase64String(value);
[...]

You’ll notice we’re now using the phone’s identity. That’s a new capability, so update your WMAppManifest.xml accordingly by adding:

<Capability Name="ID_CAP_IDENTITY_DEVICE" />

Now we have a field called “phoneID” that should contain the device’s unique ID. Rebuild your game. In order to hook this up in Dotfuscator:

  1. Go to your SetupAttribute and look at the right-hand pane.
  2. For “InstanceIdSourceElement”, select “Field”
  3. For “InstanceIdSourceName”, type “phoneID”

Now Dotfuscator has enough information to fill in the InstanceID of its messages with the phone’s unique ID. All messages will have this ID automatically, so you can now identify unique users for any message type you report.

Reporting Paid versus Trial

Now that we can identify unique users, let’s report on whether the app was launched with a full license or with a trial license. To make this easier, we’ll add some stub methods into our game code that we can then decorate using Dotfuscator.

There are many ways to do this. I chose to simply hook up to my PhoneLaunching event, which will be called only when the game is launched for the first time and not when tombstoned.

protected void OnPhoneLaunching(object sender, EventArgs args)
{
    if (Guide.IsTrialMode)
    {
        LaunchTrialFeatureTick();
    }
    else
    {
        LaunchPaidFeatureTick();
    }
}

public void LaunchTrialFeatureTick()
{
}

public void LaunchPaidFeatureTick()
{
}

This is a pretty simple example (you should check Guide.IsTrial and cache the result somewhere). Note that every time the game is launched, one of either LaunchTrialFeatureTick or LaunchPaidFeatureTick will be called. Rebuild your game. Let’s hook these up in Dotfuscator:

  1. On the “Instrumentation” tab, find the “LaunchTrialFeatureTick” method, right-click and select “Add Attribute”.
  2. This time, select “FeatureAttribute”.
  3. In the right-hand pane, set the Name field to something reasonable like “LaunchTrial”. This is how the feature will be identified in the portal.
  4. Do the same for “LaunchPaidFeatureTick”, with a name like “LaunchPaid”.

The reason I named these methods with “Tick” is because the method represents the entirety of the feature. If you want, you can identify the beginning and end of a feature separately in order to get a sense of how long a feature is used for. I won’t cover that here but it should be pretty intuitive.

Wrap up and where to go from here

At this point, your app should be reporting session data, along with a “Feature” message each time the game is launched indicating if its the paid or trial version. Each message has a unique id per phone, so you should be able to get a pretty accurate idea of how many users are playing your game. You’ll still need to wait for your data to be processed on the portal but you can check your work with Fiddler.

Don’t forget to enable SSL again!
Don’t forget to submit your instrumented .xap to certification and not your original!

What else can you do? You can easily add any custom data to your messages by filling out the “ExtendedKey” properties in Dotfuscator. For example, when a user finishes a round in my game, it also reports their high score. I also store the user’s last IsTrial setting, allowing me to send a message when they purchase the game or run the full version for the first time (rather than filtering LaunchPaid events for unique users). If there’s interest, I can show you how to do that too.

Questions? Comments?

If you found this useful, follow me on Twitter @benkane and check out my new game Zombie Accountant! Thanks!

Sales and Trailers

Windows Phone 7 launched today! Nifty! Most of the reports seem to indicate that the Canadian carriers don’t really have units available at retail. Oh well, I can wait.

Now that I have a game out on the marketplace, I can shift my attention to the next important thing: constantly checking on how the game is doing. Unfortunately, this is nearly impossible to do! It turns out that Microsoft won’t be providing download or sales data for app developers until the end of January 2011. That kinda sucks for anybody wanting to base decisions on the performance of the marketplace as well as for those of us who just want to know when we’ve made our first dollar.

To compensate for this shortcoming, Microsoft has partnered (more) with PreEmptive Solutions, makers of Dotfuscator, to provide analytic tools to WP7 developers for free (until March 2011). At first I wasn’t particularly interested in this, as the idea of adding tracking information into my game seemed to be more trouble than it would be worth. However, the potential insight gained is hard to ignore, so I spent a good chunk of today working with Dotfuscator and Runtime Intelligence.

To spoil the story, I still don’t have it working. It seems this is kind of a last-minute arrangement between the two companies, as you need to ask for the tools rather than simply downloading them and the supporting documentation is rather lacking. The process is also a bit cumbersome, as data can take hours to process, making development and testing pretty slow. To rub salt in the wound, I ran into a bug in the Dotfuscator software that stopped me altogether. Normally all of this would be enough to make me drop it altogether but there were a few saving graces:

  1. There actually aren’t many (if any) alternatives for non-Silverlight applications.
  2. The instrumentation UI and reporting portal are quite powerful. I can think of a lot of interesting telemetry to capture.
  3. The support provided by PreEmptive is impressive.

On that last point, an engineer from PreEmptive was lurking in the AppHub forums and was able to help me out with the bug I encountered. If all goes well (I’m waiting on a patch), I should be able to wrap up basic telemetry tomorrow and probably submit an update.

Since it seems like nobody else has done so, I plan on posting a full walkthrough of what is necessary to get basic usage and sales tracking in an XNA-based WP7 game using Dotfuscator and Runtime Intelligence. I’ve got basic usage reports working – I just need to add in some custom data to allow me to track unique full-licenses.

Lastly, since all-text posts are lame, here’s new promo trailer I made for Zombie Accountant today:

Ship it!

I finished my first game! It’s called Zombie Accountant and it’s out now on the Windows Phone 7 marketplace.

Windows Phone 7

In my last post, I showed an early video of a game I’m working on for Xbox Live Indie Games. All of a sudden, I’ve released Zombie Accountant for WP7. What gives?

It came down to scope. I started Zombie Accountant as a side project with much smaller scope than my other game with the intention of actually finishing a game. It seems a bit counter-intuitive to start a new game in order to ensure I finish a game, but it felt like the right thing to do given the amount of work I estimate I have remaining on my other title.

Zombie Accountant actually started as an Xbox 360 game. I had largely ignored the Windows Phone tools – I didn’t bother downloading the beta tools at all. Once the release date for XNA 4.0 support on XBLIG was revealed to be a rather generic “Fall 2010”, I decided I would probably have time to squeeze in a WP7 version. It turned out to be a relatively easy conversion and I feel the simplistic gameplay is well-suited to a mobile experience.

What’s Next

Now that XNA 4.0 support for XBLIG is imminent, I plan on dusting off the X360 build of Zombie Accountant and get it into playtest this week. This will be my first foray into playtest and the peer review system, at least as far as my own games are concerned. I’m looking forward to it (:

More Posts

With a game out on a marketplace, I feel I can take a bit of time to blog about more things. Any interest in hearing about my experience with WP7 certification? How to actually finish a game? A post about my general workflow (e.g. getting set up with Git, getting set up on AppHub)?