2015-04-05 66 views
0

我正在創建一個具有登錄活動並使用parse.com作爲網絡服務的應用程序。我在android studio中使用了默認的loginactivity.java文件。在我的類UserLoginTask中,我使用瞭解析登錄方法。但我不確定有什麼問題。該應用程序需要電子郵件ID和密碼。進度條適用於倒計時,然後應用程序關閉。然後在某個時間後出現錯誤。嘗試登錄時使用的應用程序崩潰(使用解析對象)

這是loginactivty.java。

package com.redux.kumardivyarajat.attendance; 

    import android.animation.Animator; 
    import android.animation.AnimatorListenerAdapter; 
    import android.annotation.TargetApi; 
    import android.app.AlertDialog; 
    import android.app.LoaderManager.LoaderCallbacks; 
    import android.content.ContentResolver; 
    import android.content.CursorLoader; 
    import android.content.Intent; 
    import android.content.Loader; 
    import android.database.Cursor; 
    import android.net.Uri; 
    import android.os.AsyncTask; 
    import android.os.Build; 
    import android.os.Build.VERSION; 
    import android.os.Bundle; 
    import android.provider.ContactsContract; 
    import android.support.v7.app.ActionBarActivity; 
    import android.text.TextUtils; 
    import android.view.KeyEvent; 
    import android.view.View; 
    import android.view.View.OnClickListener; 
    import android.view.inputmethod.EditorInfo; 
    import android.widget.ArrayAdapter; 
    import android.widget.AutoCompleteTextView; 
    import android.widget.Button; 
    import android.widget.EditText; 
    import android.widget.TextView; 

    import com.parse.LogInCallback; 
    import com.parse.ParseException; 
    import com.parse.ParseUser; 

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


    /** 
    * A login screen that offers login via email/password. 
    */ 
@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
public class LoginActivity extends ActionBarActivity implements  LoaderCallbacks<Cursor> { 

/** 
* A dummy authentication store containing known user names and passwords. 
* TODO: remove after connecting to a real authentication system. 
*/ 




/** 
* Keep track of the login task to ensure we can cancel it if requested. 
*/ 
private UserLoginTask mAuthTask = null; 

// UI references. 
private AutoCompleteTextView mEmailView; 
private EditText mPasswordView; 
private View mProgressView; 
private View mLoginFormView; 




@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_login2); 

    Button mSignUpButton = (Button)findViewById(R.id.SignUpButtonInsideLogin); 
    mSignUpButton.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      Intent intent = new Intent(LoginActivity.this, SignUpActivity.class); 
      startActivity(intent); 

     } 
    }); 

    // Set up the login form. 
    mEmailView = (AutoCompleteTextView) findViewById(R.id.email); 
    populateAutoComplete(); 

    mPasswordView = (EditText) findViewById(R.id.password); 
    mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() { 
     @Override 
     public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) { 
      if (id == R.id.login || id == EditorInfo.IME_NULL) { 
       attemptLogin(); 
       return true; 
      } 
      return false; 
     } 
    }); 

    Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button); 
    mEmailSignInButton.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      attemptLogin(); 
     } 
    }); 

    mLoginFormView = findViewById(R.id.login_form); 
    mProgressView = findViewById(R.id.login_progress); 
    //mSignUpTextView = (TextView) findViewById(R.id.SignupText); 

} 

private void populateAutoComplete() { 
    if (VERSION.SDK_INT >= 14) { 
     // Use ContactsContract.Profile (API 14+) 
     getLoaderManager().initLoader(0, null, this); 
    } else if (VERSION.SDK_INT >= 8) { 
     // Use AccountManager (API 8+) 
     new SetupEmailAutoCompleteTask().execute(null, null); 
    } 
} 


