Sumedh Tambat
Sumedh Tambat

Reputation: 811

custom stopwatch application android

I am trying to develop a custom stop watch application in android but it throw following exception:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

I have also tried to use chronometer but when we use it's stop method it starts from its previous value.

following is my activity file

public class MainActivity extends Activity implements OnClickListener
{

TextView sec,milisec,min;
Button start,stop,pause,resume;
int count=0;
Chronometer chrono;
Timer timer;

@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    chrono=(Chronometer)findViewById(R.id.chronometer);
    milisec=(TextView)findViewById(R.id.milisec);
    sec=(TextView)findViewById(R.id.sec);
    min=(TextView)findViewById(R.id.min);
    start=(Button)findViewById(R.id.start);
    stop=(Button)findViewById(R.id.stop);
    pause=(Button)findViewById(R.id.pause);
    resume=(Button)findViewById(R.id.resume);


    System.out.println("-------1-------");

    start.setOnClickListener(new OnClickListener() 
    {
        @Override
        public void onClick(View v) 
        {
            //chrono.start();

        //count=Integer.parseInt(count_view.getText().toString());*/
        timer = new Timer();
        timer.schedule(new TimerTask()
        {
           public void run()
           {
               System.out.println("-------2-------");
               View v = new View(getApplicationContext());
               count_increment(v);
            }
          },1000,10000);

    }   

    });

    stop.setOnClickListener(new OnClickListener() 
    {
        @Override
        public void onClick(View v) 
        {
            //chrono.clearComposingText();
            //chrono.setText("00");
            timer.cancel();

        }
    });
}

public void count_increment(View v)
{
    count++;
    System.out.println("count="+count);
    //count_str=String.valueOf(count);
    milisec.setText(""+count);

}

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub

}



}

and following is xml file

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginTop="30dp"
    android:gravity="center_horizontal" >

    <TextView
        android:id="@+id/min"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="00" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=":" />

    <TextView
        android:id="@+id/sec"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="00" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=":" />

    <TextView
        android:id="@+id/milisec"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="00" />
</LinearLayout>

<LinearLayout
    android:id="@+id/linearLayout1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginTop="60dp"
    android:gravity="center_horizontal" >

    <TableLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent" >

        <TableRow
            android:id="@+id/tableRow1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <Button
                android:id="@+id/start"
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:text="Start" />

            <Button
                android:id="@+id/stop"
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:text="Stop" />

            <Button
                android:id="@+id/pause"
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:text="Pause" />

            <Button
                android:id="@+id/resume"
                android:layout_width="80dp"
                android:layout_height="wrap_content"
                android:text="Resume" />
        </TableRow>

        <TableRow
            android:id="@+id/tableRow1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <Chronometer
                android:id="@+id/chronometer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Chronometer" />

        </TableRow>
    </TableLayout>
</LinearLayout>

</RelativeLayout>

What is going wrong?
Is there any other way than this to develop stopwatch?

Upvotes: 4

Views: 799

Answers (2)

Umesh
Umesh

Reputation: 4256

you cannot modify a view/setText from a child thread. A view can only be accessed from within the UI thread/main Thread.

try this from inside the child thread

 runOnUiThread(new Runnable() {          
    @Override         
    public void run() {             
       count_increment(v);  
    }     
}); 

Upvotes: 1

Ziteng Chen
Ziteng Chen

Reputation: 1969

The error message is quite self-explained: you shall not touch the UI element directly in a new thread. A possible workaround is that you post a runnable to the UI thread to update the UI by Activity.runOnUiThread()

I mean something like this (pseudo code not tested):

public void count_increment(View v)
{
    count++;
    System.out.println("count="+count);
    //count_str=String.valueOf(count);
    // milisec.setText(""+count);
    final String str = ""+count;
    runOnUiThread(new Runnable() {
        public void run() {
            milisec.setText(str);
        }
    });
}

Upvotes: 1

Related Questions