Alexander Sagen
Alexander Sagen

Reputation: 127

Android coding: ViewRootImpl$CalledFromWrongThreadException. [Noob]

06-13 17:29:30.750: W/dalvikvm(6257): threadid=13: thread exiting with uncaught exception (group=0xb1af0ba8)
06-13 17:29:30.780: E/AndroidRuntime(6257): FATAL EXCEPTION: Thread-251
06-13 17:29:30.780: E/AndroidRuntime(6257): Process: me.l0lkj.birthdaytimer, PID: 6257
06-13 17:29:30.780: E/AndroidRuntime(6257): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:857)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.view.ViewGroup.invalidateChild(ViewGroup.java:4320)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.view.View.invalidate(View.java:10935)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.view.View.invalidate(View.java:10890)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.widget.TextView.updateAfterEdit(TextView.java:7430)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at  android.widget.TextView.handleTextChanged(TextView.java:7453)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:9183)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:962)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:496)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:253)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:30)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.widget.TextView.append(TextView.java:3409)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at android.widget.TextView.append(TextView.java:3396)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at me.l0lkj.birthdaytimer.Screen2.appendTextAndScroll(Screen2.java:180)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at me.l0lkj.birthdaytimer.Screen2.access$1(Screen2.java:177)
06-13 17:29:30.780: E/AndroidRuntime(6257):     at  me.l0lkj.birthdaytimer.Screen2$ListenFromServer.run(Screen2.java:273)
06-13 17:29:58.330: I/Process(6257): Sending signal. PID: 6257 SIG: 9
06-13 17:33:57.960: D/dalvikvm(6315): GC_FOR_ALLOC freed 57K, 9% free 3567K/3920K,   paused 137ms, total 138ms
06-13 17:33:58.590: D/(6315): HostConnection::get() New Host Connection established  0xb91170e0, tid 6315
06-13 17:34:10.310: E/Første skjerm(6315): 10.0.0.59.1500.Anonym.123123
06-13 17:34:11.460: D/dalvikvm(6315): GC_FOR_ALLOC freed 19K, 8% free 3894K/4200K, paused 23ms, total 26ms
06-13 17:34:11.480: I/dalvikvm-heap(6315): Grow heap (frag case) to 6.498MB for 2536936-byte allocation
06-13 17:34:11.510: D/dalvikvm(6315): GC_FOR_ALLOC freed 1K, 5% free 6370K/6680K, paused 31ms, total 31ms
06-13 17:34:11.690: E/Andre skjerm(6315): 10.0.0.59.1500.Anonym.123123

I just startet coding and am currently working on my chat client for Android and got this problem:

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

I have searched around but cant seem to find anything that solves this problem. What I want in short terms:

  1. A good explanation of what this problem is and how to get around it. Why it occurs etc.

  2. Correct my code or help me find a solution to it. I read what was a bit obvious to about what classes can and can not acces that, but I found no good solution.

I have a bit messy code, so sorry about that ( I'm still a noob, remeber that :) )

package me.l0lkj.birthdaytimer;

import java.io.IOException; 
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;

import me.l0lkj.birthdaytimer.userlisthandler.UserInfo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Layout;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;

public class Screen2 extends Activity {

ArrayList<UserInfo> lastPlayerRegrex = new ArrayList<UserInfo>();

boolean running = false;

ScrollView chat_ScrollView;
TextView chat_text_chat;
TextView editText1;


String server;
int port;
String brukernavn;
String passord;


private ObjectInputStream sInput;   
private ObjectOutputStream sOutput;     
private Socket socket;

@Override
public void onCreate(Bundle savedInstanceState) {

    running = true;

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

    Button btnSend = (Button) findViewById(R.id.btnSend);
    btnSend.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            sendLine();
        }
    });

    Button btnClose = (Button) findViewById(R.id.btnClose);
    btnClose.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            appendTextAndScroll("Forlater nå chatten!!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            running = false;
            disconnect();
        }
    });

    Button btnList = (Button) findViewById(R.id.btnList);
    btnList.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            //String test = "NAME:l0lkj;IP:10.0.0.39;SINCE:123422,NAME:asdasd;IP:10.0.0.234;SINCE:345678,NAME:ihkjhg;IP:10.04.6.7;SINCE:078273549234";

            sendMessage(new Message(Message.LIST_USERS, ""));   

            //ArrayList<UserInfo> users = Format(test);
            /*
             * Denne metoden skal sende inn en Message med syntaksen:
             *      
             *      new Message(4, "");
             *      
             * 
             * 
             */
            /*
            for(UserInfo user : users){
                long millis = user.getTid();

                int seconds = (int) (millis / 1000) % 60 ;
                int minutes = (int) ((millis / (1000*60)) % 60);
                int hours   = (int) ((millis / (1000*60*60)) % 24);

                String userdata = user.getName() + " IP:" + user.getIp() + " \n        Tid online: " + hours + " timer, " + minutes + " minutter og " + seconds + " sekunder.";
                appendTextAndScroll(userdata);
            }*/
        }
    });

    editText1 = (TextView) this.findViewById(R.id.editText1);
    editText1.setOnEditorActionListener(new OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            boolean handled = false;
            if (actionId == EditorInfo.IME_ACTION_SEND) {
                sendLine();
                handled = true;
            }
            return handled;
        }
    });

    chat_text_chat = (TextView) this.findViewById(R.id.chat_text_chat);
    chat_text_chat.setMovementMethod(new ScrollingMovementMethod());

    Intent i = getIntent();

    server = i.getStringExtra("server");
    port = Integer.parseInt(i.getStringExtra("port"));
    brukernavn = i.getStringExtra("brukernavn");
    passord = i.getStringExtra("passord");

    Log.e("Andre skjerm", server + "." + port + "." + brukernavn + "." + passord);

    appendTextAndScroll("");

    this.start();

}

