2014-01-22 30 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