Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Syncing Video View with SeekBar with onStopTrackingTouch

I am making a custom Video Player, I successfully synced the progress of video to the seekbak. I wanted that the videoview should sync its progress with seekbar's progress when user moves the seekbar handler. I achieved this too, but it's not behaving as i want it too. Let me elaborate this proble, When i touch the seekbar handler and move it (forward or backward) i update the seekbar progress, but when i leave the seekbar, the seekbar handler goes a step forward/backward and then starts playing instead of starting at the same point where i left.

Here's my code:

public class MainActivity extends Activity implements OnSeekBarChangeListener {

    private VideoView vvVideo;
    private SeekBar sbVideo;
    private Handler mHandler = new Handler();
    private Utilities utils;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom_video_player);
        initOnjects();
        playVideo();
    }

    private void initOnjects() {
        vvVideo = (VideoView) findViewById(R.id.vvVideo);
        sbVideo = (SeekBar) findViewById(R.id.sbVideo);
        sbVideo.setOnSeekBarChangeListener(this);
        utils = new Utilities();
    }

    private void playVideo() {
        Uri uri = Uri
                .parse("android.resource://com.sunshine.handsonequation/raw/title_video");
        vvVideo.setVideoURI(uri);
        sbVideo.setProgress(0);
        sbVideo.setMax(100);
        vvVideo.start();
        // Updating progress bar
        updateProgressBar();
    }

    private void updateProgressBar() {
        mHandler.postDelayed(updateTimeTask, 100);
    }

    private Runnable updateTimeTask = new Runnable() {

        @Override
        public void run() {
            long totalDuration = vvVideo.getDuration();
            long currentDuration = vvVideo.getCurrentPosition();

            // update progress bar
            int progress = (int) (utils.getProgressPercentage(currentDuration,
                    totalDuration));
            sbVideo.setProgress(progress);
            mHandler.postDelayed(this, 100);

        }
    };

    @Override
    public void onProgressChanged(SeekBar seekbar, int progress,
            boolean fromTouch) {
        // TODO Auto-generated method stub

    }

    // when user starts moving the progress handler
    @Override
    public void onStartTrackingTouch(SeekBar seekbar) {
        // remove message Handler from updating progress bar
        mHandler.removeCallbacks(updateTimeTask);
    }

    // when user stops moving the progress handler
    @Override
    public void onStopTrackingTouch(SeekBar seekbar) {
        mHandler.removeCallbacks(updateTimeTask);
        int totalDuration = vvVideo.getDuration();
        int currentPosition = utils.progressToTimer(sbVideo.getProgress(),
                totalDuration);

        // forward or backward to certain seconds
        vvVideo.seekTo(currentPosition);

        // update timer progress again
        updateProgressBar();
    }
}

Utility Class:

public class Utilities {

    /**
     * Function to convert milliseconds time to
     * Timer Format
     * Hours:Minutes:Seconds
     * */
    public String milliSecondsToTimer(long milliseconds){
        String finalTimerString = "";
        String secondsString = "";

        // Convert total duration into time
           int hours = (int)( milliseconds / (1000*60*60));
           int minutes = (int)(milliseconds % (1000*60*60)) / (1000*60);
           int seconds = (int) ((milliseconds % (1000*60*60)) % (1000*60) / 1000);
           // Add hours if there
           if(hours > 0){
               finalTimerString = hours + ":";
           }

           // Prepending 0 to seconds if it is one digit
           if(seconds < 10){
               secondsString = "0" + seconds;
           }else{
               secondsString = "" + seconds;}

           finalTimerString = finalTimerString + minutes + ":" + secondsString;

        // return timer string
        return finalTimerString;
    }

    /**
     * Function to get Progress percentage
     * @param currentDuration
     * @param totalDuration
     * */
    public int getProgressPercentage(long currentDuration, long totalDuration){
        Double percentage = (double) 0;

        long currentSeconds = (int) (currentDuration / 1000);
        long totalSeconds = (int) (totalDuration / 1000);

        // calculating percentage
        percentage =(((double)currentSeconds)/totalSeconds)*100;

        // return percentage
        return percentage.intValue();
    }

    /**
     * Function to change progress to timer
     * @param progress -
     * @param totalDuration
     * returns current duration in milliseconds
     * */
    public int progressToTimer(int progress, int totalDuration) {
        int currentDuration = 0;
        totalDuration = (int) (totalDuration / 1000);
        currentDuration = (int) ((((double)progress) / 100) * totalDuration);

        // return current duration in milliseconds
        return currentDuration * 1000;
    }
}

I have no clue why it is happening, I hope you guys can give me a hint or solution around this.

like image 255
ark Avatar asked Apr 13 '13 11:04

ark


3 Answers

I think you complicated yourself a bit too much with that utility class. Set the maximum progress of the seekbar to be equal to the videos duration. Then on the seekbar listener you can just directly get its progress and seek to it. I hope you can understand what I typed bellow , this is my first answer :) .

private void playVideo() {
    Uri uri = Uri..parse("android.resource://com.sunshine.handsonequation/raw/title_video");
    vvVideo.setVideoURI(uri);
    vvVideo.start();
    // Updating progress bar
    updateProgressBar();
}

private void updateProgressBar() {
    mHandler.postDelayed(updateTimeTask, 100);
}

private Runnable updateTimeTask = new Runnable() {
    public void run() {
        sbVideo.setProgress(vvVideo.getCurrentPosition());
        sbVideo.setMax(vvVideo.getDuration());
        mHandler.postDelayed(this, 100);
    }
};

public void onProgressChanged(SeekBar seekbar, int progress,boolean fromTouch) {

}
public void onStartTrackingTouch(SeekBar seekbar) {
    mHandler.removeCallbacks(updateTimeTask);
}
public void onStopTrackingTouch(SeekBar seekbar) {
    mHandler.removeCallbacks(updateTimeTask);
    vvVideo.seekTo(sbVideo.getProgress());
    updateProgressBar();
}
like image 119
zeroblitz36 Avatar answered Sep 19 '22 18:09

zeroblitz36


Seek the video to SeekBar progress in onProgressChanged function.

@Override
    public void onProgressChanged(SeekBar seekbar, int progress,
            boolean fromTouch) {
    if(fromTouch)
    {
        vvVideo.seekTo(progress);
    }

    }
like image 28
Nirmal Raghavan Avatar answered Sep 19 '22 18:09

Nirmal Raghavan


Nirmal answer should work but instead of

vvVideo.seekTo(progress); 

it should be

vvVideo.seekTo(progress*1000);

seekTo time should be in milliseconds

http://developer.android.com/reference/android/widget/VideoView.html#seekTo(int)

like image 45
user2743753 Avatar answered Sep 22 '22 18:09

user2743753