Applies To: Silverlight (the restriction applies to XNA, but the
MediaElement is only Silverlight)
Simply setting the
Source of a
MediaElement to a valid source will stop any current background playback, causing you to fail Marketplace certification, according to section 6.5.1 from the certification guide.
The Fine Print
From the certification guide:
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).
Note: This requirement does not apply to applications that play sound effects through the Microsoft.Xna.Framework.Audio.SoundEffect class, as sound effects will be mixed with the MediaPlayer. The SoundEffect class should not be used to play background music.
Note: This requirement does not apply to Music + Videos Hub applications that are described in Section 6.4
You have a
MediaElement which only used to play back one file, so you set the
Source in your XAML.
The user starts playing some music in Zune, then launches your XAP. As soon as your XAML loads and the
Source is set, the background music stops playing, even if the
MediaElement is not playing. That’s right, even if you set
AutoPlay = "False", the background music will still be stopped.
Since you must ask the user for consent, you will have failed certification.
- Never set a
MediaElement‘s Source in XAML, unless that XAML is on a page that you navigate to after asking the user for consent.
- Check to see if background music is playing and then set the source (in code).
Note: If you set the source and then immediately call
Play() will have no affect since the
MediaElement will still be in the
"Opening" state, instead set
"AutoPlay = true" (works from code)
Applies To: Silverlight & XNA
Your app does some sort of music playing that doesn’t make sense to blend into any already playing background music (for example, you’re going to stream your own music) or you simply want to show a video.
Why You Care?
If you just start playing music you will fail certification according to section 6.5.1 of the certification guide if you don’t ask the user if you can stop the background music, but how can you stop the background music if you don’t know it’s playing? Hence, you care!
Microsoft.Xna.Framework.Media.MediaPlayer.GameHasControl (it’s a
bool) – if you have control, then you’re good to go. If you don’t have control, then there is something in the background and you need to prompt the user before continuing.
Silverlight Note: you’ll need to link in
Microsoft.Xna.Framework.dll for this to work, but make sure you don’t distribute this file with your XAP by mistake (or you’ll also fail certification for redistributing phone assemblies)
Applies To: Silverlight & XNA (anyone using Launchers / Choosers)
[some launcher object].Show() with a
try/catch block which catches
InvalidOperationException, since running
Show() while navigating (for example, if the user clicks your button multiple times quickly in succession) will cause this Exception to be thrown.
You have a button that says “Purchase Me” which launches the Marketplace or one that says “Send Feedback” which launches Outlook to send an email. For example:
EmailComposeTask emailComposeTask = new EmailComposeTask();
emailComposeTask.To = "email@example.com";
emailComposeTask.Subject = "Feedback for AwesomeApp";
The user hits the button multiple times, quickly. The app crashes.
If you debug this you’ll find that you can’t reproduce this behaviour on the Emulator (at least, I couldn’t) but that it reproduces pretty consistently on the phone.
On the phone you’ll get an
InvalidOperationException with the following message:
Navigation is not allowed when the task is not in the foreground. Error: -2147220989
There are a couple of solutions – you could remember your state, so that if you clicked the button once and haven’t navigated back yet then you just don’t call
Show(). Alternatively you could check if you were currently Navigating, and not call
Show(). I personally prefer to wrap the statement in a
try/catch block since it’s the easiest to have to worry about and the cost for the
try/catch block is minimal (performance wise).
… as opposed to multiple apps, each with a different locale.
- If these are free apps, then each language will count towards your free app quota (you get 5 free apps that you don’t need to pay certification costs for)
- Regardless of price, each app will need to go through independent certification (which will then take longer for all apps to be released), instead of one app being certified and published with all languages
Happy App Hubbing!
File this one under “Sad, but True”…
Always prefix your source paths with a “/” (full-qualified path) instead of simply using relative paths.
But they both work!?!
True, both of these will work, equally well (visually), but performance wise the relative path will do extra lookups which waste time, and can hit the SD card more than you want it to (causing further slow downs). This is something that we will fix on our side in the future – since all storage is isolated and we can assume that there is always a “/” (if there is no “..”). For now, it doesn’t hurt to get the extra performance boost by simply prefixing your paths with a “/”.
As Luke Kim, a friend from Microsoft, pointed out “/” paths are not really full qualified paths. To make things clear though, I use the term “full qualified” since we are within the confines of the .NET IsolatedStorage framework and there is no access to the rest of the system, “/” paths are as fully qualified as you get (without actual URI specifiers). Thanks for pointing this out!
Here’s a small tip for those of you who want to debug performance in a Windows Phone Silverlight app with the frame rate counters, but have the System Tray visible – hide it.
The counters currently show up behind the system tray (since technically the tray is a system overlay which is drawing over the surface available to your Silverlight app), so hiding the tray will show the counters.
Don’t forget: to re-enable the system tray when you’re done!
Here’s an awesome gotcha when moving from a desktop Silverlight application to a Windows Phone 7 application – make sure that your media (wmv) files are set to “Build Action” = “Content” and not “Resource”.
You’ll notice that if you do something like:
Where “somevideo.wmv” is set to “Content”, then the Windows Phone Developer Tools (ie. Visual Studio) will underline the
"Source" attribute and recommend that you set it to “Resource”. This is a hangover from the desktop and is something that I hope will go away – you can safely ignore this warning (it won’t appear in your build windows).
What’s Wrong With “Resource”?
For those that want more, here are the potential problems you can run into when setting your media to “Resource”:
- When a video file is compiled as a Resource it incurs an extra space and performance hit every time you play it, since Silverlight does extra processing to extract the video from your assembly (DLL). In the case of “Content” the file can be read directly from disk (or memory) and you’ll get instant start playback.
- Anything that makes your DLL larger is evil (from my point of view) – you want your assemblies to be small (think “quick and nimble”). Although the size doesn’t always directly affect load and memory time (there are a couple of other factors at play here) this helps eliminate one more possible bottleneck.