1
2
3
4
5
6

Examples of WP7 Marketplace Certification Failures

I have now made it through a baker's dozen Windows Phone Marketplace certification attempts for SmartyPantsGaming, and thought I would share the various ways in which I've failed in my apps. I generally think the best way to learn is to learn from your mistakes, but learning from someone else's mistakes is even better - so here is a rundown of ways I've failed WP7 marketplace certification so far.

The back button should close popup windows
In the release of Matchingo Free we received an app rejection because the name entry dialog popup could not be closed by pressing the back button.

If the current page displays a context menu or a dialog, the pressing of the Back button must close the menu or dialog and cancel the backward navigation to the previous page.

To fix the issue I setup a boolean flag to keep track of when the name entry dialog was open, and then override the back button event. If the dialog is open and the back button is pressed then I cancel the back button event so it doesn't continue to bubble up, and close the popup window. Here is the code block:

protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
    if (IsNameEntryPopupOpen)
    {
     e.Cancel = true;
     ShowHideNamePopup(false);
    }
    else
    {
     base.OnBackKeyPress(e);
    }           
}

(click 'read more' to keep reading..)

You should store data in a culture / region independent way
The initial release of Matchingo was rejected because of a pretty neat little bug with how I was storing game settings to IsolatedStorageSettings. Since IsolatedStorageSettings.ApplicationSettings stores settings as strings of key/value pairs, I was converting my decimal numbers (opacity of the background image for example) to strings - but I was not doing it in a culture-safe way. What would happen is that the user would store settings in a culture that uses periods for decimal points (ex "0.98"), then change their phone's culture setting, and then load their settings in a culture that uses commas for decimal points (ex: "0,98") - this would cause an exception when using double.Parse() as the period was not a valid character in a decimal number in that culture.

This issue could have been avoided by using other means of storing the data in a type specific way instead of converting to and from strings. The quickest workaround was for me to make sure I was doing the culture safe version of converting my double to and from strings like the example below:

Saving:

// wrong way:
IsolatedStorageSettings.ApplicationSettings[key] = myDouble.ToString();
 
// right way
IsolatedStorageSettings.ApplicationSettings[key] = 
    myDouble.ToString(System.Globalization.NumberFormatInfo.InvariantInfo);

Loading:

// wrong way
myDouble = double.Parse(IsolatedStorageSettings.ApplicationSettings[key].ToString());
 
// right way
myDouble = double.Parse(IsolatedStorageSettings.ApplicationSettings[key].ToString(),
          System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo);

Another lesson to learn here is to test cultures well on the phone. There is nothing to say that a user won't start using your app in one culture, and then change to a totally different culture the next time they run your app - so try out that use case yourself when testing the loading and saving of data.

Watch out for MediaElement's defined in XAML - they can stop Zune's music playback
The recent submission of Matchingo Free was rejected for a weird bug - if they were playing music on their phone and launched Matchingo Free their music would immediately stop on launch - how odd. I knew that music playback would stop if you started playing a video in a MediaElement, but I wasn't doing anything like that in Matchingo.

Luckily I already knew enough to know that MediaElement could cause such an issue, and a quick search for 'MediaElement' in my project found 3 instances of sound files defined in XAML - but they weren't actually being used. You might recall that Matchingo started off as a Silverlight app - well, that version declared it's sounds in XAML as MediaElements (as compared to using SoundEffect's in the WP7 version), and just having them defined in XAML was enough to cause the issue. KeyboardP on twitter pointed out that the MediaElement constructor for WP7 sets the loaded behavior to play, and that may be what would cause a MediaElement in XAML to stop the Zune media playback.

Long story short - don't put MediaElement's in XAML without understanding that when that page loads it will new up those MediaElements, and stop the phone's music playback - which will cause a certification failure unless you've already gotten the user's permission for your app to stop their music.

Define DefaultCharacter values for sprite fonts if the text is dynamic [XNA]
This failure was for Hungry Castaway - our first game which is written in XNA. When the user finishes a game it asks them for their name. Using the WP7 PIP keyboard the user could enter many different odd symbols - symbols which weren't defined in my sprite font. My app would throw an exception when SpriteBatch.DrawString() was called to draw out the player's name - because my sprite font didn't know how to draw some of the requested characters. There is a flag in the .spriteFont file called 'DefaultCharacter' which is commented out by default. Uncommenting the DefaultCharacter flag tells the sprite font what character to render when it is asked to render a character not defined in the font. Uncommenting this one line was all it took to get this issue fixed:

<DefaultCharacter>*</DefaultCharacter>

Bad advertisements can break back button usage
This issue was somewhat of an edge case - hopefully it won't happen to you. There was an ad that was in the Wrap It Up Box app that caused my app certification to fail. What was happening was that the ad would open a webbrowser and immediately do a redirect - so that when the user hit the back button they would not be brought back to my app, but instead were taken back to the re-direct page which made it impossible for the user to get back to my app by pressing the back button (unless they hit it twice rapidly). This issue was outside of my control, and a quick contact to pubCenter support got it straightened out (and got my free app submission credited back to me). If you ever run into this issue refer to my forum post here - they know about the issue and it shouldn't happen going forward.

Wrap Up
App certification failures can be a real bummer - even more if you can't figure out how to fix the issue. Hopefully these examples will help someone else out in the future, but know that you can find plenty of help on Twitter and in the official development forums.

Comments

Few other failures that I experienced

1. App should launch within 5 seconds. - if you used number of external dlls like (google analytics thru msaf.codeplex.com etc..) and then used preemptive obfuscation (which I found in my unofficial perf tests adds approx 1 second to launch time) then we could easily cross 5 seconds.. Since pre-emptive was providing analytics as well, I removed google anlaytics from my code

2. Pressing "power" button and locking/unlocking when in the middle of the app. I had handled tombstoning at all but one page and I should say kudos to the test team they caught that exact screen.. so make sure every page in your app can handle and resume from tombstoning.

sri