In this post we are going to explore the Android Chronometer control.

The chronometer acts as a timer. In this post we are going to create a simple timer using the Chronometer

Let’s start with the interface:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/txt"
    />
    
    <Chronometer 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/chrono"
    />
    
    <Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/btnStart"
    android:text="Start"
    android:onClick="onClick"
    />
    
    <Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/btnStop"
    android:text="Stop"
    android:onClick="onClick"
    />
    
    <Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/btnReset"
    android:text="Reset"
    android:onClick="onClick"
    />
</LinearLayout>





Define instances of the controls
Chronometer chrono;
Button btnStart;
Button btnStop;
TextView txt;
And some variables
long elapsedTime=0;
String currentTime="";
long startTime=SystemClock.elapsedRealtime();
Boolean resume=false;
we put the Boolean flag differentiate between starting the Chronometer for the first time or resuming it after pause.

Getting inside the onCreate method:
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
chrono=(Chronometer)findViewById(R.id.chrono);
btnStart=(Button)findViewById(R.id.btnStart);
btnStop=(Button)findViewById(R.id.btnStop);
btnReset=(Button)findViewById(R.id.btnReset);
txt=(TextView)findViewById(R.id.txt);

Now to handle each button click event
public void onClick(View v) {
  // TODO Auto-generated method stub
  switch(v.getId())
  {
  case R.id.btnStart:
   btnStart.setEnabled(false);
   btnStop.setEnabled(true);
   if(!resume)
   {
    chrono.setBase(SystemClock.elapsedRealtime());
    chrono.start();
   }
   else
   {
    
    chrono.start();
   }
   
   break;
  case R.id.btnStop:
   btnStart.setEnabled(true);
   btnStop.setEnabled(false);
   chrono.stop();
   chrono.setText(currentTime);
   resume=true;
   btnStart.setText("Resume");
   break;
  case R.id.btnReset:
   
   chrono.stop();
   chrono.setText("00:00");
   resume=false;
   btnStop.setEnabled(false);
   break;
  }
 }


The start button:
The start button can be clicked in two scenarios:
  1. Starting the Chronometer for the first time:
    1. We set base of the Chronometer, which is the time in Milliseconds from where the Chronometer starts counting from.
      We set it to SystemClock.elapsedRealtime() Which is the time in Milliseconds since the device boot (equivalent to current time).
    2. then start the Chronometer
  2. Resuming the chronometer count after start:
    here we start the chronometer again to resume counting from the value it had when it was stopped.

The stop button:
The stop button pauses the chronometer. And sets the resume flag to true to indicate that the next click on the start button will resume counting [not starting counting from zero].

The Reset button:
The stop button resets the chronometer so the next click on start button will start counting from zero

The chronometer can implement OnChronometerTickListener interface which requires an implementation of the onChronometerTick method.


The onChronometerTick method handles the Chronometer tick event which occurs every second.

Here’s the implementation of the onChronometerTick method:
chrono.setOnChronometerTickListener(new OnChronometerTickListener()
        {

   public void onChronometerTick(Chronometer arg0) {
    // TODO Auto-generated method stub
    
    if(!resume)
    {
     
     long minutes=((SystemClock.elapsedRealtime()-chrono.getBase())/1000)/60;
     long seconds=((SystemClock.elapsedRealtime()-chrono.getBase())/1000)%60;
     currentTime=minutes+":"+seconds;
     arg0.setText(currentTime);
     elapsedTime=SystemClock.elapsedRealtime();
    }
    else
    {
     
     long minutes=((elapsedTime-chrono.getBase())/1000)/60;
     long seconds=((elapsedTime-chrono.getBase())/1000)%60;
     currentTime=minutes+":"+seconds;
     arg0.setText(currentTime);
     elapsedTime=elapsedTime+1000;
    }
    
    
   }
         
        }
        );

In this method we handle two scenarios:
  1. The chronometer starts for the first time (or from zero):
    The method is invoked every second Here we calculate the difference between the current time(SystemClock.elapsedRealtime) and the time from which the chronometer started counting(chrono.getBase()) and display it.
    Then we store the current time so that when we pause the chronometer we hold the last value of chronometer
    elapsedTime=SystemClock.elapsedRealtime();
  2. The chronometer is resumed after stop:
    Here we calculate the difference between the last value of the chronometer (elaspedTime) and the value from which the chronometer started counting (chrono.getBase())
    Then we increment the value of the elapsedTime by 1000 milliseconds (1 second) so that it is update with each tick.


And that was a simple stopwatch or timer using Android Chronometer Control. Sure you noticed that it is limited to minutes and seconds only. This is because the onTimerTick method is invoked every second so we cannot update the elapsed milliseconds.

You can download the application from here