问题
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.
回答1:
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();
}
回答2:
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();
}
});
回答3:
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
回答4:
There are two approaches to initialise the MediaPlayer object, "new" and "create()". In order to do OnCompletionListener, it is different for the objects obtained in these two approaches.
1) the "new" approach
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) the "create" method
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();
}
});
For the create() method, I have experienced the similar issue. If mp.prepare() is called after calling the create(), the procedure will never reach the following setOnCompletionListener, not even to the start(). The essential reason is that "the objects are in the Prepared state if the creation using create method is successful"(https://developer.android.com/reference/android/media/MediaPlayer.html). So you do not need to call the prepare() after using the create() method.
回答5:
Actually, the reason is that the MediaPlayer is a local variable. After the function is finished, the MediaPlayer is collected by GC. So the fix is easy, make your MediaPlayer a member of the class.
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();
}
}
来源:https://stackoverflow.com/questions/9998677/cannot-get-android-mediaplayer-oncompletion-to-fire