Monthly Archives: February 2012

Pro-Tip: Including Background Music For Your Windows Phone App

Alright! So I’ve finally cracked how to set up background music playing consistently in the background for a Windows Phone app. Here’s a step by step lowdown:

1) Play background music with MediaElement. So we’re going to hold a MediaElement object at the Application Level, so our music keeps playing while you transition between pages. Note the MediaEnded event, which we’ll come to later.

In your App.xaml:

[sourcecode language="xml"]
<Application.Resources>
<MediaElement x:Key="GlobalMedia" MediaEnded="MediaElement_MediaEnded" AutoPlay="False" />
</Application.Resources>
[/sourcecode]

2) Include mp3 in your project with Build Action = Content.

3) Check if we should play background music when the initial page of our application is hit. There are some Application Certification Guidelines around the use of background music in apps, namely 6.5.1, which basically states that you need to ask the user whether they want to replace their currently playing audio with your app’s background music.

To check whether the user is playing background music, we can look at the MediaPlayer.GameHasControl property – you’ll need to include the XNA libraries and the appropriate using statements. If MediaPlayer.GameHasControl is not true, then something outside of our app is using the Media Player (so there is background music going).

4) Set the source for the MediaElement, and play the media once it’s ready.

So in the constructor for MainPage.xaml.cs, I have:

[sourcecode language="c-sharp"]
public MainPage()
{
InitializeComponent();
(Application.Current as App).TryPlayBackgroundMusic();
}
[/sourcecode]

and in App.xaml.cs:

[sourcecode language="c-sharp"]

public static MediaElement GlobalMediaElement
{
get { return Current.Resources["GlobalMedia"] as MediaElement; }
}

public static bool BackgroundMusicAllowed()
{
bool allowed = true;

//you can check a stored property here and return false if you want to disable all bgm

if(!MediaPlayer.GameHasControl)
{
//ask user about background music
MessageBoxResult mbr = MessageBox.Show("press ok if you’d like to use this app’s background music (this will stop your current music playback)", "use app background music?", MessageBoxButton.OKCancel);
if (mbr != MessageBoxResult.OK)
{
allowed = false;
}
}

return allowed;
}

public void TryPlayBackgroundMusic()
{
if (BackgroundMusicAllowed())
{
MediaPlayer.Stop(); //stop to clear any existing bg music

GlobalMediaElement.Source = new Uri("Audio/background.mp3", UriKind.Relative);
GlobalMediaElement.MediaOpened += MediaElement_MediaOpened; //wait until Media is ready before calling .Play()
}
}

private void MediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
App.GlobalMediaElement.Play();
}
[/sourcecode]

5) If our Application is activated (so resumed from FAS / tombstone) – check if user background music is currently playing – if so, we leave that playing (because they would have left our app, started playing some music, and returned, so it’s not likely they will want to stop their music). Otherwise, we try and play our background music.

Here’s the code that goes in App.xaml.cs:

[sourcecode language="c-sharp"]
private void Application_Activated(object sender, ActivatedEventArgs e)
{
//to prevent multiple prompts…
if (MediaPlayer.GameHasControl)
{
TryPlayBackgroundMusic();
}
}
[/sourcecode]

6) Loop the background music – we do this by catching the MediaEnded event on the MediaElement, and requesting it to play again.

[sourcecode language="c-sharp"]

private void MediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
if (GlobalMediaElement.CurrentState != System.Windows.Media.MediaElementState.Playing)
{
//loop bg music
GlobalMediaElement.Play();
}
}

[/sourcecode]

Note that my solution doesn’t handle resuming background music from the duration / seek position in which the app was suspended / tombstoned – I didn’t think it was worth the effort, and figured it wouldn’t be a dealbreaker if the music started back from the beginning of the 2 minute loop.

Hope this saves everyone a lot of time and effort!

Thanks to all the following posts for the help – worth a read if you’ve got the time:

Sterling DB vs SQL CE in Windows Phone Development

