Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot get android MediaPlayer onCompletion to fire

I'm trying to use the android MediaPlayer class to play some sounds.

Here's the code

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

This code runs in a service, but for some reason the sound plays ok, but anything placed into the onCompletion doesn't seem to fire. I then get a message in the logcat that the mediaplayer wasn't released. I'm at a loss to what I've got wrong with this.

I'm running this testing on a galaxy nexus 4.0.4 stock rom.

I also notice that the sound can get clipped at the end.

like image 373
Andrew Avatar asked Apr 03 '12 17:04

Andrew


3 Answers

It's actually simple (but silly). Set your listener after you call start(), like so:

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(); 
            } 
    });         
like image 173
ajacian81 Avatar answered Sep 30 '22 09:09

ajacian81


Here is how I have it:

    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();       
}
like image 20
Araw Avatar answered Sep 30 '22 08:09

Araw


I was encountering similar symptoms to this, and the root cause was that the MediaPlayer was getting garbage collected before the OnCompletionListener was being called.

Judging from your code, it looks like the same problem - your code doesn't hold a long-lived reference to the MediaPlayer, so as soon as that function ends (and before the audio finishes playing) the MediaPlayer is susceptible to GC.

This problem is identifiable by this log line:

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

You can fix it by rearchitecting the class such that the MediaPlayer reference is kept for longer - by storing a reference to it in the activity, and reusing the same instance to play the same sound multiple times, for example.

There's a more detailed explanation here: Garbage Collection causes : MediaPlayer finalized without being released

like image 20
Fabian Tamp Avatar answered Sep 30 '22 08:09

Fabian Tamp