MediaPlayer how to stop multiple sounds from playb

2019-02-20 10:34发布

问题:

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();
       }
     });
 }
}

回答1:

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



回答2:

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".



回答3:

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);
      }
   }
 });