Mobile Development at U2U Consult

Based in Brussels, Belgium, U2U Consult has been offering consulting & development services in the EMEA region for over 10 years. We offer mobile development on all platforms from Apple to Android & Microsoft.

This article describes how to play foreground and background sounds in a XAML-based Universal Windows app. I know that this sounds easy (pun intended). But I will do this while sticking to the MVVM pattern, which makes it a bit more challenging. I’m not targeting a specific framework here. The described architecture can be applied in MVVM Light, Universal Prism, Caliburn.Micro as well as in your home brewed MVVM library.

Here’s how the attached sample app looks like. It comes with two buttons that trigger a different sound effect, a switch to mute the background sound, and a button to navigate to a new page (very uncommon in a single-page app ):

What's the challenge for an MVVM solution to play sounds? Well, a universal XAML app can only make noise through a MediaElement, and that MediaElement should be part of the runtime structure of XAML objects known as the visual tree. As a result of that, only a small number of app components -the currently active Views- have access to it. In most cases however it’s the business logic in the Model or the ViewModel that knows which specific sound effect should be played at which particular moment. So the ‘Sound’ functionality should not be restricted to a some Views, but it should be generally available to all application components and component types.

In most MVVM ecosystems, this type of global functionality ends up in a so-called Service (other examples include logging, authorization, and toast notification). And so does the SoundPlayer: it’s a global service that comes with a Play method. That method has two parameters:

a reference to the sound effect (from a developer-friendly enumeration), and

a boolean indicating whether the sound should be played in the foreground (once) or in the background (in a loop).

Since a MediaElement can only play one sound at a time, the SoundPlayer is connected to two of them – one for the foreground and one for background. The background player can be disabled (muted) by the app.

Here’s an class diagram of the SoundPlayer, together with the Visual Studio solution structure. The platform specific projects for Windows 8.1 and Windows Phone 8.1 are collapsed, since they’re empty – except for the tile images. All the code is in the Shared project:

This is how everything was set up. The first challenge is to make sure that every Page of the app is decorated with two MediaElement instances. An easy way to do this, is to put these elements in the app’s root frame. This can be done through a custom style, e.g. in the App.xaml file:

As long as you navigate within the frame, the media elements remain available. But when you programmatically switch to another root Frame, you have to make sure to apply this style to it. That’s what the navigate button in the sample app does:

Achievement unlocked: every page will always two MediaElement instances on it. We just have to make them available to the SoundPlayer service. This assignment is done in the Initialize call in the SoundPlayer class itself. Make sure to preserve the state since we might be hosted in a new frame with brand new UI elements at their default -unmuted- state:

To make the SoundPlayer service globally accessible, it was implemented as a Singleton. A static class would not work, since property-changed notification requires an instance. In most MVVM frameworks this instance would be served to you by Dependency Injection, or it would be listening to a Messenger of some sort. Here’s the core class definition:

The Play method was made asynchronous to keep the UI responsive. The list of available sound effects is contained in an enumeration that maps the physical mp3 assets that you can see in the previous screen shot. That makes it easy for all components to select the sound effect they want to play:

publicenum Sounds
{
Nature,
Sweep,
Bell
}

By the way, if you’re looking for royalty-free sound effects, you may want to check SoundGator or SoundBible.

The SoundPlayer is now accessible from the View components. So you could decide to start some background music after a page is loaded: