2014-01-22 28 views
0

此代码适用于我测试过的设备,(所有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)。

于是我就尝试添加onCompletionListener如下,playSounds():

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个按钮屏幕上,用户只要按下它们就可以按下它们,我需要分别播放“正确”的声音和“错误”的声音。所以,它会持续按压。

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

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

回答

3

你发生异常。这是一个微妙的错误,很容易错过。这里发生的事情:

  1. 你点击一个按钮,并在您的全球MediaPlayer对象被初始化playSounds()被调用,以及OnCompletionListener设置。

  2. 内OnCompletionListener()试图释放解雇onCompletion

  3. 现在玩家,Java是通按值。它的意思是,在这里:

    @Override 
    public void onCompletion(MediaPlayer mep) 
    

    MEP是全局MP对象的引用,所以你可以做的操作,例如停止(),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 - 如果内部播放引擎尚未初始化或已被释放

SOLUTION:

稍微修改您的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

PASS-BY-VALUE是我错过了(我认为),并刚刚实施了上述规定的改变。需要在设备上进行测试。感谢分享上述链接,我们很快就会回来。 – sai

+0

是不是你解决方案相同的onCompletion方法的问题或我失去了什么? –

+0

@ANUJGUPTA它几乎是,它唯一的区别是它将_global_ MediaPlayer对象(mp,而不是mep)设置为null – Melquiades