Android - Get time of chronometer widget

AndroidTimeViewWidgetChronometer

Android Problem Overview


How to get the time from a Chronometer? I tried getText, getFormat, getBase, etc, but none of them could work.

Example code snippet:

Chronometer t = (Chronometer)findViewById(R.id.toptime);
long time = SystemClock.elapsedRealtime()-t.getBase();
Log.d(null,"Was: "+time); //time is not the proper time for some reason - it is a random number between 0 and 50
t.setBase(SystemClock.elapsedRealtime());
t.start();

Android Solutions


Solution 1 - Android

If you look at the source of the Chronometer class, you'll see that it doesn't store the elapsed time in a field and it calculates it internally every time it needs to update the display.

However it's relatively easy to do the same in your own code:

long elapsedMillis = SystemClock.elapsedRealtime() - chronometerInstance.getBase();

This assumes that you have started your clock something like this:

chronometerInstance.setBase(SystemClock.elapsedRealtime());
chronometerInstance.start();

Here's a full example:

public class ChronoExample extends Activity {
Chronometer mChronometer;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LinearLayout layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);

    mChronometer = new Chronometer(this);
    layout.addView(mChronometer);

    Button startButton = new Button(this);
    startButton.setText("Start");
    startButton.setOnClickListener(mStartListener);
    layout.addView(startButton);

    Button stopButton = new Button(this);
    stopButton.setText("Stop");
    stopButton.setOnClickListener(mStopListener);
    layout.addView(stopButton);
    
    Button resetButton = new Button(this);
    resetButton.setText("Reset");
    resetButton.setOnClickListener(mResetListener);
    layout.addView(resetButton);        
    
    setContentView(layout);
}

private void showElapsedTime() {
    long elapsedMillis = SystemClock.elapsedRealtime() - mChronometer.getBase();            
    Toast.makeText(ChronoExample.this, "Elapsed milliseconds: " + elapsedMillis, 
            Toast.LENGTH_SHORT).show();
}

View.OnClickListener mStartListener = new OnClickListener() {
    public void onClick(View v) {
        mChronometer.start();
        showElapsedTime();
    }
};

View.OnClickListener mStopListener = new OnClickListener() {
    public void onClick(View v) {
        mChronometer.stop();
        showElapsedTime();
    }
};

View.OnClickListener mResetListener = new OnClickListener() {
    public void onClick(View v) {
        mChronometer.setBase(SystemClock.elapsedRealtime());
        showElapsedTime();
    }
};
}

One somewhat confusing thing about Chronometer is that you can't really use it as a stopwatch that gets started, stopped and restarted again. When it's running, it will always show the time elapsed since you last reset it, no matter how many times and for how long you have stopped it in the meantime. When it is stopped, it simply stops updating the display.

If you need something like a stopwatch you'll have to subclass Chronometer or maybe create your own version using the source.

alt text

Solution 2 - Android

I found this example really useful, thanks nyenyec!

Here's my two cents on how to turn it into a real stopwatch function, without subclassing Chronometer. Just change the mStartListener method to parse the text from mChronometer (it's derived from TextView after all), calculate milliseconds, and use setBase() to readjust the base time to that amount of time in the past:

  View.OnClickListener mStartListener = new OnClickListener() {
    public void onClick(View v) {
        
      int stoppedMilliseconds = 0;
      
      String chronoText = mChronometer.getText().toString();
      String array[] = chronoText.split(":");
      if (array.length == 2) {
        stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 1000
            + Integer.parseInt(array[1]) * 1000;
      } else if (array.length == 3) {
        stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 60 * 1000 
            + Integer.parseInt(array[1]) * 60 * 1000
            + Integer.parseInt(array[2]) * 1000;
      }

      mChronometer.setBase(SystemClock.elapsedRealtime() - stoppedMilliseconds);
      mChronometer.start();
    }
  };

Solution 3 - Android

@nyenyec +1: here is what i ended up with, while using nyenyec's response without a sub class.

		chronometer.setOnChronometerTickListener(new OnChronometerTickListener() {						
		@Override
		public void onChronometerTick(Chronometer chronometer) {
			long elapsedMillis = SystemClock.elapsedRealtime() - chronometer.getBase();
			if(elapsedMillis>THRESHOLD){
				doYourStuff();
			}
		}
	});

where THRESHOLD is

private static final int THRESHOLD_EXERSISE = 60000; //In milliseconds

Solution 4 - Android

Somewhat late response, but I was trying to solve this myself today. I ended up just parsing the text of the view:

    // Expects a string in the form MM:SS or HH:MM:SS
