I've started messing about with Android recently. I'm trying to kick something off once a sound has finished and return to the previous activity.
spool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
int soundID = spool.load(this, card.getSound(), 1);
spool.play(soundID, 500, 500, 1, 0, 1f);
I can't see anything about getting the sound duration or any sort of sound end event. I know SoundPool can be a pain so I'm willing to ditch it.
How can I do something after a sound has ended? Can I do this with SoundPool or am I barking up the wrong tree?
Thanks. I'm pretty new to Android and Java so open to all suggestions.
If the multi-stream handling functionality of SoundPool isn't necessary, you can use MediaPlayer, which does have the callbacks you're asking about.
A rough example:
MediaPlayer mp = MediaPlayer.create(Activity.this, soundId);
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// do something
}
});
mp.start();
Just make sure that you hang onto the MediaPlayer reference somewhere so that it doesn't get GC'd before your OnCompletionListener fires :)
Related
I want to play mp3 file from res/raw folder when user click on button
my code is below:
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
MediaPlayer mp = MediaPlayer.create(MainActivity.this,
R.raw.click);
mp.start();
}
});
Work well but take some time to play after button click. please, anyone, give me a solution.
Thanks
Loading time depends on the buffer size of the MediaPlayer (which is hardcoded in the firmware) and that there is nothing that can be done to change it. Read more here.
Option 1:
Instead of creating the media player and then calling start() method in the onClick of the button, you can initialize the mediaPlayer in onCreate() of activity.
As for the button click implementation, you need to call mediaPlayer.start() only.
Option 2:
You can use SoundPool API provided by Android. This has lower latency compared to MediaPlayer API. SoundPool are recommended mainly for playing short clips.
This is as a result of the buffer size of media player.
Try using SoundPool for a more responsive playback. You can see an implementation of it here.
SoundPool soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 100);
HashMap<Integer, Integer> soundPoolMap soundPoolMap = new HashMap<Integer, Integer>();
soundPoolMap.put(soundID, soundPool.load(this, R.raw.click, 1));
Start the sound with soundPool.play(soundId, 1, 1, 1, 0, 0);
I have several GridView items that play a small .ogg file when they are selected. They are played using the SoundPool class, however this class seems very intermittent - sometimes the sound plays, sometimes it doesn't; there is no pattern to this so I am having trouble figuring out why it's doing it.
Here is my code:
public void playSelectionSound(){
SoundPool sp = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
int soundId = sp.load(this, R.raw.char_select, 1);
sp.play(soundId, 1, 1, 0, 0, 1);
}
I eventually resorted to switching to MediaPlayer instead of SoundPool:
MediaPlayer mp = MediaPlayer.create(this, R.raw.char_select); //open media player
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
mp.start(); //play the sound
Works everytime.
You shouldn't try to play it immediately after the load since the load can take time. Instead, you should use SoundPool.OnLoadCompleteListener() and play it in that callback. Here you can be sure that soundpool has loaded successfully.
When i click button plays sound on my app, but keep clicking for a while doesn`t play anymore. Maybe it is memory issue? Could you solve me my issue? Here is implemented play sound via SoundPool: when i click button i called play method: and play method works background thread
private void play(int resId) {
soundPool = buildBeforeAPI21();//TODO: refactor with deprecated constructor
soundPool.load(activity, Integer.parseInt(resId), 1);
}
public SoundPool buildBeforeAPI21() {
if (soundPool == null) {
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (status == 0) {
soundPool.play(sampleId, 1.0f, 1.0f, 1, 0, 1.0f);
}
}
});
}
return soundPool;
}
Don't create a new SoundPool with each click. That is extremely wasteful. Do this instead:
1) Create the SoundPool just once
2) Load it with all the sounds you want to play, just once
3) Wait for all the sounds to load
4) Just call soundPool.play() with each click.
Maybe this answer cames too late; but here we go. The problem is in the line
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
That '2' number is the int maxStreams, following the documentation "the maximum number of simultaneous streams for this SoundPool object" (you can go deep on this here). Now change it and set it to 10, for example, and try again. And after that, you cand adjust it as your wishes. So:
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
Hope this helps (if it is still necessary).
I'm playing a sound through STREAM_ALARM:
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(context, notificationSoundUri);
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mp.prepare();
It worked ok until I tried on Android 6. On Android 6 sound doesn't play from beginning, so if I play short sounds, no sound is heard. I tried using seekTo(0) and initializing MediaPlayer in other ways.
It only happens in Android 6 when using STREAM_ALARM (other streams work well).
Any help?
EDIT: I realized that sound actually starts playing from start, but at very low volume, and after about 2 seconds volume increases... do you know how to deactivate this behavior?
It sounds like an equalization problem (maybe this audio stream comes with an audioSessionId which is already handled by the system equalizer?)
I will try the following trick before the MediaPlayer initialization:
1) Change the STREAM_ALARM volume
AudioManager mAudioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, maxVolume, 0 /*flags*/);
2) Set volume after prepare()
//...
mp.prepare();
mp.setVolume(1.0f, 1.0f);
3) Change the audioSessionId
//...
mp.setAudioStreamType(AudioManager.STREAM_ALARM);
mp.setAudioSessionId(CUSTOM_ID); //manually assign an ID here
//...
UPDATE
4) Try to use the SoundPool API instead of MediaPlayer and see if the problem persists (I also suspect that this is a device-dependent issue).
5) Try to call start() ==> pause() ==> start() on MediaPlayer
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
mp.pause();
mp.start();
}
6) Try to trick the initial "low volume" period using the following logic:
before play, set volume to 0
play
after 2 seconds of playback, seek to position 0 (this may consume the silent period)
set the volume to max
play again
In this way, you may be able to do a normal playback, with an initial delay of few seconds.
Let us know your progress, I'll update this answer accordingly with more information and suggestions.
I have a class that extends Service, where i have a MediaPlayer that manages the background music of my app.
MediaPlayer player = MediaPlayer.create(this, R.raw.background_music);
player.setLooping(true);
The problem is that it doens't "loop" well: I mean, when the mp3 file ends, there's a second of silence before it starts again.
But, in the mp3 file, actually, there's not any second of silence.
How can i solve this problem?
You can't. This bug has been there for ages now, but they still didn't fix it and it does not look like they are going to do it in the close future!
http://code.google.com/p/android/issues/detail?id=18756
You can try to use SoundPool to play your audio file (it loops very well and without delay, however might be inappropriate for some audio resources).
Here is some kind of implementation (deprecation removal and appropriate closing of resource is left as a homework :))
SoundPool pool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
afd = getResources().openRawResourceFd(audioResource);
pool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (0 == status) {
soundPool.play(sampleId, 1f, 1f, 10, -1 /* looping parameter */, 1f);
}
}
});
pool.load(afd, 10);
afd.close();
From other side if MediaPlayer is a must have you might look into method setNextMediaPlayer. So the idea is to initialize several MediaPlayers for the same file (what a mess) and set them in a smart way.