Search code examples
androidmedia-playerandroid-mediaplayer

Android - MediaPlayer stops playing


I am creating an app where you shake the device and it plays a sound. I have everything working, but when I shake the device for a long period of time (5 Seconds) the sound stops playing. Here is my code:

MediaPlayer mp = null;
private void executeShakeAction() {
    Random random = new Random();
    int nextInt = random.nextInt(3);
    if(nextInt == 0) {
        mp = MediaPlayer.create(this, R.raw.cowbell);
    }else if(nextInt == 1){
        mp = MediaPlayer.create(this, R.raw.cowbell1);
    }else{
        mp = MediaPlayer.create(this, R.raw.cowbell3);
    }
    mp.start();
}

Solution

  • If you shake your device too often, the audio file don't have time to complete. That makes the life so hard for Android, that it eventually gives up and stops playing.

    Suggestions:

    • Avoid creating an instance of MediaPlayer, if it is playing, e.g

      if (mp != null && mp.isPlaying()) return;

    • Use SoundPool instead of MediaPlayer, which is especially designed to play short sounds (instead of music or videos, like MediaPlayer).

    • If you insist on using MediaPlayer, create it once instead of re-creating it all the time. This code is still very far from perfection, but hopefully will do the job:

    private final MediaPlayer mp = new MediaPlayer();
    private final Random random = new Random();
    private static final int[] SoundResIds = {R.raw.cowbell, R.raw.cowbell1, R.raw.cowbell2};
    private synchronized void executeShakeAction() {
        if (!mp.isPlaying()) 
           try {
              mp.reset();  // Clears mp state  
              int soundResId = SoundResIds[random.nextInt(SoundResIds.length)];
              AssetFileDescriptor afd = getResources().openRawResourceFd(soundResId);
              mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
              afd.close();
              mp.prepare();
              mp.start();
           } catch (Exception ex) {
              ex.printStackTrace();
           }
    }