Skip to content Skip to sidebar Skip to footer

Error "only The Original Thread That Created A View Hierarchy Can Touch Its Views" In Android

I am creating a simple app for login using Android and PHP but I get an error, can anyone help me? I am trying to make a relation between the Android as the client side and PHP/MyS

Solution 1:

The solution is in the log from logcat:

04-04 18:38:47.596: E/AndroidRuntime(413): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Posting user/password is working. You get the "true" response alright, but then you try to set a label or similar, in a view that was created outside the thread. That's a no-no.

result.setText("Login successful");

Look at the Android SDK docs about threads/processes on how to update views from other threads: http://developer.android.com/guide/components/processes-and-threads.html

Solution 2:

OK I made some modifications to your code it's still ugly and requires lots of refactoring but tell me if it throws any exceptions.

EDIT: Added your username and password passing to the request as parameters to your postLoginData(String password,String username) method. That should do it.


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

publicclassAndroidLoginextendsActivityimplementsOnClickListener {


    Button ok, back, exit;
    TextView result;
    EditText uname;
    EditText pword;

    @OverridepublicvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        StrictMode.ThreadPolicypolicy=newStrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        // Login button clicked
        ok = (Button) findViewById(R.id.btn_login);
        ok.setOnClickListener(this);
        uname = (EditText) findViewById(R.id.txt_username);
        pword = (EditText) findViewById(R.id.txt_password);
        result = (TextView) findViewById(R.id.lbl_result);


    }

    @OverridepublicvoidonClick(View view) {
        // TODO Auto-generated method stubfinal String resultText;   

        finalStringusername= uname.getText().toString();           
        finalStringpassword= pword.getText().toString();


        if (view == ok) {
            Threadt=newThread() {

                publicvoidrun() {
                    postLoginData(username,password);
                }
            };
            t.start();

        }
    }

    privatevoidpostLoginData(String username,String password) {

        try {
            // Create a new HttpClient and Post HeaderHttpClienthttpclient=newDefaultHttpClient();
            Log.e("Response-->", "after httpclient");
        /* login.php returns true if username and password is equal to saranga */HttpPosthttppost=newHttpPost("http://10.0.2.2/login.php");
            Log.e("Response-->", "after httppost");


            List<NameValuePair> nameValuePairs = newArrayList<NameValuePair>(2);
            nameValuePairs.add(newBasicNameValuePair("username", username));
            nameValuePairs.add(newBasicNameValuePair("password", password));

            httppost.setEntity(newUrlEncodedFormEntity(nameValuePairs));
            Log.e("Responce-->", "after using the list name pair");

            // Execute HTTP Post Request
            Log.w("SENCIDE", "Execute HTTP Post Request");
            HttpResponseresponse= httpclient.execute(httppost);
            Log.e("Responce-->", "after execute the http response");
            Stringstr= EntityUtils.toString(response.getEntity(), HTTP.UTF_8);

            if (str.toString().equalsIgnoreCase("true")) {

                runOnUiThread(newRunnable() {
                    publicvoidrun() {
                        result.setText("Login Successful");

                    }
                });


            } else {
                runOnUiThread(newRunnable() {
                    publicvoidrun() {
                        result.setText("Duh");

                    }
                });
            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


}

Solution 3:

You may not make changes to android views off the main UI thread. In your example you are starting a new thread and running postLoginData() on it. Because postLoginData ALSO sets the text of a textview you get this error.

You should: do the http request on your new thread, then on the UI thread change the text.

There are a variety of ways to do this.

And this super simple but probably not advised way to do it to just get you on your feet. Yo will want to do this anytime you are making a change inside your new thread to the UI, so in this example when you are setting the text of result.

result.post(new Runnable() {
        publicvoidrun() {
            result.setText(str);
        }
    });
}

Which will run on the UI thread. You really should look at the two options I posted first or you will just run into more trouble.

** edit ** You need to just replace this code to publish on the main thread instead of the new thread.

if(str.toString().equalsIgnoreCase("true"))
{
 Log.w("SENCIDE", "TRUE");
 result.setText("Login successful");  
}else
{
 Log.w("SENCIDE", "FALSE");
 result.setText(str);            
}

Make it look like this:

final String resultText;
if(str.toString().equalsIgnoreCase("true")) {
    resultText = "Login successful";
}else {
    resultText = str;
}
result.post(newRunnable() {
        publicvoidrun() {
            result.setText(resultText);
        }
    });
}

Post a Comment for "Error "only The Original Thread That Created A View Hierarchy Can Touch Its Views" In Android"