How to Fix Android CalledFromWrongThreadException

So you’re just cruising along writing the next big Android App dreaming of making it big and getting rich and then BAM! User after user is kicking you in the balls because that great Android application of yours just crashed and it’s complaining about a CalledFromWrongThreadException. Okay, so what happened and how to we fix it?

Well, basically when an Android application starts your process is given a thread that is your “main” thread, or alternately, your “UI” thread. Anytime you want to access or modify any user interface elements you must do so from this thread. The simple reason for this is that the UI components (or Android UI Toolkit as Google calls it) is not thread safe. In other words, bad things happen if multiple threads touch the same control at the same time. It won’t be the end of the world but it will be the end of your application. The end of your application comes via a CalledFromWrongThreadException which is just a type of runtime exception used by Android.

Time for an example. Consider the following Java code:
(in all examples I’ve added a single TextView control within the app resources called textTest)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class TestActivity extends Activity 
{
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        mTimer = new Timer();
        mTimer.schedule(new OnTimer(), 1000);
    }
 
    class OnTimer extends TimerTask
    {
    	public void run()
    	{
    		TextView v = (TextView)TestActivity.this.findViewById(R.id.textTest);
    		v.setText(Integer.toString(mValue));
    		mValue++;
 
    		mTimer.schedule(new OnTimer(), 1000);
    	}
    }
 
    private int mValue = 0;
    Timer mTimer;
}

According to that code, about once every second a counter will be incremented and the content of a TextView control will be updated with the value of the counter. Unfortunalty, when you run it you will see a message similar to this:

Basically, your app just crashed because of a CalledFromWrongThreadException exception because the run method of the OnTimer class was not executed on the user interface thread. Here is a screenshot of the call stack taken from Eclipse showing the exception (referred to as ViewRoot$CalledFromWrongThreadException)

Hmm, so how do we fix this? Well there are numerous ways and I’ll show you two of them. Have a look at this Java code listing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class TestActivity extends Activity 
{
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        mTimer = new Timer();
        mTimer.schedule(new OnTimer(), 1000);
 
    }
 
    class OnTimer extends TimerTask
    {
    	public void run()
    	{
    	    TestActivity.this.findViewById(R.id.textTest).post(new Runnable()
    	    {
    		public void run()
    		{
    		    TextView v = (TextView)TestActivity.this.findViewById(R.id.textTest);
 
    	    	    v.setText(Integer.toString(mJValue));
    	            mValue++;
 
    	    	    mTimer.schedule(new OnTimer(), 1000);
    		}
 
    	    });
    	}
    }
 
    private int mValue = 0;
    Timer mTimer;
}

So here we use the post method of the View class. This caused the run method to be queued up to be ran on the main UI thread. And thus, no annoying CalledFromWrongThreadException problems and the code properly updates and displays the counter as we hoped would have happened in the previous code listing.

Just for fun, and because that code above looks pretty ugly, let’s look at another way to achieve the same functionality:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class TestActivity extends Activity 
{
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        mHandler.postDelayed(mUpdateTimeTask, 1000);
    }
 
    private Runnable mUpdateTimeTask = new Runnable()
    {
    	public void run()
    	{
    		long ms = SystemClock.uptimeMillis();
 
    		TextView v = (TextView)TestActivity.this.findViewById(R.id.textTest);
    		v.setText(Integer.toString(mValue));
    		mValue++;
 
    		mHandler.postAtTime(this, ms + 1000);
 
    	}
    };
 
    private int mValue = 0;
    private Handler mHandler = new Handler();
}

This time, instead of calling View.post, I use a Handler and post with that instead. I also do away with the java.util.timer usage opting for SystemClock.uptimeMillis instead. I like this method better but either way will work. Another possible method you can look into is using AysncTask instead of using a Handler or View.post.

So there you have it, multiple ways to fix CalledFromWrongThreadException issues and avoid getting kicked in the balls by your end users! You’re now on your way to writing multithreaded Android Apps! Also, just so ya know, this problem is not exclusive to Java or the Android platform. It pretty much affects any user interface framework that has to support multi-threaded applications. You can read about it in C# as well.

I hope this helps somebody out there avoid pain. Let me know if it does help or if you have any questions.

September 19, 2011 · crow · No Comments
Tags: , , ,  Â· Posted in: Android, Java, Programming

Leave a Reply

Connect with Facebook

*