我正在尝试使用Android MediaPlayer类播放一些声音。
这是代码
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中收到媒体播放器未发布的消息。我对这个问题感到茫然。
我正在使用galaxy nexus 4.0.4 stock rom进行此测试。
我还注意到声音最后会被剪掉。
答案 0 :(得分:33)
这实际上很简单(但很傻)。在调用start()之后设置你的监听器,如下所示:
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();
}
});
答案 1 :(得分: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();
}
答案 2 :(得分:2)
我遇到了类似的症状,根本原因是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
答案 3 :(得分:1)
实际上,原因是MediaPlayer是一个局部变量。功能完成后,GC收集MediaPlayer。 因此修复很容易,使您的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();
}
}
答案 4 :(得分:0)
初始化MediaPlayer对象有两种方法,“new”和“create()”。为了执行OnCompletionListener,对于在这两种方法中获得的对象,它们是不同的。
1)“新”方法
GET
2)“创建”方法
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();
}
});
对于create()方法,我遇到了类似的问题。如果在调用create()之后调用mp.prepare(),则该过程将永远不会到达以下setOnCompletionListener,甚至不会到达start()。基本原因是“如果使用create方法创建成功”(https://developer.android.com/reference/android/media/MediaPlayer.html),“对象处于准备状态”。因此,在使用create()方法之后,您无需调用prepare()。