Many apps, especially games, have sounds. This can just be a feedback sound or one that enhances the navigation or interaction of the game. Games usually have background music playing on a loop.
The MediaPlayer
type is used to play a sound from a content provider, a URI or a resource:
Uri
instance, we use the static Create()
method on MediaPlayer
:var mediaPlayer = MediaPlayer.Create( this, Resource.Raw.SoundResource);
Completion
event and release the player:mediaPlayer.Completion += delegate { mediaPlayer.Release(); mediaPlayer = null; };
Start()
method:mediaPlayer.Start();
Pause()
and Stop()
methods:mediaPlayer.Pause(); mediaPlayer.Stop();
If we want to stream sound from an asset or a remote URI, we construct a new MediaPlayer
object, which sets various options before starting:
MediaPlayer
constructor:var mediaPlayer = new MediaPlayer();
Music
, so lets execute the following code to add sound in our project:mediaPlayer.SetAudioStreamType(Stream.Music);
FileDescriptor
to the SetDataSource()
method:var fd = Assets.OpenFd("SoundAsset.mp3"); mediaPlayer.SetDataSource( fd.FileDescriptor, fd.StartOffset, fd.Length); fd.Close();
Alternatively, we could play a file from a content provider or remote URI using the SetDataSource()
method as well:
var uri = "http://example.org/audio.mp3"); mediaPlayer.SetDataSource(uri);
mediaPlayer.Completion += delegate { mediaPlayer.Release(); mediaPlayer = null; };
mediaPlayer.Error += delegate { mediaPlayer.Reset(); };
PrepareAsync()
method. When the preparation is complete, the playback can be started:mediaPlayer.Prepared += delegate { mediaPlayer.Start(); }; mediaPlayer.PrepareAsync();
Prepare()
method and then use the Start()
method to begin the playback:mediaPlayer.Prepare(); mediaPlayer.Start();
If we want to play audio, we make use of the MediaPlayer
type, which provides all the tools needed to play media. Media can be streamed from local sources, such as the file system, and remote sources, such as internet streaming.
For the most simplest of cases, we can just make use of the convenient static Create()
method overloads. This method will automatically prepare the player, and once the method returns, we can start playing the audio. The Create()
method can load and prepare local audio, for example a packaged resource or a URI, such as that from a content provider or the file system.
The MediaPlayer
object is quite expensive and should be disposed of as soon as we are finished with it. We let the system know that it should clean up the resources by invoking the Release()
method. If we are creating a sound that will be played once, we can attach an event handler to the Completion
event, which will allow us to clean up as soon as the event is fired. If the player is stopped before the end of the file, the Completion
event will not be triggered, and we will have to release the player ourselves.
We can control the player through the various methods available. The most basic is Start
, which will start the player, and Stop
, which will stop the playback. If we stop the playback, we will have to prepare the player before we can start playing again. If we invoke the Pause()
method, playback is paused and can be resumed by the Start()
method without having to prepare the player.
If we want to jump to a specific location in the playback, we can use the SeekTo()
method. This method is asynchronous and moves the playback to the specified millisecond location. If we want to be notified about the completion of the seek, we can subscribe to the SeekCompleted
event. Seeking is asynchronous as we may have to wait for the buffer to load enough data before playing.
To have greater control over what, and how, audio is played, we can use the default MediaPlayer
constructor. This provides us with a player that is not already set up and ready to play. If we use the constructor, we will have to set the audio type using the SetAudioStreamType()
method. The audio stream type can be, but is not limited to, Stream.Music
, Stream.Alarm
, or Stream.Notification
, depending on what we will play. For most cases, Stream.Music
will be used.
Creating the MediaPlayer
instance through the constructor allows us to play files from stream-based locations, such as the assets or a remote URL. To play a file from the assets, we can open the FileDescriptor
instance and then pass it to the SetDataSource()
method. Similarly, we can pass either a string or an Uri
instance to the SetDataSource()
method to specify what should be played.
As there may be a problem during the execution of asynchronous methods, we can subscribe to the Error
event. This allows us to receive notifications when an error occurs. If there is an error, the player goes into an invalid state and will have to be reset using the Reset()
method before we can perform any other operations.
Before we can play the audio, we have to prepare the player. We can do this either asynchronously or synchronously. If we prepare the player synchronously, it will block the current thread. If the player is streaming from a remote source, this may take some time; thus, it should always be done on a separate thread.
If we prepare the player asynchronously, it will not block the UI and will trigger the Prepared
event on completion. We can use this event to start the audio playback immediately, or we can delay the playback until a later time. To prepare asynchronously, we invoke the PrepareAsync()
method, and to prepare synchronously, we invoke the Prepare()
method.
The SoundPool
instance can also be used for small audio clips. It can repeat or play several sounds simultaneously. Sounds are loaded asynchronously, but should not exceed 1 MB.
Sounds are loaded using the Load()
method, which returns an ID that is used by the Play()
method to start the playback of that sound. The Play()
method returns another ID, which we use to control the playback through the Pause()
and Resume()
methods.