/** 
* Attempts to sign in or register the account specified by the login form. 
* If there are form errors (invalid email, missing fields, etc.), the 
* errors are presented and no actual login attempt is made. 
*/ 
public void attemptLogin() { 
    if (mAuthTask != null) { 
     return; 
    } 

    // Reset errors. 
    mEmailView.setError(null); 
    mPasswordView.setError(null); 

    // Store values at the time of the login attempt. 
    String email = mEmailView.getText().toString(); 
    String password = mPasswordView.getText().toString(); 

    email = email.trim(); 
    password = password.trim(); 

    boolean cancel = false; 
    View focusView = null; 


    // Check for a valid password, if the user entered one. 
    if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) { 
     mPasswordView.setError(getString(R.string.error_invalid_password)); 
     focusView = mPasswordView; 
     cancel = true; 
    } 

    // Check for a valid email address. 
    if (TextUtils.isEmpty(email)) { 
     mEmailView.setError(getString(R.string.error_field_required)); 
     focusView = mEmailView; 
     cancel = true; 
    } else if (!isEmailValid(email)) { 
     mEmailView.setError(getString(R.string.error_invalid_email)); 
     focusView = mEmailView; 
     cancel = true; 
    } 

    if (cancel) { 
     // There was an error; don't attempt login and focus the first 
     // form field with an error. 
     focusView.requestFocus(); 
    } else { 
     // Show a progress spinner, and kick off a background task to 
     // perform the user login attempt. 
     showProgress(true); 
     mAuthTask = new UserLoginTask(email, password); 
     mAuthTask.execute(); 

    } 
} 

private boolean isEmailValid(String email) { 
    //TODO: Replace this with your own logic 
    return email.contains("@"); 
} 

private boolean isPasswordValid(String password) { 
    //TODO: Replace this with your own logic 
    return password.length() > 4; 
} 

/** 
* Shows the progress UI and hides the login form. 
*/ 
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) 
public void showProgress(final boolean show) { 
    // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow 
    // for very easy animations. If available, use these APIs to fade-in 
    // the progress spinner. 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { 
     int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); 

     mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); 
     mLoginFormView.animate().setDuration(shortAnimTime).alpha(
       show ? 0 : 1).setListener(new AnimatorListenerAdapter() { 
      @Override 
      public void onAnimationEnd(Animator animation) { 
       mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); 
      } 
     }); 

     mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); 
     mProgressView.animate().setDuration(shortAnimTime).alpha(
       show ? 1 : 0).setListener(new AnimatorListenerAdapter() { 
      @Override 
      public void onAnimationEnd(Animator animation) { 
       mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); 
      } 
     }); 
    } else { 
     // The ViewPropertyAnimator APIs are not available, so simply show 
     // and hide the relevant UI components. 
     mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); 
     mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); 
    } 
} 

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
@Override 
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) { 
    return new CursorLoader(this, 
      // Retrieve data rows for the device user's 'profile' contact. 
      Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI, 
        ContactsContract.Contacts.Data.CONTENT_DIRECTORY), ProfileQuery.PROJECTION, 

      // Select only email addresses. 
      ContactsContract.Contacts.Data.MIMETYPE + 
        " = ?", new String[]{ContactsContract.CommonDataKinds.Email 
      .CONTENT_ITEM_TYPE}, 

      // Show primary email addresses first. Note that there won't be 
      // a primary email address if the user hasn't specified one. 
      ContactsContract.Contacts.Data.IS_PRIMARY + " DESC"); 
} 

@Override 
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { 
    List<String> emails = new ArrayList<String>(); 
    cursor.moveToFirst(); 
    while (!cursor.isAfterLast()) { 
     emails.add(cursor.getString(ProfileQuery.ADDRESS)); 
     cursor.moveToNext(); 
    } 

    addEmailsToAutoComplete(emails); 
} 

@Override 
public void onLoaderReset(Loader<Cursor> cursorLoader) { 

} 

private interface ProfileQuery { 
    String[] PROJECTION = { 
      ContactsContract.CommonDataKinds.Email.ADDRESS, 
      ContactsContract.CommonDataKinds.Email.IS_PRIMARY, 
    }; 

    int ADDRESS = 0; 
    int IS_PRIMARY = 1; 
} 

/** 
* Use an AsyncTask to fetch the user's email addresses on a background thread, and update 
* the email text field with results on the main UI thread. 
*/ 
class SetupEmailAutoCompleteTask extends AsyncTask<Void, Void, List<String>> { 

    @Override 
    protected List<String> doInBackground(Void... voids) { 
     ArrayList<String> emailAddressCollection = new ArrayList<String>(); 

     // Get all emails from the user's contacts and copy them to a list. 
     ContentResolver cr = getContentResolver(); 
     Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, 
       null, null, null); 
     while (emailCur.moveToNext()) { 
      String email = emailCur.getString(emailCur.getColumnIndex(ContactsContract 
        .CommonDataKinds.Email.DATA)); 
      emailAddressCollection.add(email); 
     } 
     emailCur.close(); 

