1

I am doing a login application (taken from here) and basically, i want login using the nric and password which will connect to a online database, however there the program crash after i added the async task into the codes.

public class LoginActivity extends Activity {
Button btnLogin;
Button btnLinkToRegister;
EditText inputNric;
EditText inputPassword;
TextView loginErrorMsg;

// Progress Dialog
private ProgressDialog pDialog;

// JSON Response node names
//success is the column name of the database - KEY_SUCCESS is we create the name 
private static String KEY_SUCCESS = "success";
private static String KEY_ERROR = "error";
private static String KEY_ERROR_MSG = "error_msg";
private static String KEY_NAME = "name";
private static String KEY_NRIC = "nric";
private static String KEY_CREATED_AT = "created_at";

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

    // Importing all assets like buttons, text fields
    inputNric = (EditText) findViewById(R.id.loginNric);
    inputPassword = (EditText) findViewById(R.id.loginPassword);
    btnLogin = (Button) findViewById(R.id.buttonLogin);
    btnLinkToRegister = (Button) findViewById(R.id.btnLinkToRegisterScreen);
    loginErrorMsg = (TextView) findViewById(R.id.login_error);

    // login button click event
    btnLogin.setOnClickListener(new View.OnClickListener() {

        public void onClick(View arg0) {
            // starting background task to update case
            new LoginUser().execute();
        }
    });

    // Link to Register Screen
    btnLinkToRegister.setOnClickListener(new View.OnClickListener() {

        public void onClick(View view) {
            Intent i = new Intent(getApplicationContext(),
            RegisterActivity.class);
            startActivity(i);
            finish();
        }
    });
}

/**
 * Background Async Task to  Login User
 * */
class LoginUser extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     * */        
    protected void onPreExecute() {
    super.onPreExecute();
    pDialog = new ProgressDialog(LoginActivity.this);
    pDialog.setMessage("Logging In ...");
    pDialog.setIndeterminate(false);
    pDialog.setCancelable(true);
    pDialog.show();
    }

    /**
    * Logging in
    * */
    protected String doInBackground(String... params) {

            String nric = inputNric.getText().toString();
            String password = inputPassword.getText().toString();
            UserFunctions userFunction = new UserFunctions();
            Log.d("Button", "Login");
            JSONObject json = userFunction.loginUser(nric, password);

            // check for login response
            try {
                if (json.getString(KEY_SUCCESS) != null) {
                    loginErrorMsg.setText("");
                    String res = json.getString(KEY_SUCCESS); 
                    if(Integer.parseInt(res) == 1){
                        // user successfully logged in
                        // 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_NAME), json_user.getString(KEY_NRIC), json_user.getString(KEY_CREATED_AT));                      

                        // Launch home Screen
                        Intent home = new Intent(getApplicationContext(), HomeActivity.class);

                        // Close all views before launching home
                        home.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(home);

                        // Close Login Screen
                        finish();
                    }else{
                        // Error in login
                        loginErrorMsg.setText("Incorrect username/password");
                    }
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
    }

     /**
     * After completing background task Dismiss the progress dialog
     * **/
    protected void onPostExecute(String file_url) {
        // dismiss the dialog once case deleted
        pDialog.dismiss();

    }
}

}

Logcat Errors:

