I am attempting to play a sound using a MediaPlayer object, but I cannot seem to get it to work despite my best efforts. The sound simply refuses to play.
It's a short sound, that is supposed to be played when the screen is touched, meaning it will have to be repeated many times without too much delay. Knowing this I followed the state diagram, http://developer.android.com/reference/android/media/MediaPlayer.html. I can't seem to see what exactly is wrong with my sequencing of method calls.
MediaPlayer mp = MediaPlayer.create(this.getContext(), R.raw.select2);
try {
mp.prepare();
mp.start();
Log.e("debug","sound played");
}
catch(Exception e) {}
mp.stop();
You call prepare() on the mediaplayer, but the create() call you use prepares the player automatically, this causes an IllegalStateException when you try to call prepare() again, and you are sent to your catch() (you would have noticed this if you handled the exception in some way, i.e. printing the stack trace).
MediaPlayer player = MediaPlayer.create(this.getContext(), R.raw.select2);
we configure the music player by setting some of its properties as shown below
player.setWakeMode(getApplicationContext()PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
try {
player.prepare();
player.start();
Log.e("debug","sound played");
} catch(Exception e) {}
player.stop();
Related
I was using SoundPoolto play sound effects but now I need to switch to MediaPlayer as I need to listen to the onCompletion event to trigger a GUI change.
My questions are:
The sound files are very small, less than 30kB, Can I use
MediaPlayer in the main thread?
Can I just call mediaPlayer.stop() after the play is done like so,
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
//Do some GUI changes
mediaPlayer.stop();
mediaPlayer.release();
}
});
Then to play another effect will do this:
mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start();
So, is it ok to create and release every time I play an effect?
Initialize your MediaPlayer
MediaPlayer mediaPlayer = new MediaPlayer();
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
Look at the MediaPlayer lifecycle:
When the track is complete the MediaPlayer is in Stopped state and you wan't to change the track, so:
call reset()' to get toIdlethensetDataSourcethenprepareand finallystart()`.
The sound files are very small, less than 30kB, Can I use MediaPlayer in the main thread?
Irrespective of the size of your audio file, you should run MediaPlayer on its own thread, especially if you are playing a file from network. Not doing so may cause ANR (In your case I don't think much to worry about)
Can I just call mediaPlayer.stop() after the play is done
There is no need to release the MediaPlayer after every audio file. Release it once you are no longer going to use it.
how can I load a new sound
AssetFileDescriptor audio = context.getResources().openRawResourceFd(R.raw.next_audio);
mediaPlayer.setDataSource(audio);
My app is a music pad, which allows the user to create their own music by pressing buttons that will play a specific sound, and if the users presses more than one button there will be more sounds being played at the same time.
I want to stop all sounds when the onPause() gets called. But I realized that if I have more than one sound being played by the same Media player Object it only stops the last sound that was attributed to it, and the others stay on playing.
It would be very unpleasant for the user to receive a call and having my app sounds still on playing :p
Any help would be appreciated.
#Override
protected void onPause() {
super.onPause();
try {
while (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mMediaPlayer.release();
}
}catch (IllegalStateException e){
//Do nothing
}
}
EDIT
I tried to implement SoundPool API but since my app is very dynamic (users can upload their samples and also record using mic). And I have everything already implemented and working well, it would be a mess to change it now to another API rather than MediaPlayer. Is there any way to stop all sounds that were attributed to the MediaPlayer object and that are currently being played? maybe accessing to some other classes and using other methods to stop all the sounds?
I would suggest you look into the SoundPool API. It looks like that would be well suited for your task. It allows you to preload sound files and play them independently.
The SoundPool class manages and plays audio resources for applications.
A SoundPool is a collection of samples that can be loaded into memory from a resource inside the APK or from a file in the file system. The SoundPool library uses the MediaPlayer service to decode the audio into a raw 16-bit PCM mono or stereo stream. This allows applications to ship with compressed streams without having to suffer the CPU load and latency of decompressing during playback.
After a few research and trial and error there is no way that I discovered to stop all sounds being played by the same MediaPlayer Object, you can only control the last sound being attributed to it, all the other will continue until they end or the app gets destroyed.
Ok so what I did was:
I created an object for each key sound of my music pad, and Override the onPause() with the following code:
#Override
protected void onPause() {
super.onPause();
if (mAudioManager.isMusicActive()){
for (MediaPlayer aMMediaPlayer : mMediaPlayer) {
if (aMMediaPlayer != null) {
try {
if (aMMediaPlayer.isPlaying()) {
aMMediaPlayer.stop();
aMMediaPlayer.release();
}
} catch (IllegalStateException e) {
//Do nothing
}
}
}
}
}
In iPhone, we can use AVQueuePlayer, AVAsset, and AVPlayerItem if we want to play a list of movies sequentially. It is very convenient over MPMediaPlayer and MPMediaPlayerController in iPhone. From, apple documentation:
AVQueuePlayer is a subclass of AVPlayer you use to play a number
of items in sequence.
So, my question is, is there anything like that in android which we can use instead of MediaPlayer and VideoView.
In Android, there is no automatic way of playing sounds in sequence (at least not a "built-in" one). If you need to start playback of the second sound when the first one finishes, you can use method
public void setOnCompletionListener (MediaPlayer.OnCompletionListener listener)
of the MediaPlayer to start the second playback when the first one is finished. Something like this:
MediaPlayer player = MediaPlayer.create(context, uriOfFirstSound);
player.setOnCompletionListener(new OnCompletionListener(
public void onCompletion(MediaPlayer mp) {
mp.setDataSource(context, uriOfNextSound);
mp.prepare();
mp.start();
}
));
player.prepare();
player.start();
Naturally, if you have more than two sounds, you can do this in a loop.
I have to play sounds on GUI events, like clicking buttons etc. For this purpose, I call the following native code from WebView:
MediaPlayer _SoundPlayer = new MediaPlayer();
private void playSound(String sound)
{
_SoundPlayer.reset();
try
{
AssetFileDescriptor afd = getAssets().openFd("sound/" + sound + ".mp3");
_SoundPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
_SoundPlayer.prepare();
_SoundPlayer.start();
}
catch (Exception e) { }
}
The problem is there is a delay ~500ms between an event and its sound. Can I optimize playing sound somehow, maybe, creating a dedicated MediaPlayer instances for every kind of sound?
Regards,
Use SoundPool for low-latency media playback, instead of MediaPlayer.
I see that this already has an accepted answer, but I would add that there is no complete solution at this time: Android currently has very large audio latency. Devs are still waiting for a good solution.
This issue refers to the NDK, but the issue is general:
http://code.google.com/p/android/issues/detail?id=3434
I am working on video player in android.when i created surface holder in on create method ,it did not create.but when i created the surface holder in button onclick method,its created
My coding is,
preview=(VideoView)findViewById(R.id.surface);
preview.setEnabled(true);
preview.bringToFront();
holder=preview.getHolder();
holder.setFixedSize(400, 400);
mp=new MediaPlayer();
mp.setDataSource("path");
mp.setDisplay(holder);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setOnBufferingUpdateListener(playerActivity.this);
mp.setOnPreparedListener(playerActivity.this);
mp.prepare();
mp.start();
mp.prepare();
mp.start();
prepare() is asynchronous, which means, it might not be finished when you already call the mp.start. What do you mean by 'surface not created'? Do you just mean the video doesn't play?
Anyway, you should use an MediaPlayer.OnPreparedListener and start the media in onPrepared().