     return emailAddressCollection; 
    } 

    @Override 
    protected void onPostExecute(List<String> emailAddressCollection) { 
     addEmailsToAutoComplete(emailAddressCollection); 
    } 
} 

private void addEmailsToAutoComplete(List<String> emailAddressCollection) { 
    //Create adapter to tell the AutoCompleteTextView what to show in its dropdown list. 
    ArrayAdapter<String> adapter = 
      new ArrayAdapter<String>(LoginActivity.this, 
        android.R.layout.simple_dropdown_item_1line, emailAddressCollection); 

    mEmailView.setAdapter(adapter); 
} 

/** 
* Represents an asynchronous login/registration task used to authenticate 
* the user. 
*/ 
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> { 

    private final String mEmail; 
    private final String mPassword; 

    UserLoginTask(String email, String password) { 
     mEmail = email; 
     mPassword = password; 
    } 

    @Override 
    protected Boolean doInBackground(Void... params) { 
     // TODO: attempt authentication against a network service. 

     /*try { 
      // Simulate network access. 
      Thread.sleep(2000); 
     } catch (InterruptedException e) { 
      return false; 
     } 

     for (String credential : DUMMY_CREDENTIALS) { 
      String[] pieces = credential.split(":"); 
      if (pieces[0].equals(mEmail)) { 
       // Account exists, return true if the password matches. 
       return pieces[1].equals(mPassword); 
      } 
     } 

     // TODO: register the new account here. 
     return true;*/ 
     ParseUser.logInInBackground(mEmail,mPassword, new LogInCallback() { 
      @Override 
      public void done(ParseUser parseUser, ParseException e) { 
       if (e == null) 
       { 
        Intent intent = new Intent(LoginActivity.this, MainActivity.class); 
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 
        startActivity(intent); 
       } else { 
        AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this); 

        builder.setMessage(e.getMessage()); 
        builder.setTitle(R.string.loginup_error_title); 
        builder.setPositiveButton(android.R.string.ok, null); 

        AlertDialog dialog = builder.create(); 
        dialog.show(); 
       } 
      } 
     }); 
     return true; 
    } 

    @Override 
    protected void onPostExecute(final Boolean success) { 
     mAuthTask = null; 
     showProgress(false); 

     if (success) { 
      finish(); 
     } else { 
      mPasswordView.setError(getString(R.string.error_incorrect_password)); 
      mPasswordView.requestFocus(); 
     } 
    } 

    @Override 
    protected void onCancelled() { 
     mAuthTask = null; 
     showProgress(false); 
    } 
    } 
} 

而這是我得到一段時間後的錯誤。我認爲這個錯誤是因爲應用程序關閉了,但從解析中獲取數據的後臺任務仍在進行中。我不確定。

com.redux.kumardivyarajat.attendance E/AndroidRuntime﹕ FATAL EXCEPTION: main 
Process: com.redux.kumardivyarajat.attendance, PID: 22430 
android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running? 
     at android.view.ViewRootImpl.setView(ViewRootImpl.java:559) 
     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259) 
     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) 
     at android.app.Dialog.show(Dialog.java:286) 
     at com.redux.kumardivyarajat.attendance.LoginActivity$UserLoginTask$1.done(LoginActivity.java:362) 
     at com.redux.kumardivyarajat.attendance.LoginActivity$UserLoginTask$1.done(LoginActivity.java:345) 
     at com.parse.Parse$6$1.run(Parse.java:945) 
     at android.os.Handler.handleCallback(Handler.java:733) 
     at android.os.Handler.dispatchMessage(Handler.java:95) 
     at android.os.Looper.loop(Looper.java:136) 
     at android.app.ActivityThread.main(ActivityThread.java:5047) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:515) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:806) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622) 
     at dalvik.system.NativeStart.main(Native Method) 

請建議我應該在UserLoginTask(asynctask)中做什麼chage使它工作。

編輯:添加mainactivity.java和activity_login2.xml。

