15

SeekBar を使用して、MediaPlayer クラスによって再生されるトラックの長さの両方を表示し、トラック内でのシークを有効にしようとしています。

トラック内のシークはうまく機能します。ただし、トラックの再生中に setProgress を使用して進行値を更新すると、わずかにスキップが発生するようです。

onCreate メソッドで、現在のトラックの SeekBar の進行状況の値を更新するループを持つ Thread を作成します。このループは、トラックが変更されるとリセットされます。

private void createProgressThread() {

    _progressUpdater = new Runnable() {
        @Override
        public void run() {
            //Exitting is set on destroy
            while(!_exitting) {
                _resetProgress = false;
                if(_player.isPlaying()) {
                    try
                    {
                        int current = 0;
                        int total = _player.getDuration();
                        progressBar.setMax(total);
                        progressBar.setIndeterminate(false);

                        while(_player!=null && current<total && !_resetProgress){
                            try {
                                Thread.sleep(1000); //Update once per second
                                current = _player.getCurrentPosition();
                                 //Removing this line, the track plays normally.
                                progressBar.setProgress(current); 
                            } catch (InterruptedException e) {

                            } catch (Exception e){

                            }            
                        }
                    }
                    catch(Exception e)
                    {
                        //Don't want this thread to intefere with the rest of the app.
                    }
                }
            }
        }
    };
    Thread thread = new Thread(_progressUpdater);
    thread.start();
}

理想的には、これには欠点があることを理解しているため、スレッドを使用しないことをお勧めします。また、例外の飲み込みについてはご容赦ください。UI イベントに応答してすべての MediaPlayer の状態をチェックし続けることは困難です。ただし、私の本当の問題は、音楽がスキップしていることです。

進行状況を更新する別の方法を提案し、別のスレッドを使用しても setProgress の呼び出しによってトラックがスキップされる理由を説明できますか?

前もって感謝します。

4

1 に答える 1

27

問題は、setProgress() を呼び出すと、onProgressChanged イベントが発生することだと思います。

リスナー (OnSeekBarChangeListener) にはメソッド public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) があります。ここでは、リスナーがユーザー アクションまたはコードによって起動されたかどうかをテストする必要があります。あなたの場合、 fromUser 変数は false でなければなりません。

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    if(fromUser){
           player.seekTo(x);
        }
        else{
         // the event was fired from code and you shouldn't call player.seekTo()
        }
}
于 2011-01-09T20:29:03.607 に答える