1

Possible Duplicate:
android - Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException

I am using this example http://www.androidhive.info/2012/01/android-login-and-registration-with-php-mysql-and-sqlite/ when i have registered my detail in registration form it save data in database but app crash it give below error

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

my regsitration code is below

Register.java

import org.json.JSONException;
import org.json.JSONObject;


import com.example.petencare.library.JSONParser;
import com.example.petencare.library.DatabaseHandler;
import com.example.petencare.library.UserFunctions;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;


/**
 * Handles the user registration activity.
 * 
 */
public class Register extends Activity {

    JSONParser jsonParser = new JSONParser();
    private EditText newUsername;
    private EditText newPassword;
    private EditText newConfiPass;
    private EditText newName;
    private EditText newPhone;
    private TextView Alreadyuser;
    private Button registerButton;
    private TextView registerErrorMsg;
    private ProgressDialog pDialog;

    // JSON Response node names
    private static String KEY_SUCCESS = "success";
    private static String KEY_ERROR = "error";
    private static String KEY_ERROR_MSG = "error_msg";
    private static String KEY_UID = "uid";
    private static String KEY_EMAIL = "email";
    private static String KEY_NAME = "name";
    private static String KEY_MOBILE = "mobile";
    private static String KEY_CREATED_AT = "created_at";


     @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.registration);


            newUsername = (EditText) findViewById(R.id.reg_email);
            newPassword = (EditText) findViewById(R.id.reg_pass);
            newConfiPass = (EditText) findViewById(R.id.reg_passre);
            newName      =(EditText)findViewById(R.id.reg_name);
            newPhone      =(EditText)findViewById(R.id.reg_mobile);
            registerButton = (Button) findViewById(R.id.btnRegister);
            Alreadyuser =    (TextView)findViewById(R.id.link_to_login);
            registerErrorMsg= (TextView)findViewById(R.id.register_error);

            Alreadyuser.setOnClickListener(new TextView.OnClickListener(){ 
                public void onClick (View v){ 
                    Intent i = new Intent(v.getContext(), Login.class);
                    startActivity(i);
                    // Close Registration View

                    finish();
                }
            });


            registerButton.setOnClickListener(new View.OnClickListener() { 
                public void onClick (View view){ 

                new Registeruser().execute();

                }

            });

     }

            class Registeruser extends AsyncTask<String, String, String> {


                @Override
                protected void onPreExecute() {
                    super.onPreExecute();
                    pDialog = new ProgressDialog(Register.this);
                    pDialog.setMessage("Registering. Please wait...");
                    pDialog.setIndeterminate(false);
                    pDialog.setCancelable(false);
                    pDialog.show();

                }



            protected  String doInBackground(String... args) {
                    //Get user details. 
            String email = newUsername.getText().toString();
            String password = newPassword.getText().toString();
            String confirmpassword = newConfiPass.getText().toString();
            String name=           newName.getText().toString();
            String mobile =   newPhone.getText().toString();



            //Check if all fields have been completed.
            if (email.equals("") || password.equals("") || name.equals("") || mobile.equals("")){
                Toast.makeText(getApplicationContext(), 
                        "Please ensure all fields have been completed.",
                          Toast.LENGTH_SHORT).show();
            return null;
            }

            //Check password match. 
            if (!password.equals(confirmpassword)) {
                Toast.makeText(getApplicationContext(), 
                        "The password does not match.",
                            Toast.LENGTH_SHORT).show();
                            newPassword.setText("");
                            newConfiPass.setText("");
                return null;
            }
             UserFunctions userFunction = new UserFunctions();
             JSONObject json = userFunction.registerUser(email, password, name, mobile);


             // check for login response
             try {
                 if (json.getString(KEY_SUCCESS) != null) {
                     registerErrorMsg.setText("");
                     String res = json.getString(KEY_SUCCESS);
                     if(Integer.parseInt(res) == 1){
                         // user successfully registred
                         // Store user details in SQLite Database
                         DatabaseHandler db = new DatabaseHandler(getApplicationContext());
                         JSONObject json_user = json.getJSONObject("user");

                         // Clear all previous data in database
                         userFunction.logoutUser(getApplicationContext());
                         db.addUser(json_user.getString(KEY_EMAIL), json_user.getString(KEY_NAME), json.getString(KEY_UID), json_user.getString(KEY_MOBILE), json_user.getString(KEY_CREATED_AT));
                         // Launch Dashboard Screen
                         Intent dashboard1 = new Intent(getApplicationContext(), MainActivity.class);
                         // Close all views before launching Dashboard
                         dashboard1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                         startActivity(dashboard1);
                         // Close Registration Screen
                         finish();
                     }else{
                         // Error in registration
                         registerErrorMsg.setText("User already existed");
                     }
                 }
             } catch (JSONException e) {
                 e.printStackTrace();
             }  
             return null;
            }

            @Override
    protected void onPostExecute(String file_url){
        // dismiss the dialog once done
        pDialog.dismiss();

            }


     }

}

