Search code examples
androidtimerchronometer

How can I avoid the difference of milliseconds between two Chronometers start time?


I have two Chronometer in an activity. First Chronometer is for elapsed time, and Second Chronometer is for interval time.

For Ex.:- We chose 5 Min elapsed time and 30 Seconds interval time, now we start both timers at the same time by pressing btn_start. Both timers start with 0, now when interval timer reaches 00:30 time it restarts again with 0.

Now the issue:- As I have cross checked both timers start with a difference of milliseconds. Which later becomes a difference of 1 second,2 seconds,3 seconds or more seconds.

Below is Custom Chronometer.Java

public class PausableChronometer extends Chronometer implements PlaybackStateView {
    // Keeps track of how far long the Chronometer has been tracking when it's paused. We'd like
    // to start from this time the next time it's resumed.
    private long timeWhenStopped = 0;

    public PausableChronometer(Context context) {
        super(context);
    }

    public PausableChronometer(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PausableChronometer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void start() {
        setBase(SystemClock.elapsedRealtime() + timeWhenStopped);
        Log.e("start()", String.valueOf(SystemClock.elapsedRealtime() + timeWhenStopped));
        super.start();
    }

    @Override
    public void stop() {
        super.stop();
        timeWhenStopped = getBase() - SystemClock.elapsedRealtime();
    }

    /**
     * Reset the timer and start counting from zero.
     */
    @Override
    public void restart() {
        reset();
        start();
    }

    public void reset() {
        stop();
        setBase(SystemClock.elapsedRealtime());
        timeWhenStopped = 0;
    }

    @Override
    public void resume() {
        setBase(SystemClock.elapsedRealtime() - timeWhenStopped);
        start();
    }

    @Override
    public void pause() {
        stop();
        timeWhenStopped = SystemClock.elapsedRealtime() - getBase();

    }

}

On Button Clicked I execute following:

private void startTimer() {
        intervalTimer.start();
        elapsedTimer.start();
    }

Please let me know, How can I avoid the difference of milliseconds between both Chronometers start time?


Solution

  • As Anton Malyshev said that it's not possible to avoid the difference of start time of two different chronometers.

    I used Handler and Runnable to resolve the issue and for me, it works perfectly.

    private TextView elapsedTimer, intervalTimer;
    Handler mHandlerElapsed = new Handler(), mHandlerInterval = new Handler();
    Runnable mRunnableElapsed, mRunnableInterval;
    private int nCounterInterval = 0, nCounterElapsed = 0;
    

    Method for timer:-

    private void updateTime() {
    
            mHandlerElapsed = new Handler();
            mRunnableElapsed = new Runnable() {
                @Override
                public void run() {
                    if (!isPause) {
                        mHandlerElapsed.postDelayed(mRunnableElapsed, 1000);
                        nCounterElapsed++;
    
                            elapsedTimer.setText(AppUtil.formattedTime(nCounterElapsed));                    
    
                    } else {
                        mHandlerElapsed.removeCallbacks(mRunnableElapsed);
                    }
                }
            };
    
            mHandlerElapsed.post(mRunnableElapsed);
    
            mHandlerInterval = new Handler();
            mRunnableInterval = new Runnable() {
                @Override
                public void run() {
                    if (!isPause) {
                        mHandlerInterval.postDelayed(mRunnableInterval, 1000);
                        nCounterInterval++;
                        intervalTimer.setText(AppUtil.formattedTime(nCounterInterval));
    
                    } else {
                        mHandlerInterval.removeCallbacks(mRunnableInterval);
                    }
                }
            };
            mHandlerInterval.post(mRunnableInterval);
        }
    

    for start and pause timer:-

    private void startTimer() {
            isPause = false;
            updateTime();
        }
    
     private void pauseTimer() {
            isPause = true;
            updateTime();
        }
    

    In AppUtil.java

     public static String formattedTime(int totalSeconds) {
            int seconds = totalSeconds % 60;
            int minutes = (totalSeconds / 60) % 60;
            if (totalSeconds >= 3600) {
                minutes = minutes + 60;
            }
            return String.format(Locale.US, "%02d:%02d", minutes, seconds);
        }
    

    Using the above solution my issue is resolved.