public static int getSecondsFromDurationString(String value){

    String [] parts = value.split(":");

    // Wrong format, no value for you.
    if(parts.length < 2 || parts.length > 3)
        return 0;

    int seconds = 0, minutes = 0, hours = 0;

    if(parts.length == 2){
        seconds = Integer.parseInt(parts[1]);
        minutes = Integer.parseInt(parts[0]);
    }
    else if(parts.length == 3){
        seconds = Integer.parseInt(parts[2]);
        minutes = Integer.parseInt(parts[1]);
        hours = Integer.parseInt(parts[0]);
    }

    return seconds + (minutes*60) + (hours*3600);
}

So calling getSecondsFromDurationString with view.getText().toString() gives you the total elapsed time in seconds (my application is some kind of stop watch, so you can pause it and resume it).

Hope it helps.

Solution 5 - Android

My Solution:

    public void starttimer(View view){
	Button mybtn = (Button) view;
	if (mybtn.equals(findViewById(R.id.button1))) {
		mycm.setBase(SystemClock.elapsedRealtime() - elapsed);
		mycm.start();
	}
	else {
		mycm.stop();
		elapsed = SystemClock.elapsedRealtime() -  mycm.getBase();
	}
}

In onCreate:

    mycm = (Chronometer) findViewById(R.id.chronometer1);
    elapsed = 0;

There are two buttons in the layout which both call the starttimer method (start and stop)

Solution 6 - Android

	final Chronometer counter = (Chronometer) findViewById(R.id.chronometer1);
	counter.setOnChronometerTickListener(new OnChronometerTickListener() {
		
		public void onChronometerTick(Chronometer chronometer) {
			// TODO Auto-generated method stub
			chronometer.refreshDrawableState();
			
		}
	});
	
	final ToggleButton togglebutton = (ToggleButton) findViewById(R.id.togglebutton1);
	togglebutton.setOnClickListener(new OnClickListener() {
		public void onClick(View v) {
			// Perform action on clicks
			if (togglebutton.isChecked()) {
				counter.start();
			} else {
				counter.stop();
			}
		}
	});

Solution 7 - Android

//ok here is the final changed code which works well

import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.LinearLayout;
import android.widget.Toast;

public class HelloWidgetActivity extends Activity {
	Chronometer mChronometer;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		LinearLayout layout = new LinearLayout(this);
		layout.setOrientation(LinearLayout.VERTICAL);

		mChronometer = new Chronometer(this);
		layout.addView(mChronometer);

		Button startButton = new Button(this);
		startButton.setText("Start");
		startButton.setOnClickListener(mStartListener);
		layout.addView(startButton);

		Button stopButton = new Button(this);
		stopButton.setText("Stop");
		stopButton.setOnClickListener(mStopListener);
		layout.addView(stopButton);

		Button resetButton = new Button(this);
		resetButton.setText("Reset");
		resetButton.setOnClickListener(mResetListener);
		layout.addView(resetButton);

		setContentView(layout);
	}

	private void showElapsedTime() {
		long elapsedMillis = SystemClock.elapsedRealtime()
				- mChronometer.getBase();
		Toast.makeText(HelloWidgetActivity.this,
				"Elapsed milliseconds: " + elapsedMillis, Toast.LENGTH_SHORT).show();
	}


	
	View.OnClickListener mStartListener = new OnClickListener() {
	    public void onClick(View v) {
	      int stoppedMilliseconds = 0;
	      String chronoText = mChronometer.getText().toString();
	      String array[] = chronoText.split(":");
	      if (array.length == 2) {
	        stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 1000
	            + Integer.parseInt(array[1]) * 1000;
	      } else if (array.length == 3) {
	        stoppedMilliseconds = Integer.parseInt(array[0]) * 60 * 60 * 1000 
	            + Integer.parseInt(array[1]) * 60 * 1000
	            + Integer.parseInt(array[2]) * 1000;
	      }
	      mChronometer.setBase(SystemClock.elapsedRealtime() - stoppedMilliseconds);
	      mChronometer.start();
	    }
	  };

	View.OnClickListener mStopListener = new OnClickListener() {
		public void onClick(View v) {
			mChronometer.stop();
			showElapsedTime();
		}
	};

	View.OnClickListener mResetListener = new OnClickListener() {
		public void onClick(View v) {
			mChronometer.setBase(SystemClock.elapsedRealtime());
			mChronometer.stop();
			showElapsedTime();
		}
	};
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIsaac WallerView Question on Stackoverflow
Solution 1 - AndroidnyenyecView Answer on Stackoverflow
Solution 2 - Androiduser158114View Answer on Stackoverflow
Solution 3 - AndroidSamuelView Answer on Stackoverflow
Solution 4 - AndroidjeudyxView Answer on Stackoverflow
Solution 5 - AndroidDominik BennerView Answer on Stackoverflow
Solution 6 - AndroidhoofuzView Answer on Stackoverflow
Solution 7 - AndroidSubash BasnetView Answer on Stackoverflow