到目前为止,此代码适用于我测试的设备(所有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对象后发生的。
我想知道如何在上述条件下有效处理媒体播放器(或者)如何在媒体播放器对象完成播放后释放它?
答案 0 :(得分:3)
在OnCompletionListener()中停止上一个声音后单击按钮时发生异常。这是一个微妙的错误,很容易错过。这是正在发生的事情:
单击按钮,调用playSounds(),初始化全局MediaPlayer对象,并设置OnCompletionListener。
在OnCompletionListener()内部尝试释放触发onCompletion的玩家
现在,Java 按值传递。这意味着:
@Override
public void onCompletion(MediaPlayer mep)
mep是对你的全局mp对象的引用,因此你可以执行诸如stop(),reset()等操作,但是当你这样做时:
mep = null;
你是null'nig - 据我所知 - 那个引用(是一个值),而不是全局对象。
假设声音已完成(OnCompletionListener被调用),并且您单击另一个按钮,则会调用playSounds(),调用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 - 如果内部播放器引擎尚未初始化或已被释放
<强> 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