android - seekBar更新Android的MediaPlayer视频时不流畅

标签 android android-videoview android-mediaplayer

我在我的 Android 应用程序中通过 MediPlayer 播放视频并显示了 SeekBar。现在我希望这个搜索栏随着视频的进行自动更新,因此它应该自动从左向右移动。目前,(下面的代码)栏更新,这是通过运行线程完成的,每秒更新 seekBar 的进度。问题是它不流畅,并且当 seekBar 通过其 seekProgress() 更新时,视频会瞬间停止并且一切都非常跳跃。现在我希望它比每秒更频繁地更新,并保留我已经实现的功能以允许用户点击栏并更改视频的进度。

我正在寻找像 Android MediaPLayer 应用程序这样的东西,seekBar 在透明背景上并且一切顺利,我不知道它是如何完成的。

不,正如您从下面的代码中看到的那样,线程在 f run 方法中休眠时每秒更新一次。我也尝试过使用处理程序来更新 UI 线程,效果是一样的。我还将 SeekBar 扩展到它自己的类,那里有线程,这也不好,完全相同的效果。

如果有人能向我解释如何解决这个问题以及它是如何与其他播放器应用程序一起完成的,那就太好了。

public class FightPlayerActivity extends Activity implements Runnable, OnSeekBarChangeListener, SurfaceHolder.Callback, OnPreparedListener {

    private MediaPlayer mp=null;
    private SeekBar seekBar;
    private Thread progressBarUpdater;
    private String filePath;
    private Handler handler=new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        Toast.makeText(this,"Create ", 2000).show();


    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub

    }

    public void onStop()
    {
        super.onStop();

        mp.stop();
        mp.reset();
        mp.release();
    }

    public void run()
    {
        while(true)
        {
            try {
                progressBarUpdater.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            seekBar.setProgress(mp.getCurrentPosition());

            // handler does have same effect, so video stops for split second
            //handler.postDelayed(this, 1000);

        }
    }

    public void onStart()
    {
        super.onStart();

        setContentView(R.layout.fight_player);

        filePath=getIntent().getStringExtra("filename");
        filePath=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+"/FightAll_BJJ_Scoring/"+filePath;

        Toast.makeText(this,filePath, 2000).show();
        // seek bar

        seekBar=(SeekBar) findViewById(R.id.seek_bar);
        seekBar.setOnSeekBarChangeListener(this);

        try {
            SurfaceView sv=(SurfaceView) findViewById(id.video_preview);

            SurfaceHolder sh=sv.getHolder();
            sh.addCallback(this);

            sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    


    }

    public void stop(View view)
    {
        mp.seekTo(0);
        mp.pause();
    }

    public void pause(View view)
    {
        mp.pause();
    }

    public void play(View view)
    {
        mp.start();
    }

    public void surfaceCreated(SurfaceHolder holder) {

        try {
            mp=new MediaPlayer();
            mp.setDataSource(filePath);
            mp.setDisplay(holder);  
            mp.setOnPreparedListener(this);
            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mp.prepare();

            //handler.removeCallbacks(this);

            //handler.postDelayed(this, 1000);

        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    }


    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }

    public void onPrepared(MediaPlayer mediaplayer) {
         mp.start(); 
         seekBar.setMax(mp.getDuration());

         progressBarUpdater=new Thread(this);
         progressBarUpdater.start();

         //handler.postDelayed(this, 1000);
    }

    public void onProgressChanged(SeekBar sb,int progress,boolean fromUser)
    {
        //Toast.makeText(this, progress, 2000).show();
        mp.seekTo(progress);
    }

    public void onStartTrackingTouch(SeekBar seekBar) {
        // TODO Auto-generated method stub
        onProgressChanged(seekBar,seekBar.getProgress(),true);
    }

    public void onStopTrackingTouch(SeekBar seekBar) {
        // TODO Auto-generated method stub

    }
    }

最佳答案

您的主要问题出在您的 onProgressChanged() 方法中。

每次 seekBar 进度发生变化时,您都在寻找指定的位置,即使它是通过编程完成的。这意味着每次调用 seekBar.setProgress(mp.getCurrentPosition()) 时,都会触发 onProgressChanged()

所以我们将其改成如下:

public void onProgressChanged(SeekBar sb, int progress, boolean fromUser) {
    if (fromUser) {
        mp.seekTo(progress);
    }
}

这样它只会在用户移动 seekBar 时触发。

此外,根据这个answer ,最好将 while(true) 循环替换为:

public void run() {
    seekBar.setProgress(mp.getCurrentPosition());
    if (mp.getCurrentPosition() < mp.getDuration()) {
        seekBar.postDelayed(this, MILLISECONDS);
    }

}

关于android - seekBar更新Android的MediaPlayer视频时不流畅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12030125/

相关文章:

android - 阻止 BroadCastReceiver 在 Android 中触发应用程序更新

android - 如何在 VideoView 中翻转(镜像效果)视频?

android - 检测图像时 ArCore Sceneform : Play . mp4 视频

android - 如何通过其uri播放音乐

java - MediaPlayer - 切换歌曲之间的时间很长

java - MediaPlayer 在开始另一个 Activity 时停止

java - 使用旋转动画旋转正方形

安卓异步任务问题

android - 先淡出,然后淡入,在 Android 中不起作用

android - 我们可以在android VideoView中播放.swf文件吗?