Error "Only The Original Thread That Created A View Hierarchy Can Touch Its Views" In Android
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;
public class AndroidLogin extends Activity implements OnClickListener {
Button ok, back, exit;
TextView result;
EditText uname;
EditText pword;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
StrictMode.ThreadPolicy policy =
new StrictMode.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);
}
@Override
public void onClick(View view) {
// TODO Auto-generated method stub
final String resultText;
final String username = uname.getText().toString();
final String password = pword.getText().toString();
if (view == ok) {
Thread t = new Thread() {
public void run() {
postLoginData(username,password);
}
};
t.start();
}
}
private void postLoginData(String username,String password) {
try {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
Log.e("Response-->", "after httpclient");
/* login.php returns true if username and password is equal to saranga */
HttpPost httppost = new HttpPost("http://10.0.2.2/login.php");
Log.e("Response-->", "after httppost");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("username", username));
nameValuePairs.add(new BasicNameValuePair("password", password));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
Log.e("Responce-->", "after using the list name pair");
// Execute HTTP Post Request
Log.w("SENCIDE", "Execute HTTP Post Request");
HttpResponse response = httpclient.execute(httppost);
Log.e("Responce-->", "after execute the http response");
String str = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
if (str.toString().equalsIgnoreCase("true")) {
runOnUiThread(new Runnable() {
public void run() {
result.setText("Login Successful");
}
});
} else {
runOnUiThread(new Runnable() {
public void run() {
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() {
public void run() {
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(new Runnable() {
public void run() {
result.setText(resultText);
}
});
}
Post a Comment for "Error "Only The Original Thread That Created A View Hierarchy Can Touch Its Views" In Android"