当seekBar更新Android的MediaPlayer视频不流畅时 [英] When seekBar updating Android's MediaPlayer video is not smooth

查看:106
本文介绍了当seekBar更新Android的MediaPlayer视频不流畅时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Android应用程序中通过MediPlayer播放视频,并显示了SeekBar.现在,我希望搜索栏随着视频的进行而自动更新,因此它应该自动从左移到右.此刻,(下面的代码)栏会更新,这是通过运行线程完成的,每秒更新一次seekBar的进度.问题是它不平滑,并且由于seekBar通过其seekProgress()更新,视频停止了一秒钟,并且全部跳动.现在,我希望它每秒更新一次,并且希望保留我已经实现的功能,以允许用户点击栏并更改视频的进度.

I'm playing video via MediPlayer in my android application and have SeekBar displayed. Now I want this seeks bar to automatically update as the video progresses so it should automatically move from left to right. At the moment, (code below) the bar updates and this is done via running thread, that every second updates the progress of seekBar. The problem is it is not smooth and as seekBar is updated via its seekProgress() the video stops for split second and all is very jumpy. Now I would like it to have updated more often then every second as well as keep functionality that I already implemented to allow user to tap on the bar and change progress of the video.

我正在寻找类似Android MediaPLayer应用程序的东西,seekBar位于透明背景上,并且一切都很流畅,我不知道它是如何完成的.

I'm after something like Android MediaPLayer application have, seekBar is on transparent background and all is smooth and I have no idea how it is done.

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

No, currently as you see from the code below thread updates every second as it sleeps inside f run method. I've also tried to use handlers to update UI thread, effect was the same. I also extended SeekBar to its own class, had thread there and this was no good either, exactly same effect.

如果有人可以向我解释如何解决此问题以及如何与其他播放器应用程序一起完成,那就太好了.

If anyone can explain to me how to solve this problem and how its done with other player appls that would be great.

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()方法中.

Your major problem is in your onProgressChanged() method.

每次seekBar进度更改时,即使是以编程方式完成,您也要搜索到指定位置.也就是说,每次您呼叫seekBar.setProgress(mp.getCurrentPosition())时,都会触发onProgressChanged().

You are seeking to the specified position every time the seekBar progress changes, even when it is done programmatically. Which means that every time you call seekBar.setProgress(mp.getCurrentPosition()), onProgressChanged() will be fired.

因此我们将其更改为以下内容:

So we change it to the following:

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

这样,只有当用户移动seekBar时才会触发.

That way it will only be fired when the user moves the seekBar.

此外,根据此答案,最好将您的while(true)循环替换为:

Moreover, according to this answer, it would be better to replace your while(true) loop with:

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

}

这篇关于当seekBar更新Android的MediaPlayer视频不流畅时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