Question

In Chronometer, how can we extract the time elapsed and store it separately in variables.

For example, store the number of hours, minutes, seconds elapsed in separate int variables?

Is it possible? If Yes, How?

Apart from Chronometer can it be better done using some other concept? If Yes, what is it?

Was it helpful?

Solution

You can get the time value (in milliseconds) doing that :

long timeElapsed = SystemClock.elapsedRealtime() - chrono.getBase();

Then you can simply retrieve the hours, minutes and seconds as follows :

long timeElapsed = 7564000; //For example
int hours = (int) (timeElapsed / 3600000);
int minutes = (int) (timeElapsed - hours * 3600000) / 60000;
int seconds = (int) (timeElapsed - hours * 3600000 - minutes * 60000) / 1000;
//hours = 2
//minutes = 6
//seconds = 4

OTHER TIPS

A couple ideas jump out at me:

  • A Chronometer extends a TextView so use getText() and parse the time with each ":" (or whatever the local time separator is).
  • You can also calculate the current time in milliseconds on your own, pass this to a Java Calendar object and use it's get() method:

    Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    calendar.setTimeInMillis(SystemClock.elapsedRealtime() - chronometer.getBase());
    int hour = calendar.get(Calendar.HOUR_OF_DAY);
    // etc
    

You could also create your own Chronometer, here is an example I use as a countdown timer, but the idea is just the same in reverse, you should only need to change the CountQueue CountDownTimer to add minutes and hours instead of substracting them, changing the @Override onTick to store iSec as 60 minus the current value and changing "void setTimeText()" to however you want to display the values. setTrainingCountdown() should also change so it starts at 0 by default.

To use it you just bind any TextView when creating a new SkillQCountdown and you start it with setTrainingCountdown() you might want to create a way to pause and restart the timer (just stop the timer and store the values, then restart with stored values). If you want to store and show milliseconds as well, change this line "counter = new CountQueue(60000, 100);" so you can register the onTick every second instead of every 60 seconds, second value is how frecuently it tries to update the TextView with new values.

However, if you just want to store the values precisely, you can get the current time in milliseconds at start of the count and whenever you want to get the values, then substract that values and calculate seconds, minutes and hours the same as you can see it is done inside "public void setTrainingCountdown(long diffInMis)"

public class SkillQCountdown {

    int iDay,iHour,iMin,iSec;
    CountQueue counter;
    NumberFormat myFormat = NumberFormat.getInstance();

    Context mContext;
    private TextView text = null;

    public SkillQCountdown(Context context, TextView text){
        mContext = context;
        this.text = text;
    }

    public void setTrainingCountdown(long diffInMis) {
        myFormat.setMinimumIntegerDigits(2);

        try {
            if(diffInMis < 0) {
                Toast.makeText(mContext, "Skill Queue unsynchronized"
                        ,Toast.LENGTH_SHORT).show();

            }else {             
                long diff = TimeUnit.MILLISECONDS.toSeconds(diffInMis);
                iDay = (int) (diff/(60*60*24));

                long lday = (diff%(60*60*24));
                iHour = (int)(lday/3600);

                long lhour = (lday%(60*60));
                iMin = (int)(lhour/60);

                long lmin= (lhour%(60));
                iSec = (int)(lmin);

                setTimeText();

                counter = new CountQueue(iSec*1000, 100);
                counter.start();}

        } catch (ParseException e) {
            e.printStackTrace();
        }    
    }

    private void setTimeText() {
        StringBuilder sb = new StringBuilder();
        String strText = null;

        if (iDay > 0) {
            sb.append(myFormat.format(iDay));
            if (iDay == 1) {
                sb.append(" day ");
            }else {
                sb.append(" days ");
            }
        }

        if (iHour > 0 || iDay > 0) {
            sb.append(myFormat.format(iHour));
            if (iHour == 1) {
                sb.append(" hour ");
            }else {
                sb.append(" hours ");
            }
        }

        if (iMin > 0 || iHour > 0 || iDay > 0) {
            sb.append(myFormat.format(iMin));
            if (iMin == 1) {
                sb.append(" minute ");
            }else {
                sb.append(" minutes ");
            }
        }

        if (iSec > 0 || iMin > 0 || iHour > 0 || iDay > 0) {
            sb.append(myFormat.format(iSec));
            sb.append(" seconds");
            strText = sb.substring(0);
        }else {
            strText = mContext.getString(R.string.msg_skillQueueEmpty);
        }

        text.setText(strText);
    }

    private class CountQueue extends CountDownTimer{
        public CountQueue(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }
        @Override
        public void onFinish() {
            iSec = 0;
            setTimeText();

            counter = new CountQueue(60000, 100);
            counter.start();
            iMin-=1;

            if(iMin < 0 && (iHour > 0 || iDay > 0)) {
                iMin=59;
                iHour-=1;

                if(iHour < 0 && iDay > 0) {
                    iHour=23;
                    iDay-=1;
                }
            }
        }

        @Override
        public void onTick(long millisUntilFinished) {
            if (Math.floor((float)millisUntilFinished / 1000.0f) != iSec) {  
                iSec = (int) Math.floor((float)millisUntilFinished / 1000.0f);
                setTimeText();
             }
        }
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top