无法启动Android MediaPlayer onCompletion

时间:2012-04-03 17:53:13

标签: android android-mediaplayer

我正在尝试使用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进行此测试。

我还注意到声音最后会被剪掉。

5 个答案:

答案 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()。