문제

I'm using Android to construct a video player using the VideoView. I've managed to get a video player running and now I'm setting a counter using chronometer that starts ticking when I select the file.
However, the video clip takes a few seconds to start running while the timer has already begun counting a few seconds when the clip starts.

How can I code to sync the counter with the media file?
I've checked around but can't seem to find an answer.

    video = (VideoView) findViewById(R.id.video);
    play = (Button) findViewById(R.id.play);
    pause = (Button) findViewById(R.id.pause);
    stop = (Button) findViewById(R.id.stop);
    reset = (Button) findViewById(R.id.reset);
    Chronometer counter = (Chronometer) findViewById(R.id.chrono);
    startTime = SystemClock.elapsedRealtime();
    time = (TextView) findViewById(R.id.time);

        try {
        video.setVideoPath(link);
        video.start();
        video.requestFocus();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    }

    play.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            video.start();
            video.requestFocus();
        }
    });
    pause.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            video.pause();
        }
    });
    stop.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            try {
                video.stopPlayback();
                video.setVideoPath(link);
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
    });
    reset.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            try {
                video.seekTo(0);
                video.start();
                video.requestFocus();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
    });

counter.setOnChronometerTickListener(new OnChronometerTickListener(){
        public void onChronometerTick(Chronometer arg0) {
            countUp = (SystemClock.elapsedRealtime() - arg0.getBase()) / 1000;
            duration = video.getDuration();
            if (countUp % 60 <= 9) {
                countText = (countUp / 60) + ":0" + (countUp % 60);
            } else {
                countText = (countUp / 60) + ":" + (countUp % 60);           
            } 
            if (duration % 60000 <= 9) {
                durationText = (duration / 60000) + ":0" + (duration % 60000);
            } else {
                durationText = (duration / 60000) + ":" + (duration % 60000);           
            }
            time.setText(countText + " / " + durationText);
        }
    });
    counter.start();
도움이 되었습니까?

해결책

No worries, I found a way to use VideoView getCurrentPosition() in the Chronometer. Now it always sees the correct current time and is easier to keep check of.

counter.setOnChronometerTickListener(new OnChronometerTickListener(){
        public void onChronometerTick(Chronometer arg0) {
            countUp = video.getCurrentPosition();
            countUp = Math.round(countUp / 1000);
            duration = video.getDuration();
            duration = duration / 1000;
            long a = (long) countUp;
            if (countUp % 60000 <= 9) {
                countText = (a / 60000) + ":0" + (a % 60000);
            } else {
                countText = (a / 60000) + ":" + (a % 60000);           
            } 
            if (duration % 60000 <= 9) {
                durationText = (duration / 60000) + ":0" + (duration % 60000);
            } else {
                durationText = (duration / 60000) + ":" + (duration % 60000);           
            }
            time.setText(countText + " / " + durationText);
        }
    });
    counter.start();

다른 팁

I'll give my two cents on this as it may help others.

You can setup onPreparedListener where you will be able to get hold of MediaPlayer. MediaPlayer has onInfoListener that will let you know when the media is being buffered, or even the first frame actually being rendered MEDIA_INFO_VIDEO_RENDERING_START (only API 17+). I'm using this to update the local state variable (something like: enum VideoPlayerState (BUFFERING, PLAYING, STOPPED, OPEN, PAUSED)) in the overridden VideoView class. You can override its setter to get a callback when the state is changing. That callback can kick off/pause your timer.

setOnPreparedListener(new OnPreparedListener() {
        @Override
        public void onPrepared(final MediaPlayer mp) {
            mp.setOnInfoListener(new OnInfoListener() {

                @Override
                public boolean onInfo(MediaPlayer mp, int what, int extra) {
                    if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
                        setPlayerState(VideoPlayerState.BUFFERING);
                    } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
                        if (mp.isPlaying()
                                && mPlayerState == VideoPlayerState.BUFFERING) {
                            setPlayerState(VideoPlayerState.PLAYING);
                        }
                    }
                    return false;
                }
            });
});

You can also override these methods on the VideoView to switch the state:

@Override
public void pause() {
    super.pause();
    setPlayerState(VideoPlayerState.PAUSED);
}

@Override
public void start() {
    super.start();
    setPlayerState(VideoPlayerState.PLAYING);
}

@Override
public void stopPlayback() {
    super.stopPlayback();
    setPlayerState(VideoPlayerState.STOPPED);
}

Hope it helps.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top