i have a button that plays a sound.
When i push the button multiple times, it plays the sound multiple times.
This is oke, i want this.
But when i click the stop button it must stop all sounds currently playing.
I used:
while (mediaPlayer.isPlaying()){mediaPlayer.stop();}
but it is not working, the sounds keep on playing. Can someone help me?
Here is my full code:
public class HelloSoundboard extends Activity {
MediaPlayer mediaPlayer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button item1 = (Button)findViewById(R.id.item1);
item1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mediaPlayer = MediaPlayer.create(getBaseContext(), R.raw.atyourservice);
mediaPlayer.start();
}
});
Button stop = (Button)findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
while (mediaPlayer.isPlaying()){mediaPlayer.stop();}
// mediaPlayer.stop();
}
});
}
}
SoundPool is a much better alternative for this purpose. I would caution strongly against instantiating multiple MediaPlayer instances as most systems do not have the resources to generate many parallel active instances. You wil find on many device that hitting the button upwards of 5 times will cause a memory based crash.
As far as stopping all active streams, there is not baked-in function for this, but it's easy to accomplish in a manner to similar to your existing code. As a side note, there is an autoPause() method, which halts all streams, but it doesn't truly end their playback (as the method name insinuates). Here is a simple example to manage your audio streams:
//SoundPool initialization somewhere
SoundPool pool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
//Load your sound effect into the pool
int soundId = pool.load(...); //There are several versions of this, pick which fits your sound
List<Integer> streams = new ArrayList<Integer>();
Button item1 = (Button)findViewById(R.id.item1);
item1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
int streamId = pool.play(soundId, 1.0f, 1.0f, 1, 0, 1.0f);
streams.add(streamId);
}
});
Button stop = (Button)findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for (Integer stream : streams) {
pool.stop(stream);
}
streams.clear();
}
});
It is much more memory efficient to manage a list of streamID values than MediaPlayer instances, and your users will thank you. Also, note that it is safe to call SoundPool.stop() even if the streamID is no longer valid, so you don't need to check for existing playback.
HTH
I'm not sure about this, but I think is better if you use a SoundPool.
"SoundPool is designed for short clips which can be kept in memory decompressed for quick access, this is best suited for sound effects in apps or games".
"MediaPlayer is designed for longer sound files or streams, this is best suited for music files or larger files".
You can use a list of MediaPlayers:
List<MediaPlayer> mps = new ArrayList<MediaPlayer>();
Button item1 = (Button)findViewById(R.id.item1);
item1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
MediaPlayer mp = MediaPlayer.create(getBaseContext(), R.raw.atyourservice);
mp.start();
mps.add(mp);
}
});
Button stop = (Button)findViewById(R.id.stop);
stop.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for (int i = mps.size() - 1; i >= 0; --i) { //changed ++i to --i
if (mps.get(i).isPlaying()) {
mps.get(i).stop();
}
mps.remove(i);
}
}
});
Related
I'm currently developing application and i want to control playing sound file on different headphones sides ex the first time on the left side and second time on the right side is there any way to achieve this ?
Yes there is a way. MediaPlayer.setVolume(float leftVolume,float rightVolume).
In the following snippet we're playing an .mp3 file contained in assets folder(note if you have multiple files in the folder you should check this answer). By pressing one of the Button objects the song is played only out of the left or the right headphone :
MediaPlayer AudioObj = new MediaPlayer();
AudioObj.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mediaPlayer) {
findViewById(R.id.progressBar).setVisibility(View.INVISIBLE);
Button btnl = (Button) findViewById(R.id.btnPlayleft);
Button btnr = (Button) findViewById(R.id.btnPlayright);
btnl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mediaPlayer.setVolume(1, 0);
mediaPlayer.start();
}
});
btnr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mediaPlayer.setVolume(0, 1);
mediaPlayer.start();
}
});
}
});
AudioObj.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
AssetFileDescriptor afd = getAssets().openFd("audio.mp3");
AudioObj.setDataSource(afd.getFileDescriptor());
}catch (IOException e){}
AudioObj.prepareAsync();
P.S.
The audio file must be stereo.
Whether you want to check if the headset are plugged or not before playing the audio in order to prompt a message or do something else :
AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if(!audioManager.isSpeakerphoneOn()){
//prompt a message or do something else
}
When I touch sound play sound but when I touch another it stop play this sound. I need to sound don't stop playing.
public void onClick(View v) {
mSoundManager.playSound(1);
}
});
Button SoundButton2 = (Button)findViewById(R.id.sound2);
SoundButton2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mSoundManager.playSound(2);
}
});
Button SoundButton3 = (Button)findViewById(R.id.sound3);
SoundButton3.setOnClickListener(new OnClickListener() {`enter code here`
public void onClick(View v) {
mSoundManager.playSound(3);
Your code in my comment shows that you have initialized your sound pool with 1 as the value for maxStreams. If you set this value to the maximum amount of sounds you want to be able to play at the same time, it should work.
You have mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
If you change that to mSoundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
You will be able to play 5 sounds at once.
I'd need to take a look at your sound manager class to have a better idea of what is wrong with it. However, it is perfectly possible.
Take a look at this:
Playing sounds simultaneously Android
I need to have the same short wav file (1 second) play each time the user presses a single button. I have the following code that works for about 30 clicks and then the app "Force closes" on the device. I think what is going on is that new instances of media player are being created and then the instances build up (approx 30 clicks) and the app crashes. So I then added the "release" instance in the hope that on button-click the wav would play and then the mediaplayer would be released. However, it doesnt work that way. With the mp.release() no sound is played possibly becaue the medaiplayer gets released too soon for the user to hear the sound?
Anyone have a good tip to help me getting this to work? Thank you all so much.
Button button2 = (Button) findViewById(R.id.button10);
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.clicker);
mp.start();
mp.release();
Its simple just create the MediaPlayer once, and play it over time.
private MediaPlayer mp;
public void onClick(View v) {
// Perform action on click
if (mp == null){
mp = MediaPlayer.create(getApplicationContext(), R.raw.clicker);
}
mp.start();
}
Why use MediaPlayer, when SoundPool is better suited for small audio files? As a base you could use this:
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 70);
final HashMap<Integer, Integer> soundPoolMap = new HashMap<Integer, Integer>();
final int soundID = 4;
soundPoolMap.put(soundID, soundPool.load(this, R.raw.wav_sound, 4));
soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener()
{
public void onLoadComplete(SoundPool soundPool, int sampleId, int status)
{
if (sampleId == 4)
{
soundPool.play(4, 50, 50, 1, 0, 1f);
}
}
});
Here is the simple solution that will work
MediaPlayer mp;
mp = MediaPlayer.create(getApplicationContext(), R.raw.clicker);
public void onClick(View v) {
// Perform action on click
if(mp.isPlaying())
{
mp.stop();
mp.reset();
mp.release();
}
mp = MediaPlayer.create(getApplicationContext(), R.raw.clicker);
mp.start();
This is will check if mediaplayer is already playing..If it already playing it will stop and release it and then initialize that mediaplayer(mp) object and start the mediaplayer.
If it is not playing it will execute the code after the if statement and the start the media player after initialzing the mediaplayer object(mp in this case)
To learn more about MediaPlayer study this http://developer.android.com/reference/android/media/MediaPlayer.html. Study the Mediaplayer life cycle
I'm working on a project in which I have to load 6 different sounds in one activity and play all sound on button click.The sound file are not so big,but the problem is that maybe they will be more.So my question is which is the fastest way to load sound files in a single activity.For test purposes I used res/raw folder to store the sound files and tried with two different method to play the files,but the result did not satisfied me.Here is the two different types of code :
Method 1:
Button first = (Button) findViewById(R.id.one);
Button second = (Button) findViewById(R.id.two);
first.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(SoundFXActivity.this, R.raw.drumtwo);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
}
});
second.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(SoundFXActivity.this, R.raw.drumone);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
}
});
Method 2:
private SoundPool spool;
private int soundID,soundID2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
spool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundID = spool.load(this, R.raw.drumone, 1);
soundID2 = spool.load(this, R.raw.drumtwo, 1);
Button three = (Button) findViewById(R.id.three);
three.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Sound();
}
});
}
public void Sound(){
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
float volume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
spool.play(soundID, volume, volume, 1, 0, 1f);
};
But the problem is that the both methods are slow..I need to find a way a faster way to play the sounds..but now there is like almost a second after I click the button to play the sound.
Can you give me some advice how to play the sounda faster.Should I load them into a cache when the application starts or save them in database or somewhere else (I don't think database is a good option as a matter of fact,but I want to hear some suggestions).Or maybe load them from assets folder,but I think it still going to be slow.
So any ideas or suggestions?
Thanks in advance!
You could create the media players in your onCreate and then the buttons will just make them play. That would be the easiest solution, I would say.
Alternatively, depending on how important it is to you and how much work you want to do, you could consider using JetPlayer:
here's android development page for media:
http://developer.android.com/guide/topics/media/index.html
The page on the JetPlayer class:
http://developer.android.com/reference/android/media/JetPlayer.html
and the page on creating the JET files:
http://developer.android.com/guide/topics/media/jet/jetcreator_manual.html
If you implemented this it would likely work best but would definitely be the most work.
JetPlayer basically lets you have one audio file (i think it's a MIDI file) with multiple tracks that you mute and unmute as you please. I have no personal experience with it and have just read the docs some, but it seems like it would be very useful for any situation with more than one sound.
Edit: Also, it's worth mentioning this mailing list and in case the link ever changes this google search in case anyone is interested in android audio topics.
If you want to have the less delay you must use OpenSL in c++, From jelly bean is the faster sound player
SoundPool is working fine, you can see an example with the Hexiano project. However, you must preload the sounds into SoundPool, because it takes a lot of time to decode the file and store them in-memory before being able to use them. But once the sounds are loaded, there's no noticeable delay between key press and sound output.
How do I set up an audiofile to play when a user touches an image.
Where should I store the audio file and what code should I use to actually play the file?
I don't want to bring up the MediaPlayer interface or anything like that.
I was thinking of doing it like this:
foo = (ImageView)this.findViewById(R.id.foo);
foo.setOnClickListener(this);
public void onClick(View v) {
if (foo.isTouched()) {
playAudioFile();
}
}
Thanks
This won't create a bring up the MediaPlayer interface... it will just play the sound you want.
Button boton = (Button) findViewById(R.id.boton);
boton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(TestSonido.this, R.raw.slayer);
mp.start();
}
});
In this case, R.raw.slayer represents an audio file called slayer.mp3 that is stored in the res/raw/ folder and once you click the button the droid will rock you...
You can also achieve the same using SoundPool.
MediaPlayer first loads the whole sound data in memory then play, so it produces some lag when we switch among sounds frequently.
SoundPool is a better option with small size sound file and produces better result with .ogg media file.
SoundPool pl = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
// 5 indicates the maximum number of simultaneous streams for this SoundPool object
pl.setOnLoadCompleteListener(new OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
// The onLoadComplet method is called when a sound has completed loading.
soundPool.play(sampleId, 1f, 1f, 0, 0, 1);
// second and third parameters indicates left and right value (range = 0.0 to 1.0)
}
});
Button btn = findViewById(R.id.boton);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int sound = pl.load(this, R.raw.sound_01, 0);
}
});
public void aud_play(View view) {
if (!mp.isPlaying()) { //If media player is not playing it.
mp = MediaPlayer.create(this, R.raw.audio_name);
mp.start();
} else {// Toast of Already playing ...
}
}