Project: Android-SyncAdapter-JSON-Server-Example
/*
 * Copyright (C) 2010 The Android Open Source Project 
 *  
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy of 
 * the License at 
 *  
 * http://www.apache.org/licenses/LICENSE-2.0 
 *  
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
 * License for the specific language governing permissions and limitations under 
 * the License. 
 */
 
package com.example.android.samplesync.authenticator; 
 
import android.accounts.Account; 
import android.accounts.AccountAuthenticatorActivity; 
import android.accounts.AccountManager; 
import android.app.Dialog; 
import android.app.ProgressDialog; 
import android.content.ContentResolver; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.Handler; 
import android.provider.ContactsContract; 
import android.text.TextUtils; 
import android.util.Log; 
import android.view.View; 
import android.view.Window; 
import android.widget.EditText; 
import android.widget.TextView; 
 
import com.example.android.samplesync.Constants; 
import com.example.android.samplesync.R; 
import com.example.android.samplesync.client.NetworkUtilities; 
 
/**
 * Activity which displays login screen to the user. 
 */
 
public class AuthenticatorActivity extends AccountAuthenticatorActivity { 
    public static final String PARAM_CONFIRMCREDENTIALS = "confirmCredentials"
    public static final String PARAM_PASSWORD = "password"
    public static final String PARAM_USERNAME = "username"
    public static final String PARAM_AUTHTOKEN_TYPE = "authtokenType"
 
    private static final String TAG = "AuthenticatorActivity"
 
    private AccountManager mAccountManager; 
    private Thread mAuthThread; 
    private String mAuthtoken; 
    private String mAuthtokenType; 
 
    /**
     * If set we are just checking that the user knows their credentials; this 
     * doesn't cause the user's password to be changed on the device. 
     */
 
    private Boolean mConfirmCredentials = false
 
    /** for posting authentication attempts back to UI thread */ 
    private final Handler mHandler = new Handler(); 
    private TextView mMessage; 
    private String mPassword; 
    private EditText mPasswordEdit; 
 
    /** Was the original caller asking for an entirely new account? */ 
    protected boolean mRequestNewAccount = false
 
    private String mUsername; 
    private EditText mUsernameEdit; 
 
    /**
     * {@inheritDoc} 
     */
 
    @Override 
    public void onCreate(Bundle icicle) { 
        Log.i(TAG, "onCreate(" + icicle + ")"); 
        super.onCreate(icicle); 
        mAccountManager = AccountManager.get(this); 
        Log.i(TAG, "loading data from Intent"); 
        final Intent intent = getIntent(); 
        mUsername = intent.getStringExtra(PARAM_USERNAME); 
        mAuthtokenType = intent.getStringExtra(PARAM_AUTHTOKEN_TYPE); 
        mRequestNewAccount = mUsername == null
        mConfirmCredentials = 
            intent.getBooleanExtra(PARAM_CONFIRMCREDENTIALS, false); 
 
        Log.i(TAG, "    request new: " + mRequestNewAccount); 
        requestWindowFeature(Window.FEATURE_LEFT_ICON); 
        setContentView(R.layout.login_activity); 
        getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, 
            android.R.drawable.ic_dialog_alert); 
 
        mMessage = (TextView) findViewById(R.id.message); 
        mUsernameEdit = (EditText) findViewById(R.id.username_edit); 
        mPasswordEdit = (EditText) findViewById(R.id.password_edit); 
 