I am using JSON parsing for sending data and i have a userfunction.java class which code is below

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;

import android.content.Context;

public class UserFunctions {

    private JSONParser jsonParser;

    // Testing in localhost using wamp or xampp
    // use http://10.0.2.2/ to connect to your localhost ie http://localhost/
    private static String loginURL = "http://www.mywebsite.com/android_login_api/";
    private static String registerURL = "http://www.mywebsite.com/android_login_api/";

    private static String login_tag = "login";
    private static String register_tag = "register";

    // constructor
    public UserFunctions(){
        jsonParser = new JSONParser();
    }

    /**
     * function make Login Request
     * @param email
     * @param password
     * */
    public JSONObject loginUser(String email, String password){
        // Building Parameters
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("tag", login_tag));
        params.add(new BasicNameValuePair("email", email));
        params.add(new BasicNameValuePair("password", password));
        JSONObject json = jsonParser.getJSONFromUrl(loginURL, params);
        // return json
        // Log.e("JSON", json.toString());
        return json;
    }

    /**
     * function make Login Request
     * @param name
     * @param email
     * @param password
     * */
    public JSONObject registerUser(String email, String password, String name, String mobile){
        // Building Parameters
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("tag", register_tag));
        params.add(new BasicNameValuePair("email", email));
        params.add(new BasicNameValuePair("password", password));
        params.add(new BasicNameValuePair("name", name));
        params.add(new BasicNameValuePair("mobile", mobile));

        // getting JSON Object
        JSONObject json = jsonParser.getJSONFromUrl(registerURL, params);
        // return json
        return json;
    }

    /**
     * Function get Login status
     * */
    public boolean isUserLoggedIn(Context context){
        DatabaseHandler db = new DatabaseHandler(context);
        int count = db.getRowCount();
        if(count > 0){
            // user logged in
            return true;
        }
        return false;
    }

    /**
     * Function to logout user
     * Reset Database
     * */
    public boolean logoutUser(Context context){
        DatabaseHandler db = new DatabaseHandler(context);
        db.resetTables();
        return true;
    }

}

please help me thanks in advance

Community
  • 1
  • 1
akash
  • 45
  • 7

3 Answers3

3

i'm getting error

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

means you are trying to access UI elements from doInBackground of AsyncTask. it's not possible to access Ui elements or Make Toast from Non UI Thread.

solution is move all EditText validation like code before starting AsyncTask and use onPreExecute of AsyncTask for getting EditText values in doInBackground ,use onPostExecute for Updating Ui when doInBackground execution completed

EDIT :

as on OP request move all validation inside button click as:

    registerButton.setOnClickListener(new View.OnClickListener() { 
        public void onClick (View view){ 

        //  PUT YOUR ALL VALIDATION HERE
        
        if(/* if validation success  */){
           
            // start AsyncTask here
            new Registeruser().execute();
         }
         else{
                // show validation error here
          }
        }

    });
Community
  • 1
  • 1
ρяσѕρєя K
  • 132,198
  • 53
  • 198
  • 213
1

Try removing Toasts in the doInBackground() method. As you are accessing UI in the doInBackground() to show the toasts and even why can't you move the validations' part before you start the asynctask.

Kanth
  • 6,681
  • 3
  • 29
  • 41
0

I think you Should to use RunOnuithread method or use Handler While in doInBackground() of Asynctask Method.

this way use

    @Override
    protected Long doInBackground(String... urls) {
        // Already suggested by Dixit Patel:
        // Use the runOnUiThread method.
        // See his explanation.
        runOnUiThread(new Runnable() {

     @Override
         public void run() {
         if (!password.equals(confirmpassword)) {
            Toast.makeText(getApplicationContext(), 
                    "The password does not match.",
                        Toast.LENGTH_SHORT).show();
                        newPassword.setText("");
                        newConfiPass.setText("");

        }

     }
    });
Dixit Patel
  • 3,190
  • 1
  • 24
  • 36