2012-04-03 16 views
11

Próbuję użyć klasy Android Media Player, aby odtwarzać dźwięki.Nie można uruchomić Android MediaPlayer onCompletion na ogień

Oto kod

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(); 

Ten kod działa w służbie, ale z jakiegoś powodu dźwięk odgrywa ok, ale nic umieszczane w onCompletion nie wydają się ognia. Dostaję wiadomość w logcat, że mediaplayer nie został zwolniony. Brakuje mi tego, co mam w tym złego.

Używam tego testowania na romie z galaxy nexus 4.0.4.

Zauważyłem również, że dźwięk może zostać przycięty na końcu.

Odpowiedz

3

Oto jak mam go:

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

Przypuszczam, że "wideo" jest instancją MediaPlayera? i że masz "implementację MediaPlayer.OnCompletionListener" w swojej klasie? Próbowałem również tej metody, ale nie działa. – Andrew

+2

@Andrew Jak to się zgadza, jeśli to nie działa? Czy sprawiłeś, że to zadziałało? Jeśli tak, w jaki sposób? – hendrix

+2

@smitalm wywołaj start() zanim ustawisz swojego słuchacza. – ajacian81

26

To rzeczywiście proste (ale głupie). Ustaw słuchacza po wywołaniu start(), tak jak poniżej:

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

Czy możesz wyjaśnić, dlaczego wywoływanie funkcji start() przed ustawieniem detektora zakończenia jest ważne? Czy to dziwactwo Androida? –

+0

@FabianTamp to kolejne dziwactwo Androida. Może nie być wymagane na wszystkich urządzeniach (lub nawet więcej), ale w tamtym czasie było zdecydowanie poprawką do wydania. – ajacian81

+1

Nie widziałem żadnych dowodów na to, dlaczego naprawiłoby to źródło Androida. Okazuje się, że głównym problemem dla mnie było to, że MediaPlayer był odtwarzany GC przed zakończeniem odtwarzania, dodałem odpowiedź, która bardziej szczegółowo opisuje :) –

1

byłem napotykają podobne objawy do tego, a przyczyną było to, że MediaPlayer był coraz śmieci zgromadzonych przed OnCompletionListener był nazywany.

Sądząc po kodzie, wygląda na to samo - Twój kod nie zawiera długotrwałych odniesień do MediaPlayer, więc gdy tylko ta funkcja się zakończy (i zanim zakończy się odtwarzanie dźwięku), MediaPlayer jest podatny do GC.

Ten problem jest możliwy do zidentyfikowania przez tę linię log:

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

można naprawić poprzez rearchitecting klasę tak, że odniesienie MediaPlayer jest przechowywany przez dłuższy czas - przechowując odniesienie do niej w działalności i ponownego Ta sama instancja, aby na przykład odtwarzać ten sam dźwięk wiele razy.

Jest bardziej szczegółowe wyjaśnienie tutaj: Garbage Collection causes : MediaPlayer finalized without being released

0

Istnieją dwa podejścia do inicjalizacji obiektu MediaPlayer, „nowy” i „stworzyć()”. W celu wykonania OnCompletionListener jest inaczej dla obiektów uzyskanych w tych dwóch podejściach.

1) "nowe" podejście

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) "stwórz" metoda

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(); 
    } 
}); 

Dla metody create(), mam doświadczył podobnego problemu. Jeśli funkcja mp.prepare() zostanie wywołana po wywołaniu funkcji create(), procedura nigdy nie osiągnie poniższej metody setOnCompletionListener, nawet do funkcji start(). Zasadniczą przyczyną jest to, że "obiekty są w stanie Przygotowane, jeśli tworzenie za pomocą metody create zakończyło się pomyślnie" (https://developer.android.com/reference/android/media/MediaPlayer.html). Tak więc nie trzeba wywoływać metody prepare() po użyciu metody create().

0

Właściwie powodem jest to, że MediaPlayer jest zmienną lokalną. Po zakończeniu funkcji MediaPlayer jest zbierany przez GC. Poprawka jest łatwa, a Twój MediaPlayer należy do klasy.

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(); 
    } 
} 
Powiązane problemy