private void disconnect() {
    try { 
        if(sInput != null) sInput.close();
    }
    catch(Exception e) {}
    try {
        if(sOutput != null) sOutput.close();
    }
    catch(Exception e) {}
    try{
        if(socket != null) socket.close();
    }
    catch(Exception e) {}

    finish();

}

@SuppressWarnings("unused")
private void startConnection(String address, int port){

}

private void broadcastText(String text){
    //appendTextAndScroll(text);
    this.sendMessage(new Message(Message.MELDING, text));
    //sende til serveren
}

private void sendMessage(Message msg){
    try {
        sOutput.writeObject(msg);
    }
    catch(IOException e) {
        appendTextAndScroll("Exception writing to server: " + e);
    }
}

private void appendTextAndScroll(String text) {
    if(text.length() >= 1){
        if(chat_text_chat != null){
            chat_text_chat.append(text + "\n");
            final Layout layout = chat_text_chat.getLayout();
            if(layout != null){
                int scrollDelta = layout.getLineBottom(chat_text_chat.getLineCount() - 1) - chat_text_chat.getScrollY() - chat_text_chat.getHeight();
                if(scrollDelta > 0){
                    chat_text_chat.scrollBy(0, scrollDelta);
                }
            }
        }
    }
}

private void sendLine(){
    String text = editText1.getText().toString();
    editText1.setText("");
    broadcastText(text);
}

public ArrayList<UserInfo> Format(String rawFromServer){

    ArrayList<UserInfo> userObjects = new ArrayList<UserInfo>();

    String[] users = rawFromServer.split(",");
    for(String user : users){

        String name = null;
        String ip = null;
        long since = 0; 

        String[] keys = user.split(";");
        for(String key : keys){

            String[] keyAndAns = key.split(":");

            if(keyAndAns[0].equals("NAME")){
                name = keyAndAns[1];
            }

            if(keyAndAns[0].equals("IP")){
                ip = keyAndAns[1];
            }

            if(keyAndAns[0].equals("SINCE")){
                since = Long.parseLong(keyAndAns[1]);
            }

        }
        userObjects.add(new UserInfo(name, ip, since));
    }
    return userObjects;
}


public boolean start() {
    try {
        socket = new Socket(server, port);
    } 
    catch(Exception ec) {
        appendTextAndScroll("Feil under oppkobling til serveren:" + ec);
        return false;
    }

    String msg = "Kobling godtatt fra " + socket.getInetAddress() + ":" + socket.getPort();
    appendTextAndScroll(msg);

    try
    {
        sInput  = new ObjectInputStream(socket.getInputStream());
        sOutput = new ObjectOutputStream(socket.getOutputStream());
    }
    catch (IOException eIO) {
        appendTextAndScroll("Unntak ved ny Input/output strøm: " + eIO);
        return false;
    }

    new ListenFromServer().start();
    try {
        sOutput.writeObject((brukernavn + ":" + passord));
    } catch (IOException e) {
        e.printStackTrace();
    }

    return true;
}

class ListenFromServer extends Thread {

    public void run() {
        while(true) {
            try {

                String msg = (String) sInput.readObject();

                appendTextAndScroll(msg);
            }

            catch(IOException e) {
                appendTextAndScroll("Serveren har stengt koblingen: " + e);
                break;
            }
            catch(ClassNotFoundException e2) {}
        }
    }
}

}

Thank you for answer;

Best regards Alexander

Upvotes: 1

Views: 666

Answers (1)

matiash
matiash

Reputation: 55370

You're getting a CalledFromWrongThreadException error because you're trying to update views from a background thread. That is not allowed.

In this case, the easiest change would probably be to modify appendTextAndScroll() itself to make sure it runs in the UI thread.

private void appendTextAndScroll(String text)
{
    runOnUiThread(new Runnable()
    {
        public void run()
        {
            if(text.length() >= 1){
                if(chat_text_chat != null){
                    chat_text_chat.append(text + "\n");
                    final Layout layout = chat_text_chat.getLayout();
                    if(layout != null){
                        int scrollDelta = layout.getLineBottom(chat_text_chat.getLineCount() - 1) - chat_text_chat.getScrollY() - chat_text_chat.getHeight();
                        if(scrollDelta > 0){
                            chat_text_chat.scrollBy(0, scrollDelta);
                        }
                    }
                }
            }
        }
    });
}

Upvotes: 1

Related Questions