1

Android アプリケーションで MediPlayer を介してビデオを再生していて、SeekBar が表示されています。ここで、このシーク バーがビデオの進行に合わせて自動的に更新されるようにして、左から右に自動的に移動するようにします。現時点では (以下のコード) バーが更新され、これは実行中のスレッドを介して行われ、1 秒ごとに seekBar の進行状況が更新されます。問題は、スムーズではなく、seekProgress() を介して seekBar が更新されると、ビデオが一瞬停止し、すべてが非常に不安定になることです。今では、ユーザーがバーをタップしてビデオの進行状況を変更できるようにするために、既に実装した機能を維持するだけでなく、毎秒よりも頻繁に更新したいと考えています。

私は 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

    }
    }
4

1 に答える 1

2

あなたの主な問題はあなたのonProgressChanged()方法にあります。

プログラムで実行されている場合でも、seekBarの進行状況が変化するたびに、指定された位置にシークします。つまり、電話をかけるたびにseekBar.setProgress(mp.getCurrentPosition())onProgressChanged()が解雇されます。

したがって、次のように変更します。

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

そうすれば、ユーザーがseekBarを動かしたときにのみ起動されます。

さらに、この回答によれば、while(true)ループを次のように置き換える方がよいでしょう。

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

}
于 2012-08-19T23:11:47.037 に答える