activity_login2.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:gravity="center_horizontal" 
android:orientation="vertical" 
android:paddingBottom="@dimen/activity_vertical_margin" 
android:paddingLeft="@dimen/activity_horizontal_margin" 
android:paddingRight="@dimen/activity_horizontal_margin" 
android:paddingTop="@dimen/activity_vertical_margin" 
tools:context="com.redux.kumardivyarajat.attendance.LoginActivity" 
android:weightSum="1" 
android:id="@+id/activity_login2"> 

<!-- Login progress --> 
<ProgressBar android:id="@+id/login_progress" 
    style="?android:attr/progressBarStyleLarge" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_marginBottom="8dp" 
    android:visibility="gone" /> 

<ScrollView android:id="@+id/login_form" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <LinearLayout android:id="@+id/email_login_form" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" 
     android:weightSum="1" 
     android:touchscreenBlocksFocus="false"> 

     <AutoCompleteTextView 
      android:id="@+id/email" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:hint="@string/prompt_email" 
      android:inputType="textEmailAddress" 
      android:maxLines="1" 
      android:singleLine="true" 
      android:layout_weight="10.63"> 
      <requestFocus/> 
     </AutoCompleteTextView> 


     <EditText android:id="@+id/password" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:hint="@string/prompt_password" 
      android:imeActionId="@+id/login" 
      android:imeActionLabel="@string/action_sign_in_short" 
      android:imeOptions="actionUnspecified" 
      android:inputType="textPassword" 
      android:maxLines="1" 
      android:singleLine="true" 
      android:textSize="20dp"/> 

     <Button android:id="@+id/email_sign_in_button" 
      style="?android:textAppearanceSmall" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_marginTop="16dp" 
      android:text="@string/action_sign_in_short" 
      android:textStyle="bold" /> 

     <TextView 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:id ="@+id/SignupText" 
      android:text="@string/sign_up_from_login" 
      android:textColor="#ffff0500" 
      android:layout_marginTop="50dp" 
      android:layout_weight="0.18" /> 

     <Button 
      style="?android:textAppearanceSmall" 
      android:id="@+id/SignUpButtonInsideLogin" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_marginTop="16dp" 
      android:text="Sign Up" 
      android:textStyle="bold" 
      android:layout_gravity="center_horizontal" /> 

    </LinearLayout> 
    </ScrollView> 
</LinearLayout> 

現在mainactivity.java的上創建方法。

public class MainActivity extends ActionBarActivity { 
    public static final String TAG = MainActivity.class.getSimpleName(); 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    if (savedInstanceState == null) { 
     getSupportFragmentManager().beginTransaction() 
       .add(R.id.container, new PlaceholderFragment()) 
       .commit(); 
     setContentView(R.layout.activity_main); 

    } 

    ParseAnalytics.trackAppOpened(getIntent()); 
    ParseUser currentUser = ParseUser.getCurrentUser(); 

    if(currentUser == null) { 
     navigateToLogin(); 

    } else { 
     Log.i(TAG,currentUser.getUsername()); 
    } 



} 

private void navigateToLogin() { 
    Intent intent = new Intent(this, LoginActivity.class); 
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 
    startActivity(intent); 
} 

回答

1

根據您的情況,當您嘗試在完成當前活動後顯示特定視圖或對話框時,可能會出現BadToken錯誤。無論發生什麼,你的doinBackground都會返回true,但是當它被執行時,你可能已經完成了這個活動。所以我建議你在onpostExecute內進行。

試試這個,

更新你的異步任務如下,從doInBackground返回的狀態值。然後使用onPostExecute執行基於返回值的任何任務。

public class UserLoginTask extends AsyncTask<Void, Void, Boolean> { 

private final String mEmail; 
private final String mPassword; 
private boolean status = false; 

UserLoginTask(String email, String password) { 
    mEmail = email; 
    mPassword = password; 
} 

@Override 
protected Boolean doInBackground(Void... params) { 
    // TODO: attempt authentication against a network service. 

    ParseUser.logInInBackground(mEmail,mPassword, new LogInCallback() { 
     @Override 
     public void done(ParseUser parseUser, ParseException e) { 
      if (e == null) 
      { 
       status = true; 
      } else { 
       status = false; 
      } 
     } 
    }); 
    return status; 
} 

@Override 
protected void onPostExecute(final Boolean success) { 

    if (success) { 
     // success code 
    } else { 
     // failure code 
    } 
} 
相關問題