我在我的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
}
}
答案 0 :(得分:2)
您的主要问题在于onProgressChanged()
方法。
每次seekBar进度发生变化时,您都在寻找指定位置,即使以编程方式完成也是如此。这意味着,每次拨打seekBar.setProgress(mp.getCurrentPosition())
时,都会触发onProgressChanged()
。
因此我们将其更改为以下内容:
public void onProgressChanged(SeekBar sb, int progress, boolean fromUser) {
if (fromUser) {
mp.seekTo(progress);
}
}
这样只有在用户移动搜索栏时才会触发。
此外,根据此answer,最好用以下内容替换while(true)循环:
public void run() {
seekBar.setProgress(mp.getCurrentPosition());
if (mp.getCurrentPosition() < mp.getDuration()) {
seekBar.postDelayed(this, MILLISECONDS);
}
}