r0flonic
r0flonic

Reputation: 13

Can't access views from another thread, even when using a handler

I am writing a simple app used for communicating between a server and an app on a local network. Writing and receiving messages works without problems. But I can't display the messages I received in a Textview.

For receiving incoming messages, I make use of a (worker)thread. When I receive something, I send the message to a handler in the mainthread which should then display the message in a Textview.
But everytime the handler tries to display the message, I get the exception:
"Only the original thread that created a view hierarchy can touch its views."

I've searched many websites, including this one, to find a solution but still couldn't fix the problem. Please help me out.

Code:

    public class TCPClientActivity extends Activity {
    BufferedWriter output;
    Socket s = new Socket();

    //my handler
    private Handler mHandler;
    //where I want to display the message
    private TextView lblChat;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.tcpclient);

        Button btnConnect = (Button)findViewById(R.id.btnConnect);
        Button btnSend = (Button) findViewById(R.id.btnSend);
        //creating the TextView
        lblChat = (TextView) findViewById(R.id.lblChat);
        final EditText tbIP = (EditText) findViewById(R.id.tbIP);
        final EditText tbInput = (EditText) findViewById(R.id.tbInput);

        //creating the handler
        mHandler = new Handler()
        {
            @Override
            public void handleMessage(Message msg)
            {
                switch(msg.what)
                {
                    case 1:
                    {
                        lblChat.append("Received: " + msg.obj + "\r\n" );
                    }
                }
            }
        };
}

//Thread in which I receive incoming Messages from the server
    Thread communication = new Thread()
    {
        @Override
        public void run() 
        {
            String finalText = "";

            while(true) 
            {
                try
                {
                    DataInputStream inputStream = new DataInputStream(s.getInputStream());

                    int bytesRead;
                    byte[] b = new byte[4096];

                    bytesRead = inputStream.read(b,0,b.length);

                finalText = EncodingUtils.getAsciiString(b);

                //sending the message to the handler
                    Message msg = new Message();
                    msg.what = 1;
                    msg.obj = finalText;

                    mHandler.handleMessage(msg);
            }

                //android.view.ViewRoot$CalledFromWrongThreadException: 
                //Only the original thread that created a view hierarchy can touch its views.
                //That's the exception I get when running the program
            catch (Exception e) 
            {
                e.printStackTrace();
            }
        }
        }
    };

//method where I connect to the server
    private void connectToServer(String ip)
    {
        try
        {
            if(!ip.equals(""))
            {
                s = new Socket(ip, 3000);
            }

            else
            {
                s = new Socket("10.0.0.143", 3000);
            }

            output = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            output.write("Android Connected");
            output.flush();

    //      new CommuTask().execute();

            //starting the thread
            communication.start();
    //      s.close();
        }

        catch(UnknownHostException e)
        {
            e.printStackTrace();
            try {
                s.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

        catch(IOException e)
        {
            e.printStackTrace();
            try {
                s.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

    }
}

Upvotes: 1

Views: 975

Answers (2)

Ted Hopp
Ted Hopp

Reputation: 234867

Instead of this:

mHandler.handleMessage(msg);

Use this:

mHandler.sendMessage(msg);

Upvotes: 0

Blundell
Blundell

Reputation: 76574

You are invoking the method on the handler directly (therefore on your worker thread) instead of pushing the message

Instead of:

 mHandler.handleMessage(msg);

you will want:

 mHandler.sendMessage(msg);

Ref: http://developer.android.com/reference/android/os/Handler.html#sendMessage(android.os.Message)

Upvotes: 1

Related Questions