08-15 06:20:26.254: E/AndroidRuntime(302): FATAL EXCEPTION: AsyncTask #1
08-15 06:20:26.254: E/AndroidRuntime(302): java.lang.RuntimeException: An error occured      while executing doInBackground()
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.os.AsyncTask$3.done(AsyncTask.java:200)
08-15 06:20:26.254: E/AndroidRuntime(302):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
08-15 06:20:26.254: E/AndroidRuntime(302):  at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
08-15 06:20:26.254: E/AndroidRuntime(302):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
08-15 06:20:26.254: E/AndroidRuntime(302):  at java.util.concurrent.FutureTask.run(FutureTask.java:137)
08-15 06:20:26.254: E/AndroidRuntime(302):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
08-15 06:20:26.254: E/AndroidRuntime(302):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
08-15 06:20:26.254: E/AndroidRuntime(302):  at java.lang.Thread.run(Thread.java:1096)
08-15 06:20:26.254: E/AndroidRuntime(302): Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.view.ViewRoot.checkThread(ViewRoot.java:2802)
08-15 06:20:26.254: E/AndroidRuntime(302):  at      android.view.ViewRoot.requestLayout(ViewRoot.java:594)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.view.View.requestLayout(View.java:8125)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.view.View.requestLayout(View.java:8125)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.view.View.requestLayout(View.java:8125)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.view.View.requestLayout(View.java:8125)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.view.View.requestLayout(View.java:8125)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.widget.TextView.checkForRelayout(TextView.java:5378)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.widget.TextView.setText(TextView.java:2688)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.widget.TextView.setText(TextView.java:2556)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.widget.TextView.setText(TextView.java:2531)
08-15 06:20:26.254: E/AndroidRuntime(302):  at com.pivestigator.LoginActivity$LoginUser.doInBackground(LoginActivity.java:107)
08-15 06:20:26.254: E/AndroidRuntime(302):  at com.pivestigator.LoginActivity$LoginUser.doInBackground(LoginActivity.java:1)
08-15 06:20:26.254: E/AndroidRuntime(302):  at android.os.AsyncTask$2.call(AsyncTask.java:185)
08-15 06:20:26.254: E/AndroidRuntime(302):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
08-15 06:20:26.254: E/AndroidRuntime(302):  ... 4 more
08-15 06:20:26.344: W/ActivityManager(75):   Force finishing activity com.pivestigator/.LoginActivity
08-15 06:20:28.554: E/WindowManager(302): Activity com.pivestigator.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44f33188 that was originally added here
08-15 06:20:28.554: E/WindowManager(302): android.view.WindowLeaked: Activity com.pivestigator.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44f33188 that was originally added here
08-15 06:20:28.554: E/WindowManager(302):   at android.view.ViewRoot.<init>(ViewRoot.java:247)
08-15 06:20:28.554: E/WindowManager(302):   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
08-15 06:20:28.554: E/WindowManager(302):   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
08-15 06:20:28.554: E/WindowManager(302):   at android.view.Window$LocalWindowManager.addView(Window.java:424)
08-15 06:20:28.554: E/WindowManager(302):   at android.app.Dialog.show(Dialog.java:241)
08-15 06:20:28.554: E/WindowManager(302):   at com.pivestigator.LoginActivity$LoginUser.onPreExecute(LoginActivity.java:90)
08-15 06:20:28.554: E/WindowManager(302):   at android.os.AsyncTask.execute(AsyncTask.java:391)
08-15 06:20:28.554: E/WindowManager(302):   at com.pivestigator.LoginActivity$1.onClick(LoginActivity.java:60)
08-15 06:20:28.554: E/WindowManager(302):   at android.view.View.performClick(View.java:2408)
08-15 06:20:28.554: E/WindowManager(302):   at android.view.View$PerformClick.run(View.java:8816)
08-15 06:20:28.554: E/WindowManager(302):   at android.os.Handler.handleCallback(Handler.java:587)
08-15 06:20:28.554: E/WindowManager(302):   at android.os.Handler.dispatchMessage(Handler.java:92)
08-15 06:20:28.554: E/WindowManager(302):   at android.os.Looper.loop(Looper.java:123)
08-15 06:20:28.554: E/WindowManager(302):   at android.app.ActivityThread.main(ActivityThread.java:4627)
08-15 06:20:28.554: E/WindowManager(302):   at java.lang.reflect.Method.invokeNative(Native Method)
08-15 06:20:28.554: E/WindowManager(302):   at java.lang.reflect.Method.invoke(Method.java:521)
08-15 06:20:28.554: E/WindowManager(302):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
08-15 06:20:28.554: E/WindowManager(302):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
08-15 06:20:28.554: E/WindowManager(302):   at dalvik.system.NativeStart.main(Native Method)
4

2 回答 2

2

The error itself described you are trying to update or access Activity's Main UI Thread in other Thread which is not allowed.

Actually you are trying to update Activity's View from AsyncTask's doInBackground() (As doInBAckground() runs in worker thread) method. in Android its not allowed.

I think these lines,

String nric = inputNric.getText().toString();
String password = inputPassword.getText().toString();

and

loginErrorMsg.setText("Incorrect username/password");

cause error.. So remove these lines from doInBackground() of AsyncTask and put those code lines in onPreExecute() and onPostExecute() of AsyncTask.

于 2012-08-15T06:43:19.377 回答
0

Move loginErrorMsg.setText("Incorrect username/password"); to the AsyncTask's onProgressUpdate(..) method, and call publishProgress(..) instead in the doInBackground() thread.

The other problem is (wich in my opinion caused the crash) is that you are trying to start a new Activity from the worker thread. Move the following code to the onPostExecute(..) method, just after pDialog.dismiss() and check there if the login was successful through the doInBackground() return value, and the argument of onPostExecute().

The leaked window exception means, that the ProgressDialog is still visible, when you try to finish your acttivity.

class LoginUser extends AsyncTask<Void, String, Boolean> {

    /**
     * Before starting background thread Show Progress Dialog
     * */        
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(LoginActivity.this);
        pDialog.setMessage("Logging In ...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    /**
    * Logging in
    * */
    protected Boolean doInBackground(Void... params) {

        String nric = inputNric.getText().toString();
        String password = inputPassword.getText().toString();
        UserFunctions userFunction = new UserFunctions();
        Log.d("Button", "Login");
        JSONObject json = userFunction.loginUser(nric, password);

        boolean isSuccess = false;

        // check for login response
        try {
            if (json.getString(KEY_SUCCESS) != null) {
                // Set the error TextField on the UI thread
                publishProgress("");

                String res = json.getString(KEY_SUCCESS); 
                if(Integer.parseInt(res) == 1){
                    // user successfully logged in
                    // 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_NAME), json_user.getString(KEY_NRIC), json_user.getString(KEY_CREATED_AT));                      


                    // We logged in successfully
                    isSuccess = true;
                }else{
                    // Error in login
                    // Set the error TextField on the UI thread
                    publishProgress("Incorrect username/password");
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return isSuccess;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        loginErrorMsg.setText(values[0]);
    }

     /**
     * After completing background task Dismiss the progress dialog
     * **/
    protected void onPostExecute(Boolean result) {
        // dismiss the dialog once case deleted
        pDialog.dismiss();

        if(result.booleanValue()){
            // Launch home Screen
                Intent home = new Intent(getApplicationContext(), HomeActivity.class);

                // Close all views before launching home
                home.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(home);

                // Close Login Screen
                finish();
        }
    }
}
于 2012-08-15T06:58:25.320 回答