How do I release my media player after it is done

2019-08-17 12:18发布

问题:

I am creating a sound board and after clicking about 30 different sounds it stops working; I believe android is running out of memory. Below is my code. How can I implement .release() so that when the sound is done playing it is released? I don't really care if two things play at the same time; the clips are t0o short for this to be possible. I would just like to get my code set.

public class soundPageOne extends Activity {
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        setContentView(R.layout.soundsone);

        final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);
        Button playSound1 = (Button) this.findViewById(R.id.peter1Button);

        playSound1.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                pg1.start();

        }
    });

I have done a lot of searching around but due to my lack of java/android knowledge I have not been able to get anything to work. Thanks in advance, let me know if anyone needs anymore code.

回答1:

I left a comment, but I'll post an answer to show what I mean anyway...

The idea is that you have a set number of MediaPlayer instances that you can use. That way you never exceed the maximum number of instances. The array should be the length of the number of concurrent sounds you expect to be able to hear. If the sounds are local files, the length of time it takes to prepare the sounds should be almost negligible, so calling create inside the click handler should not result in terrible performance. Each of your buttons is associated with a particular resource, I suppose, so I set up a helper method to create and play the sounds for each button in the same way.

public class soundPageOne extends Activity {

    private MediaPlayer[] mPlayers = new MediaPlayer[2];
    private int mNextPlayer = 0;

    @Override
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        setContentView(R.layout.soundsone);
        Button playSound1 = (Button)this.findViewById(R.id.peter1Button);
        playSound1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startSound(R.raw.peter1);
            }
        });
    }

    public void onDestroy() {
        super.onDestroy(); // <---------------------- This needed to be there
        for (int i = 0; i < mPlayers.length; ++i)
            if (mPlayers[i] != null)
                try {
                    mPlayers[i].release();
                    mPlayers[i] = null;
                }
                catch (Exception ex) {
                    // handle...
                }
    }

    private void startSound(int id) {
        try {
            if (mPlayers[mNextPlayer] != null) {
                mPlayers[mNextPlayer].release();
                mPlayers[mNextPlayer] = null;
            }
            mPlayers[mNextPlayer] = MediaPlayer.create(this, id);
            mPlayers[mNextPlayer].start();
        }
        catch (Exception ex) {
            // handle
        }
        finally {
            ++mNextPlayer;
            mNextPlayer %= mPlayers.length;
        }
    }

}


回答2:

Create a class, say AudioPlayer with a SoundPool variable. Setup a constructor to initialise the AudioPlayer object and create a Play method. SoundPool works better for short sounds played many times and does not require you to release.

public class AudioPlayer {

    private SoundPool sPool = new SoundPool(Integer.MAX_VALUE, AudioManager.STREAM_MUSIC, 0);

    public AudioPlayer(Context c, int id){  
        sounds.put("1",sPool.load(c, id, 1));   
    }

    public void play(Context c) {
        sPool.play("1", 1, 1, 1, 0, 1f);
    }
}

So your class should look like

public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
    super.onCreate(savedState);
    setContentView(R.layout.soundsone);

    final AudioPlayer ap = new AudioPlayer(this, R.raw.sound);
    Button playSound1 = (Button) this.findViewById(R.id.peter1Button);

    playSound1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            ap.play();

    }
});


回答3:

Could you use a MediaPlayer.OnCompletionListener?

Something like:

public class soundPageOne extends Activity implements MediaPlayer.OnCompletionListener {
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        setContentView(R.layout.soundsone);
        final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);

        //***set the listener here***
        pg1.setOnCompletionListener(this);

        Button playSound1 = (Button) this.findViewById(R.id.peter1Button);

        playSound1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                pg1.start();
            }   
        });
    }

    //***this code will be executed once the sound finishes playing***
    @Override
    public void onCompletion(MediaPlayer mp) {
        //log messages, other things can go here
        mp.release();
    }


回答4:

Try something like this

Your activity class:

public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
    super.onCreate(savedState);
    setContentView(R.layout.soundsone);

    final AudioPlayer pg1 = new AudioPlayer();
    Button playSound1 = (Button) this.findViewById(R.id.peter1Button);

    playSound1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            pg1.play(this, R.raw.sound);

    }
});

}

This is another Java Class:

public class AudioPlayer {

private MediaPlayer mPlayer;

public void stop() {
    if (mPlayer != null) {
        mPlayer.release();
        mPlayer = null;
    }
}

public void play(Context c, int sound) {

    stop();

    mPlayer = MediaPlayer.create(c, sound);

    mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        public void onCompletion(MediaPlayer mp) {
            stop();
        }
    });

    mPlayer.start();
}

public boolean isPlaying() {
    return mPlayer != null;
}

}