Just a quick note for everyone weighing up between Sterling DB and SQL CE for your Windows Phone app – while Sterling DB is fantastic for small sets of data, it performs very, very poorly with bulk inserts / restore (a few minutes when we hit the hundreds of rows mark), which makes it unsuitable for any large tables. The SQL CE support in Mango, while slightly slower on queries, is much more consistent and more suited to larger data sets.

Hopefully the team behind it improves the performance in the future, because it’s really lightweight and easy to program against; but for now would warn against using unless you want to spend a day replacing your DB layer like I did…

If you’re looking to get started with SQL CE, this guide at Windows Phone Geek is a good place to begin.

Pro-Tip: Infopath 2010 and mysteriously duplicating Promoted Fields

For all it’s power, InfoPath sure does have some massive annoying bugs. Today I was working with some InfoPath forms, and was afflicted by the “duplicate promoted fields / properties” issue, which seems to want to randomly occur when you add / modify new promoted fields. In essence, instead of reusing the promoted properties it’s already created for use on your SharePoint site, InfoPath decides it’s going to create you a whole new set of Site columns to use.

Normally this is fine, if only a little annoying – but we were using those forms in conjunction with some workflows, which were relying on those promoted fields to have a consistent name…so this needed to be fixed.

InfoPath forms, like a lot of other MS file formats and technologies from the 90s era, is based around a cabinet file / .cab; so the steps I took to remove these erroneous fields were:

1) Rename my form to .cab
2) Extract everything, and open manifest.xsf in notepad
3) Find the offending duplicate columns, and remove them. You’ll find them within a block similar to <xsf2:listPropertiesExtension> (though the namespace might be different):

EDIT: It turns out that you can set specific guids to use as the column name – so instead of removing them, it would probably be better to *add* Guids to ensure they maintain consistent between environments and deployments; so in the screenshot above, you want to ensure the listpropertyextensions have ColumnIDs assigned like the ones bracketed in red.

If you aren’t sure which ones to remove, you can always compare the columnName property in the <fieldExtension> with the columnName property in the <xsf:field/> near the bottom of the manifest.xsf file.

4) Repack the cabinet – you could use IZarc you can actually open the mainfest.xsf using InfoPath designer (right click and select Design) and then “save as” .xsn, bypassing the fiddly cab creation step.

Once you redeploy / update the form, everything should now be fixed! If you were using the form on a document library, it’s likely you won’t be able to remove the site columns – I ended up recreating the document library to refresh everything but you may not have this luxury if you’ve already got live data in there…

Maybe Office 15 will fix all this (but judging from how SharePoint Designer has progressed over the years, I wouldn’t hold my breath).

My Xbox Live Account Got Hacked

I woke up this morning to find five emails listing purchase confirmations at 3am – somehow, someone had gotten hold of a really old Windows Live account which unfortunately had credit card information stored against it for a Windows Azure subscription. Anyway, whoever got it changed my name to Robert Bubnick (lol), and proceeded to buy ridiculous PC games such as “Fishdom: Spooky Splash”.

So I called Xbox support here in NZ – and they were terrible. Seriously, seriously atrocious. The guy just wasn’t taking my call seriously, and essentially told me to call kiwibank and wanted to do as little as possible, and it took me five random voice prompts and on hold before I had even got to him…frustrated and angry, I proceeded to call Kiwibank to try and cancel those charges.

And man they were good. I rang the number, and they picked up instantly (+5 points). The guy immediately understood the situation, was clear and concise, didn’t have difficulty understanding, and coming from a horrible support rep to one of this quality really made a massive difference. Unfortunately, he said, because the charges hadn’t cleared through my credit card, he had to ask me to call Microsoft again.

So I did, and played the whole thing again, and got an average experience this time – my favourite part was the part when I told him “I don’t actually own an Xbox” and this new person says “oh wow, sorry. Sorry for this…I’m going to actually take your case seriously now.”

Great work, Microsoft.

So I guess the moral of the story is:

1) if you’re gonna hack my account, PLEASE buy something less retarded
2) Xbox Support – up your game. (I feel like your outsourcing is not maybe the best thing)
3) Kiwibank – I love that you constantly remind me how much I love you.

Excel 2010 and Unicode CSV files

