Enable background audio for multiple pages in Windows Phone 7

Building an audio application this weekend I ran into a problem; where do you place the media element when you have more than one page, and you want the audio to continue playing when you navigate between pages. I will get to the solution later on in the post but first some background.

During the weekend our .NET team spent two days with Windows Phone 7. A few weeks ago we brainstormed around a few application ideas. The ultimate goal from the weekend was to se how far we could get in about a day of coding. To get us all kick started we were happy to have Dag König with us to talk about windows phone 7 development and support us during the weekend with ideas and hardware.

We split into several groups and my group focused on an audio application with streaming media, based on listings from an XML source. The available streams were presented in a list and selecting one navigated us to another page where the player was located. Of course there was a lot of different problems solved during this session but one of them was as follows:

We wanted the stream to start playing when we navigated to the Player Page and continue to play in the background when we returned to the stream list in the Panorama Page. It shouldn’t stop until we directly stopped it or a new stream was selected.

After some thinking it was obvious that we needed place that’s globally accessible for the media element responsible for the sound. One such place is the application level, and it turned out to be the way to solve this. But you can’t just drop element in the xaml and be done, that would be too simple. However, the solution wasn’t that far away. I placed it in the common resources instead and used a property to expose it globally for the pages. So the first code part is from the app.xaml file:



  ...

  
    

      
      

      
      
        
      
    
  

And in the code behind you find the properties parts to make it accessible from the pages in the application (through App.GlobalMediaElement). The property is set the first time the media element is loaded (via the Loaded event) and then it’s just returning the original media element on reoccurring calls:

private static MediaElement _globalAudioElement = null;

public static MediaElement GlobalAudioElement
{
  get { return _globalAudioElement;  }
}

private void OnMediaLoaded(object sender, RoutedEventArgs e)
{
  if (_globalAudioElement == null)
    _globalAudioElement = sender as MediaElement;
}

Finally in the end of app.xaml.cs there is the initialization section and here I injected the global media element in the system with the template from the resource:

private void CompleteInitializePhoneApplication(object sender,
                                                NavigationEventArgs e)
{
  if (RootVisual != RootFrame)
    RootVisual = RootFrame;

  RootFrame.Navigated -= CompleteInitializePhoneApplication;

  // Add this to inject the media element Control template
  RootFrame.Template = App.Current.Resources["AudioContentTemplate"]
                           as ControlTemplate;
}

And now you can access the MediaElement form any page and do your stuff almost as if it was added the the page itself with:

App.GlobalAudioElement.Source = streamUri;
App.GlobalAudioElement.Play();

That’s all there is to it, hope it helps someone out with the same problem we had. There is actually another solution but that one includes a bit of XNA coding, for this scenario it was enough with the above solution but if you need a more detailed and advanced control over the audio in your application I recommend looking into XNA.

This Post Has 9 Comments

  1. Stephgane

    Thanks you for this exemple, but in my case it doesn’t work. The MediaElement open the stream (CurrentState = Openin) and then nothing..

    If I open the same stream from a MediaElement on the page, it works.

    You knows an isue ?

  2. Stephane

    Sorry, the problem is from me. It’s ok now ! Thanks you !

  3. Mohamed

    Thanks alot, it works.
    but what if I want to play a list of mp3 files (kind of playlist)?

  4. VJ

    Thanks a lot. It works.
    But the design in all pages got slightly collapsed also the button in few pages are not working as before. Hope the problem may be due to style collapse.
    Any ideas ??

  5. Håkan Reis

    VJ: Have you checked the followup: http://blog.jayway.com/2010/11/11/enable-background-audio-for-multiple-pages-in-windows-phone-7-e28093-take-2/

    Mohamed: If you want to play a list of files you just take the media element and when the event changes from playing to stopped (as when the current item is played) you would feed it a new source and start that play automatically.

    However, most of these problems could be solved with a Background Audio Tasks (either streaming or content) in mango.

  6. Sm

    @Håkan Reis in some devices like 256MB ram backgroundaudio agent not available. Other solutions?

  7. Anju

    Thanx a lot for the code.. It helps..Saved my time!! :-)

Leave a Reply