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

问题描述 投票:0回答:2

到目前为止,此代码适用于我测试的设备(所有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对象后发生上述错误。

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

android media-player android-mediaplayer
2个回答
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被调用),并且您单击另一个按钮,则调用playSounds(),调用stopSounds(),您正在检查: if (mp != null ... <-------- here, mp will NOT be null 在同一行,你正在检查 mp.isPlaying()) { <----------- THIS IS CAUSING AN EXCEPTION 为什么?请记住,在OnCompletionListener中,您调用了reset()和release(),它们分别将MediaPlayer的状态置于空闲状态和结束状态,并且正如文档所述,如果在wrong状态中调用isPlaying(),则会抛出异常: IllegalStateException - 如果内部播放器引擎尚未初始化或已被释放

解:

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

@Override
public void onCompletion(MediaPlayer mep) {
    mep.stop();
    mep.reset();
    mep.release();

    //null the global MediaPlayer object
    mp = null;
}

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

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


0
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.