如何有效地处理媒体播放器?

时间:2014-01-22 12:29:33

标签: android media-player android-mediaplayer

到目前为止,此代码适用于我测试的设备(所有mdpi级设备)。

private void stopSounds() {
    if (mp!=null && mp.isPlaying()) {
        mp.stop();
        mp.reset();
        mp.release();
        mp = null;
    }
}
private void playSounds(int sound) {
    stopSounds();
    mp = new MediaPlayer();
    mp = MediaPlayer.create(this, sound);
    mp.start();
    }
@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.button1:
        playSounds(R.raw.correct_amazing);
        break;
    case R.id.button2:
        playSounds(R.raw.correct_awesome);
        break;
    case R.id.button3:
        playSounds(R.raw.correct_chick);
        break;
    default:
        break;
    }
}

到目前为止没有错误或异常,我考虑在完成(播放)后释放MediaPlayer对象(mp)。

所以我只是尝试在playSounds()中添加onCompletionListener,如下所示:

    private void playSounds(int sound) {
    stopSounds();
    mp = new MediaPlayer();
    mp = MediaPlayer.create(this, sound);
    mp.start();

    mp.setOnCompletionListener(new OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mep) {
            mep.stop();
            mep.reset();
            mep.release();
            mep = null;
        }
    });
}

然后它开始抛出“IllegalStateException”,如下所示,

  01-22 17:51:24.150: W/dalvikvm(3081): threadid=1: thread exiting with uncaught exception (group=0x41e2e498)
  01-22 17:51:24.150: E/test(3081): Exception
  01-22 17:51:24.180: E/AndroidRuntime(3081): FATAL EXCEPTION: main
  01-22 17:51:24.180: E/AndroidRuntime(3081): java.lang.IllegalStateException
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at android.media.MediaPlayer.isPlaying(Native Method)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at com.Test.mediaplayertert.MPActivity.stopSounds(MPActivity.java:30)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at com.Test.mediaplayertert.MPActivity.playSounds(MPActivity.java:39)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at com.Test.mediaplayertert.MPActivity.onClick(MPActivity.java:61)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at android.view.View.performClick(View.java:4106)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at android.view.View$PerformClick.run(View.java:17150)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at android.os.Handler.handleCallback(Handler.java:615)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at android.os.Handler.dispatchMessage(Handler.java:92)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at android.os.Looper.loop(Looper.java:137)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at android.app.ActivityThread.main(ActivityThread.java:4793)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at java.lang.reflect.Method.invokeNative(Native Method)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at java.lang.reflect.Method.invoke(Method.java:511)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:808)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:575)
  01-22 17:51:24.180: E/AndroidRuntime(3081):   at dalvik.system.NativeStart.main(Native Method)

我的问题是我在屏幕上有6个按钮,只要他们在活动上,用户就会按下它们,我需要分别播放“正确”的声音,“错误的”声音。因此,需要持续的压力。

我的上述错误是在通过setOnCompletionListener()释放mp对象后发生的。

我想知道如何在上述条件下有效处理媒体播放器(或者)如何在媒体播放器对象完成播放后释放它?

2 个答案:

答案 0 :(得分:3)

在OnCompletionListener()中停止上一个声音后单击按钮时发生异常。这是一个微妙的错误,很容易错过。这是正在发生的事情:

  1. 单击按钮,调用playSounds(),初始化全局MediaPlayer对象,并设置OnCompletionListener。

  2. 在OnCompletionListener()内部尝试释放触发onCompletion的玩家

  3. 现在,Java 按值传递。这意味着:

    @Override
    public void onCompletion(MediaPlayer mep)
    

    mep是对你的全局mp对象的引用,因此你可以执行诸如stop(),reset()等操作,但是当你这样做时:

    mep = null;
    

    你是null'nig - 据我所知 - 那个引用(是一个值),而不是全局对象。

  4. 假设声音已完成(OnCompletionListener被调用),并且您单击另一个按钮,则会调用pl​​aySounds(),调用stopSounds(),您正在检查:

    if (mp != null ...  <-------- here, mp will NOT be null
    

    并在同一行中检查

    mp.isPlaying()) { <----------- THIS IS CAUSING AN EXCEPTION
    

    为什么呢?请记住,在OnCompletionListener中,您调用了reset()和release(),它们分别将MediaPlayer的状态置于空闲状态和结束状态,正如文档所述,如果在{{1中调用isPlaying(),则会抛出异常state:

      

    IllegalStateException - 如果内部播放器引擎尚未初始化或已被释放

  5. <强> SOLUTION:

    略微修改OnCompletionListener,使其为您的全局MediaPlayer对象为空:

    wrong

    以下是一些关于Java是按值传递的优秀文章,它的解释比我的尝试要好得多:)

    Is Java "pass-by-reference" or "pass-by-value"?
    http://javadude.com/articles/passbyvalue.htm

答案 1 :(得分:0)

这些音频文件有多长/多长?您是否考虑过使用SoundPool而不是MediaPlayer?这里有一些很好的信息:

http://developer.samsung.com/android/technical-docs/Playing-Audio-and-Video-in-Android