2012-04-03 93 views
11

我想使用Android MediaPlayer類播放一些聲音。無法讓Android MediaPlayer onCompletion觸發

下面是此代碼在服務運行的代碼

MediaPlayer mp = new MediaPlayer(); 
mp.setDataSource(context, Uri.parse(soundUrl)); 
mp.setAudioStreamType(AudioManager.STREAM_MUSIC); 
mp.setLooping(false); 
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
    @Override 
      public void onCompletion(MediaPlayer mp) { 
       Log.i(LOGTAG, "onComplete hit"); 
       mp.stop(); 
       mp.release(); 
      } 
    });   

mp.prepare(); 
mp.start(); 

,但由於某些原因,播放聲音好,但任何事情放到onCompletion似乎不火。然後,我在logcat中收到消息,說明mediaplayer沒有發佈。我對此感到不知所措。

我在galaxy nexus 4.0.4 stock ROM上運行這個測試。

我還注意到聲音最後可能會被截斷。

回答

3

這是我如何把它:

video.setOnCompletionListener(this); 
    IntroClip.execute(video); 
} 

@Override 
public void onCompletion(MediaPlayer mp){ 
    Button LoginButton; 
    Button CreateAccount; 
    Button RecoverPass; 

    setContentView(R.layout.loginmenu); 
    Spin = (ProgressBar)findViewById(R.id.Spinner); 

    mp.release();  
} 
+0

我猜「視頻」是MediaPlayer的一個實例嗎?並且你的課堂上有一個「實現MediaPlayer.OnCompletionListener」?我也試過這種方法,但它沒有奏效。 – Andrew 2012-04-04 06:06:34

+2

@Andrew它如何被接受的答案,如果它沒有工作?你做到了嗎?如果是,如何? – hendrix 2013-04-04 15:40:06

+2

@smitalm在設置偵聽器之前調用start()。 – ajacian81 2013-10-24 01:50:41

26

這其實很簡單(但愚蠢的)。你調用啓動(在設置你的聽衆),像這樣:

ediaPlayer mp = new MediaPlayer(); 
mp.setDataSource(context, Uri.parse(soundUrl)); 
mp.setAudioStreamType(AudioManager.STREAM_MUSIC); 
mp.setLooping(false); 
mp.prepare(); 
mp.start(); 
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
    @Override 
      public void onCompletion(MediaPlayer mp) { 
       Log.i(LOGTAG, "onComplete hit"); 
       mp.stop(); 
       mp.release(); 
      } 
    });   
+3

你能解釋爲什麼在設置完成監聽器之前調用start()很重要嗎?這是Android的怪癖嗎? – 2015-06-02 04:58:23

+0

@FabianTamp這是另一個Android怪癖。它可能不是所有設備都需要的(或者甚至不再需要),但當時它絕對是解決問題的方法。 – ajacian81 2015-06-03 15:30:22

+1

雖然我看不到任何證據支持爲什麼會修復Android源代碼中的內容。對我來說,根本問題是MediaPlayer在播放前已經GC'd,我已經添加了一個更詳細的答案:) – 2015-06-04 01:04:12

1

我遇到類似的症狀此,根本原因是,MediaPlayer居然也得到了OnCompletionListener之前收集的垃圾是被調用。

從你的代碼判斷,它看起來像是同樣的問題 - 你的代碼沒有對MediaPlayer進行長時間的引用,所以一旦該函數結束(並且在音頻結束播放之前),MediaPlayer就會變得易受影響到GC。

此問題是由該日誌線上可識別:

02-22 13:14:57.969: W/MediaPlayer-JNI(16888): MediaPlayer finalized without being released 

您可以通過重新構建該類使得MediaPlayer參考保持更長的時間解決這個問題 - 通過存儲在活動對它的引用和重用例如,同一個實例可以多次播放相同的聲音。

這裏有一個更詳細的解釋:Garbage Collection causes : MediaPlayer finalized without being released

0

有初始化的MediaPlayer對象兩種方法,「新」和「創建()」。爲了執行OnCompletionListener,它在這兩種方法中獲得的對象是不同的。

1)中的 「新」 辦法

MediaPlayer mp = new MediaPlayer(); 
mp.setDataSource(context, Uri.parse(soundUrl)); 
mp.setAudioStreamType(AudioManager.STREAM_MUSIC); 
mp.setLooping(false); 
mp.prepare(); 
mp.start(); 
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
    @Override 
    public void onCompletion(MediaPlayer mp) { 
     Log.i(LOGTAG, "onComplete hit"); 
     mp.stop(); 
     mp.release(); 
    } 
}); 

2) 「創造」 的方法

MediaPlayer mp = MediaPlayer.create(getActivity(), Uri.parse(soundUrl)); 
//mp.prepare() is not needed here 
mp.setLooping(false); 
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ 
    @Override 
    public void onCompletion(MediaPlayer mp) { 
     Log.i(LOGTAG, "onComplete hit"); 
     mp.stop(); 
     mp.release(); 
    } 
}); 

對於create()方法,我都經歷過類似的問題。如果在調用create()之後調用mp.prepare(),則該過程永遠不會到達以下setOnCompletionListener,甚至不會到達start()。基本原因是「對象處於準備狀態,如果使用create方法創建成功」(https://developer.android.com/reference/android/media/MediaPlayer.html)。所以你不需要在使用create()方法後調用prepare()。

0

其實,原因是MediaPlayer是一個局部變量。該功能完成後,MediaPlayer將由GC收集。 所以修復很簡單,讓您的MediaPlayer成爲該課程的一員。

YourClassName { 
    MediaPlayer mp = new MediaPlayer(); 

    void YourFunction() { 
      mp.setDataSource(context, Uri.parse(soundUrl)); 
      mp.setAudioStreamType(AudioManager.STREAM_MUSIC); 
      mp.setLooping(false); 
      mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
       @Override 
       public void onCompletion(MediaPlayer mp) { 
        Log.i(LOGTAG, "onComplete hit"); 
        mp.stop(); 
        mp.release(); 
       } 
      });   
      mp.prepare(); 
      mp.start(); 
    } 
} 
相關問題