3

我有一个带有播放声音的按钮的 android 应用程序。播放声音的代码:

if (mp != null)
{
    mp.release();
}
mp = MediaPlayer.create(this, R.raw.match);
mp.start();

mp 是活动中的一个字段:

public class Game extends Activity implements OnClickListener {
/** Called when the activity is first created. */
//variables:
MediaPlayer mp;
//...

该应用程序运行正常,但在模拟器上单击按钮约 200 次后,应用程序崩溃并给了我这个错误https://dl.dropbox.com/u/5488790/error.txt(不知道如何发布它在这里,所以它会显得体面)
我假设这是因为 MediaPlayer 对象消耗了太多内存,但是 mp.release() 不应该处理这个问题吗?我在这里做错了什么?

4

4 回答 4

3

如果您要为按钮附加声音效果,MediaPlayer通常对于此操作来说太重了。每次只是将声音数据加载到内存中,您都会得到不必要的延迟。你应该看看 using SoundPool

MediaPlayer在任何一种情况下,都没有正当理由每次都释放并重新创建。如果您决定使用MediaPlayer,请通过单击按钮来控制您拥有的单个实例。

MediaPlayer mp;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //Other init code

    //Create the player this way so it doesn't auto-prepare
    mp = new MediaPlayer();
    AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.match);
    mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
    afd.close();
}

public void onDestroy() {
    super.onDestroy();
    //Release it only when no longer needed
    mp.release();
    mp = null;
}

public void onButtonClick(View v) {
    if (mp.isPlaying()) {
        mp.stop();
    }
    //Play the sound
    mp.prepare();
    mp.start();
}

SoundPool希望对您有所帮助,但如果这种声音只是一个短暂的效果,我强烈建议您改用它。

于 2012-09-06T15:46:34.557 回答
2

看起来您的代码应该可以工作,但显然release()并没有真正发布所有内容。

可能是因为R.raw.match每次想要播放声音时都必须重新加载。如果R.raw.match只是一个简短的音效,那么您可能要考虑SoundPool改用。

如果您使用SoundPool,您只需加载R.raw.match一次,这可能会防止内存问题。

本教程有一个很好的例子来说明如何使用它:http ://www.vogella.com/articles/AndroidMedia/article.html#tutorial_soundpool

您几乎只需创建一个 SoundPool 实例,然后加载一次声音并在需要时播放它。

希望这可以帮助!

编辑

如果你想使用媒体播放器...

public class Blah extends Activity implements OnClickListener {
   MediaPlayer mp;

   @Override 
   public void onCreate(Bundle b)
   {
      // blah blah
      mp = MediaPlayer.create(R.raw.match);

      // blah blah
   }

   @Override
   public void onClick(View v)
   {
      if (v.getId() == yourButtonID)
      {
         // play sound from beginning
         mp.seekTo(0);
         mp.start();
      }
   }
}

这样,您只需创建一个实例,并且无论何时要播放它,只需将其倒回到开头然后播放即可。

于 2012-09-06T15:46:37.923 回答
0

尝试

if (mp != null)
        {
            mp.release();
        }
        mp = MediaPlayer.create(this, R.raw.match);
        mp.prepare(); // not needed 
        mp.start();

祝你好运!!

于 2012-09-06T15:35:48.113 回答
0

如果您持有 MediaPlayer,请在活动结束时释放它

@Override
void onDestroy() {

    if (mMediaPlayer != null) {
        mMediaPlayer.release();
        mMediaPlayer = null;
    }

    super.onDestroy();
}
于 2020-02-10T09:38:21.950 回答