WP7 (8): play a ringtone on the selection page of The ListPicker Control
Written by Allen Lee
In the previous lesson, we achieved the playing icon effect on the selection page of The ListPicker control. Then sjcxyf found a new problem:
I added an MP3 file to the project and added a MediaElement control to the page. I added the code for playing music to the Image_Tap event, however, the result is that you cannot play music when you click the play icon after the selection page pops up. I tried to add the MediaElement control to the selection template, but the final result is the same.
In Silverlight for Windows Phone, MediaElement has a special restriction. You must add it to the visualization tree, otherwise it will not play. Suppose we add a play button on the ringtone settings page, as shown in 1, and then create a MediaElement object in the Click event handler of this button, then play the pre-added ringtone through it (the value of the Build Action attribute of this ringtone file is Content), as shown in Code 1.
Figure 1 ringtone setting page
Code 1 play a ringtone through a MediaElement object
private void Button_Click(object sender, RoutedEventArgs e)
{
var media = new MediaElement();
media.Volume = 1;
media.Source = new Uri(“Windows Logon Sound.wav”, UriKind.Relative);
}
Run the application and click the play button. You will find that there is no sound. However, if we add the MediaElement object to LayoutRoot after it is created, as shown in Code 2, click the play button to hear the sound, because the MediaElement object is already on the visualization tree.
Code 2: add the MediaElement object to LayoutRoot
private void Button_Click(object sender, RoutedEventArgs e)
{
var media = new MediaElement();
LayoutRoot.Children.Add(media);
media.Volume = 1;
media.Source = new Uri("Windows Logon Sound.wav", UriKind.Relative);
}
This is why we often see that someone else creates a MediaElement object in XAML and calls its Play method in code hiding to Play the audio. However, if you try to copy Code 2 to the Tap event handler of the Image control, you will find that you still cannot hear the sound. Why?
When we click the ListPicker control, it will open a new selection page. At this time, because the ringtone setting page is no longer visible and does not need to be rendered, Silverlight for Windows Phone will remove it from the visualization tree, therefore, it is meaningless to add the MediaElement object to the LayoutRoot of the ringtone setting page in the Image control's Tap event handler.
So what if we create a MediaElement object in the Project template on the selection page? Without a doubt, this will cause multiple MediaElement objects on the same page, which is not supported by Silverlight for Windows Phone. Therefore, this path does not work.
From the above analysis, it is not difficult to see that the biggest problem with MediaElement is its dependency on the visual tree. Is there a solution that does not depend on the visual tree? Yes, we can borrow the XNA SoundEffect:
1) Add a reference to the Microsoft. Xna. Framework library, as shown in figure 2.
Figure 2 Add a reference to the Microsoft. Xna. Framework library
2) Add a reference to the XNA namespace, as shown in code 3.
Code 3 XNA namespace
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
3) change the Tap event handler of the Image control to the one shown in code 4.
Code 4 play the ringtone through SoundEffect of XNA
private void Image_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
using (var stream = TitleContainer.OpenStream("Windows Logon Sound.wav"))
{
var audio = SoundEffect.FromStream(stream);
FrameworkDispatcher.Update();
audio.Play();
}
e.Handled = true;
}
Code 4 is simple. It opens the ringtone file as a stream, creates a SoundEffect object with the stream object, updates the component Status of XNA, and finally plays the ringtone.
Generally, when we mention the storage area of the Windows Phone application, many people will first think of the independent storage area. However, the Windows Phone application also has another storage area, this area is the installation folder of the application. Unlike the independent storage area, the content in the installation folder is read-only. When we set the value of the Build Action attribute of the Content file to Content in the Visual Studio attribute window, for example, in the previous ringtone file, the installer will deploy them in the installation folder. In fact, the Windows Phone SDK 7.1's LINQ to SQL uses "appdata" and "isostore" to differentiate the two areas in the connection string.
TitleContainer provided by XNA. the OpenStream method can be used to read the content in the installation folder. If your application downloads ringtones from the Internet, these ringtones will be saved in a separate storage area, this means that the code for opening the file stream in code 4 should be replaced with the corresponding independent storage access code.