        mUsernameEdit.setText(mUsername); 
        mMessage.setText(getMessage()); 
    } 
 
    /*
     * {@inheritDoc} 
     */
 
    @Override 
    protected Dialog onCreateDialog(int id) { 
        final ProgressDialog dialog = new ProgressDialog(this); 
        dialog.setMessage(getText(R.string.ui_activity_authenticating)); 
        dialog.setIndeterminate(true); 
        dialog.setCancelable(true); 
        dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { 
            public void onCancel(DialogInterface dialog) { 
                Log.i(TAG, "dialog cancel has been invoked"); 
                if (mAuthThread != null) { 
                    mAuthThread.interrupt(); 
                    finish(); 
                } 
            } 
        }); 
        return dialog; 
    } 
 
    /**
     * Handles onClick event on the Submit button. Sends username/password to 
     * the server for authentication. 
     *  
     * @param view The Submit button for which this method is invoked 
     */
 
    public void handleLogin(View view) { 
        if (mRequestNewAccount) { 
            mUsername = mUsernameEdit.getText().toString(); 
        } 
        mPassword = mPasswordEdit.getText().toString(); 
        if (TextUtils.isEmpty(mUsername) || TextUtils.isEmpty(mPassword)) { 
            mMessage.setText(getMessage()); 
        } else { 
            showProgress(); 
            // Start authenticating... 
            mAuthThread = 
                NetworkUtilities.attemptAuth(mUsername, mPassword, mHandler, 
                    AuthenticatorActivity.this); 
        } 
    } 
 
    /**
     * Called when response is received from the server for confirm credentials 
     * request. See onAuthenticationResult(). Sets the 
     * AccountAuthenticatorResult which is sent back to the caller. 
     *  
     * @param the confirmCredentials result. 
     */
 
    protected void finishConfirmCredentials(boolean result) { 
        Log.i(TAG, "finishConfirmCredentials()"); 
        final Account account = new Account(mUsername, Constants.ACCOUNT_TYPE); 
        mAccountManager.setPassword(account, mPassword); 
        final Intent intent = new Intent(); 
        intent.putExtra(AccountManager.KEY_BOOLEAN_RESULT, result); 
        setAccountAuthenticatorResult(intent.getExtras()); 
        setResult(RESULT_OK, intent); 
        finish(); 
    } 
 
    /**
     *  
     * Called when response is received from the server for authentication 
     * request. See onAuthenticationResult(). Sets the 
     * AccountAuthenticatorResult which is sent back to the caller. Also sets 
     * the authToken in AccountManager for this account. 
     *  
     * @param the confirmCredentials result. 
     */
 
 
    protected void finishLogin() { 
        Log.i(TAG, "finishLogin()"); 
        final Account account = new Account(mUsername, Constants.ACCOUNT_TYPE); 
 
        if (mRequestNewAccount) { 
            mAccountManager.addAccountExplicitly(account, mPassword, null); 
            // Set contacts sync for this account. 
            ContentResolver.setSyncAutomatically(account, 
                ContactsContract.AUTHORITY, true); 
        } else { 
            mAccountManager.setPassword(account, mPassword); 
        } 
        final Intent intent = new Intent(); 
        mAuthtoken = mPassword; 
        intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mUsername); 
        intent 
            .putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE); 
        if (mAuthtokenType != null 
            && mAuthtokenType.equals(Constants.AUTHTOKEN_TYPE)) { 
            intent.putExtra(AccountManager.KEY_AUTHTOKEN, mAuthtoken); 
        } 
        setAccountAuthenticatorResult(intent.getExtras()); 
        setResult(RESULT_OK, intent); 
        finish(); 
    } 
 
    /**
     * Hides the progress UI for a lengthy operation. 
     */
 
    protected void hideProgress() { 
        dismissDialog(0); 
    } 
 
    /**
     * Called when the authentication process completes (see attemptLogin()). 
     */
 
    public void onAuthenticationResult(boolean result) { 
        Log.i(TAG, "onAuthenticationResult(" + result + ")"); 
        // Hide the progress dialog 
        hideProgress(); 
        if (result) { 
            if (!mConfirmCredentials) { 
                finishLogin(); 
            } else { 
                finishConfirmCredentials(true); 
            } 
        } else { 
            Log.e(TAG, "onAuthenticationResult: failed to authenticate"); 
            if (mRequestNewAccount) { 
                // "Please enter a valid username/password. 
                mMessage 
                    .setText(getText(R.string.login_activity_loginfail_text_both)); 
            } else { 
                // "Please enter a valid password." (Used when the 
                // account is already in the database but the password 
                // doesn't work.) 
                mMessage 
                    .setText(getText(R.string.login_activity_loginfail_text_pwonly)); 
            } 
        } 
    } 
 
    /**
     * Returns the message to be displayed at the top of the login dialog box. 
     */
 
    private CharSequence getMessage() { 
        getString(R.string.label); 
        if (TextUtils.isEmpty(mUsername)) { 
            // If no username, then we ask the user to log in using an 
            // appropriate service. 
            final CharSequence msg = 
                getText(R.string.login_activity_newaccount_text); 
            return msg; 
        } 
        if (TextUtils.isEmpty(mPassword)) { 
            // We have an account but no password 
            return getText(R.string.login_activity_loginfail_text_pwmissing); 
        } 
        return null
    } 
 
    /**
     * Shows the progress UI for a lengthy operation. 
     */
 
    protected void showProgress() { 
        showDialog(0); 
    } 
}