As part of Wuxie, I’m creating (or rather, compiling from the internet) a number of different resources to include in the application to populate the word database. So I have a whole bunch of nice .xls spreadsheets with all the characters and information in UTF-8; but someone, for some reason, decided that any time you save a spreadsheet to a .csv, it would force the encoding back to ANSI and you’d just end up with a whole bunch of ??? where your beautiful 漢語 used to be.

Enter Jaimon Mathew to the rescue, who wrote a little Excel Add-In to get around exactly this issue – it works exactly as advertised, and allows a save as Unicode CSV option. Perfect!

PS Vita: Hands On Impressions

Today, me (and probably like 100 or so other dorky guys) got to get some hands on time with the PS Vita prior to it’s local New Zealand launch – and while it’s a nice piece of hardware, I don’t really feel like it’s substantially better than my PSP, and Uncharted / ModNation weren’t nearly as beautiful as I was led to believe they would be. They weren’t bad – but Uncharted especially had a lot of pixellation and jagged edges. There was one cool game I tried called Reality Fighters, which was a pretty standard fighting game – except that it used the rear camera to project your fighters into the environment. A gimmick? Yes. Adorable? Double yes.

I think I’ll wait until a Final Fantasy / Decent RPG comes out for the platform before I commit.

Wuxie: Sneak Preview

Working on my next Windows Phone 7 app – here’s the very first screenshot! This time round I’m trying a few new things – I did a design document (instead of making up all my classes and pages on the fly, I’ve actually got a plan, which is handy), and I’m using NotifyPropertyWeaver – which is awesome!

Yes – I know the word card above is *totally* wrong – it’s just dummy data for layout purposes, don’t worry :)

Hoping to get this one rolled out in a few weeks, since I have until the end of March to make 5 apps for yet another competition…

SharePoint Gotcha: Working with change tokens and change logs

Was working on some code today, which was a timer job that used to work, but now doesn’t. In the timer job, we had essentially something similar to the following:

[sourcecode language="c-sharp"]
SPChangeToken changeToken = list.ParentWeb.Properties["mychangetoken"];
SPChangeCollection changedItems = null;
SPChangeQuery queryitem = new SPChangeQuery(false, true);
queryitem.Item = true;
queryitem.ChangeTokenStart = changeToken;
newItemchanges = list.GetChanges(queryitem);
[/sourcecode]

All the code above was working perfectly fine last year, but after coming back from holiday, we noticed the timer job would now keep throwing an exception when running:

The changeToken refers to a time before the start of the current change log.

It turns out that this happens because by default the change log only keeps entries for 60 days. (You can change this setting in the Resource Throttling section of the Web Application properties in Central Administration.) So therefore, after no changes were made in 60 days, the changeToken was now referring to a change log entry that had been purged.

So if you’re getting an exception while working with the SharePoint changelog or changelog objects, make sure that you aren’t attempting to use a changelog entry that doesn’t exist any more. You can probably set the change log to never expire (but I imagine database space would very quickly become a concern for any reasonable amount of usage over a period of time), or just make sure that you handle / don’t always expect to be able to get a full list of changes.

Skritter: Day #22

Until very recently (thanks to the very, very large distraction and happy disruption to my life in the form of Final Fantasy XIII-2), I’ve been Skrittering daily. I’m kind of over super complicated words, for now – while they’re initially hard to remember, they eventually become pretty memorable once broken down to the radicals. My new pet confusion is words that are written the same but have two entirely different meanings and pronounciations.

For example – 覺 – which is jue (and in jue de – reckon/feel), but also jiao (as in sleep, shui jiao) and
還 – which is hai (as in still, continuing), but also huan (as in return)

I hadn’t known this was true until now, and I wonder why it is…and it’d be great if Skritter could highlight this in some way (but would rather they fast forward the iPad app :P ). So now, not only does Chinese have a large number of words that sound the same but written completely differently – but now there are words that are written the same but sound different! Or maybe they’re the same word, and it all depends on context? But the context completely changes the pronounciation?

At least, now I know…

[202 Words Learned | Retention 90.1%]