com.clearcenter.mobile_demo.mdAuthenticatorActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.clearcenter.mobile_demo.mdAuthenticatorActivity.java

Source

// ClearOS Mobile Demo: Example Android Application
// Copyright (C) 2012 ClearFoundation <http://www.clearfoundation.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package com.clearcenter.mobile_demo;

import com.clearcenter.mobile_demo.mdConstants;
import com.clearcenter.mobile_demo.mdRest;
import com.clearcenter.mobile_demo.mdSSLUtil;
import com.clearcenter.mobile_demo.providers.mdContentProvider;
import com.clearcenter.mobile_demo.R;

import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
import android.app.Dialog;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import java.security.GeneralSecurityException;

import org.json.JSONException;

public class mdAuthenticatorActivity extends AccountAuthenticatorActivity {
    // The tag used to log to adb console.
    private static final String TAG = "mdAuthenticatorActivity";

    // The Intent flag to confirm credentials.
    public static final String PARAM_CONFIRM_CREDENTIALS = "confirmCredentials";

    // The Intent extra to store nickname.
    public static final String PARAM_NICKNAME = "nickname";

    // The Intent extra to store hostname.
    public static final String PARAM_HOSTNAME = "hostname";

    // The Intent extra to store username.
    public static final String PARAM_USERNAME = "username";

    // The Intent extra to store password.
    public static final String PARAM_PASSWORD = "password";

    // The Intent extra to store authtoken type.
    public static final String PARAM_AUTHTOKEN_TYPE = "authtokenType";

    // The account manager.
    private AccountManager account_manager;

    // Keep track of the login task so can cancel it if requested
    private UserLoginTask auth_task = null;

    // Keep track of the progress dialog so we can dismiss it
    private ProgressDialog progress_dialog = null;

    // If set we are just checking that the user knows their credentials; this
    // doesn't cause the user's password or authToken to be changed on the
    // device.
    private Boolean confirm_credentials = false;

    // Was the original caller asking for an entirely new account?
    protected boolean request_new_account = false;

    // For posting authentication attempts back to UI thread.
    private final Handler handler = new Handler();

    private ScrollView scroll_view;

    private TextView message;

    private String nickname;
    private TextView nickname_label;
    private EditText nickname_edit;

    private String hostname;
    private TextView hostname_label;
    private EditText hostname_edit;

    private String username;
    private TextView username_label;
    private EditText username_edit;

    private String password;
    private EditText password_edit;

    public void onCreate(Bundle bundle) {
        Log.i(TAG, "onCreate(" + bundle + ")");
        super.onCreate(bundle);
        setContentView(R.layout.login_activity);

        account_manager = AccountManager.get(this);

        Log.i(TAG, "loading data from Intent");
        final Intent intent = getIntent();

        nickname = intent.getStringExtra(PARAM_NICKNAME);
        username = intent.getStringExtra(PARAM_USERNAME);
        hostname = intent.getStringExtra(PARAM_HOSTNAME);

        request_new_account = nickname == null;
        confirm_credentials = intent.getBooleanExtra(PARAM_CONFIRM_CREDENTIALS, false);
        Log.i(TAG, "new account? " + request_new_account + ", confirm credentials? " + confirm_credentials);

        scroll_view = (ScrollView) findViewById(R.id.scroll_view);

        message = (TextView) findViewById(R.id.message);

        nickname_label = (TextView) findViewById(R.id.nickname_label);
        nickname_edit = (EditText) findViewById(R.id.nickname_edit);
        nickname_label.setVisibility(request_new_account ? View.VISIBLE : View.GONE);
        nickname_edit.setVisibility(request_new_account ? View.VISIBLE : View.GONE);
        if (nickname != null)
            nickname_edit.setText(nickname);

        hostname_label = (TextView) findViewById(R.id.hostname_label);
        hostname_edit = (EditText) findViewById(R.id.hostname_edit);
        hostname_label.setVisibility(request_new_account ? View.VISIBLE : View.GONE);
        hostname_edit.setVisibility(request_new_account ? View.VISIBLE : View.GONE);
        if (hostname != null)
            hostname_edit.setText(hostname);

        username_label = (TextView) findViewById(R.id.username_label);
        username_edit = (EditText) findViewById(R.id.username_edit);
        username_label.setVisibility(request_new_account ? View.VISIBLE : View.GONE);
        username_edit.setVisibility(request_new_account ? View.VISIBLE : View.GONE);
        if (username != null)
            username_edit.setText(username);

        password_edit = (EditText) findViewById(R.id.password_edit);

        if (confirm_credentials) {
            String ns = Context.NOTIFICATION_SERVICE;
            NotificationManager notification_manager;
            notification_manager = (NotificationManager) getApplicationContext().getSystemService(ns);
            notification_manager.cancelAll();
            Log.i(TAG, "TODO: Cancel all notifications?");
        }

        if (!TextUtils.isEmpty(nickname))
            nickname_edit.setText(nickname);

        if (request_new_account)
            message.setText(getText(R.string.login_activity_new_account));
        else if (confirm_credentials) {
            message.setText(getText(R.string.login_activity_confirm_credentials));
        }

        try {
            mdSSLUtil.DisableSecurity();
        } catch (GeneralSecurityException e) {
            Toast.makeText(getApplicationContext(), e.getMessage(), 4).show();
        }
    }

    //protected Dialog onCreateDialog(int id, Bundle args)
    protected Dialog onCreateDialog(int id) {
        final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage(getText(R.string.login_activity_authenticating));
        dialog.setIndeterminate(true);
        dialog.setCancelable(true);
        dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            public void onCancel(DialogInterface dialog) {
                Log.i(TAG, "user cancelling authentication");
                if (auth_task != null) {
                    auth_task.cancel(true);
                }
            }
        });
        // We save off the progress dialog in a field so that we can dismiss
        // it later. We can't just call dismissDialog(0) because the system
        // can lose track of our dialog if there's an orientation change.
        progress_dialog = dialog;
        return dialog;
    }

    // Handles onClick event on the Submit button. Sends username/password to
    // the server for authentication. The button is configured to call
    // handleLogin() in the layout XML.
    public void handleLogin(View view) {
        if (request_new_account)
            Log.i(TAG, "handleLogin: new account");
        else
            Log.i(TAG, "handleLogin: existing account");

        nickname = nickname_edit.getText().toString();
        hostname = hostname_edit.getText().toString();
        username = username_edit.getText().toString();
        password = password_edit.getText().toString();

        final Account accounts[] = account_manager.getAccountsByType(mdConstants.ACCOUNT_TYPE);
        for (Account account : accounts) {
            if (request_new_account && TextUtils.equals(account.name, nickname)) {
                message.setText(getText(R.string.login_activity_duplicate_account));
                scroll_view.smoothScrollTo(0, 0);
                nickname_edit.requestFocus();
                nickname_edit.setSelected(true);
                return;
            }
            Log.i(TAG, account.name + " != " + nickname);
        }

        if (request_new_account) {
            if (TextUtils.isEmpty(nickname)) {
                message.setText(getText(R.string.login_activity_null_nickname));
                scroll_view.smoothScrollTo(0, 0);
                nickname_edit.requestFocus();
                nickname_edit.setSelected(true);
                return;
            }
            if (TextUtils.isEmpty(hostname)) {
                message.setText(getText(R.string.login_activity_null_hostname));
                scroll_view.smoothScrollTo(0, 0);
                hostname_edit.requestFocus();
                hostname_edit.setSelected(true);
                return;
            }
            if (TextUtils.isEmpty(username)) {
                message.setText(getText(R.string.login_activity_null_username));
                scroll_view.smoothScrollTo(0, 0);
                username_edit.requestFocus();
                username_edit.setSelected(true);
                return;
            }
        }
        if (TextUtils.isEmpty(password)) {
            message.setText(getText(R.string.login_activity_null_password));
            scroll_view.smoothScrollTo(0, 0);
            password_edit.requestFocus();
            password_edit.setSelected(true);
            return;
        }
        // Show a progress dialog, and kick off a background task to perform
        // the user login attempt.
        showProgress();
        auth_task = new UserLoginTask();
        auth_task.execute();
    }

    // Called when response is received from the server for confirm credentials
    // request. See onAuthenticationResult(). Sets the
    // AccountAuthenticatorResult which is sent back to the caller.
    private void finishConfirmCredentials(boolean result, String authToken) {
        Log.i(TAG, "finishConfirmCredentials()");
        final Account account = new Account(nickname, mdConstants.ACCOUNT_TYPE);

        if (result)
            account_manager.setPassword(account, authToken);

        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. We store
    // the authToken that's returned from the server as the 'password' for this
    // account - so we're never storing the user's actual password locally.
    private void finishLogin(String authToken) {
        Log.i(TAG, "finishLogin()");

        final Account account = new Account(nickname, mdConstants.ACCOUNT_TYPE);
        if (request_new_account) {
            account_manager.addAccountExplicitly(account, authToken, null);
            account_manager.setUserData(account, "hostname", hostname);
            account_manager.setUserData(account, "username", username);

            // Set system info sync for this account.
            final Bundle extras = new Bundle();
            ContentResolver.setSyncAutomatically(account, mdContentProvider.AUTHORITY, true);
            if (android.os.Build.VERSION.SDK_INT >= 8) {
                ContentResolver.addPeriodicSync(account, mdContentProvider.AUTHORITY, extras, 10);
            }
        } else
            account_manager.setPassword(account, authToken);

        final Intent intent = new Intent();
        intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, nickname);
        intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, mdConstants.ACCOUNT_TYPE);
        setAccountAuthenticatorResult(intent.getExtras());
        setResult(RESULT_OK, intent);

        ContentResolver.requestSync(account, mdContentProvider.AUTHORITY, new Bundle());

        finish();
    }

    // Called when the authentication process completes (see attemptLogin()).
    public void onAuthenticationResult(String authToken) {
        boolean success = ((authToken != null) && (authToken.length() > 0));
        Log.i(TAG, "onAuthenticationResult(" + success + ")");

        // Our task is complete, so clear it out
        auth_task = null;

        // Hide the progress dialog
        hideProgress();

        if (success) {
            if (!confirm_credentials)
                finishLogin(authToken);
            else
                finishConfirmCredentials(success, authToken);
        } else {
            Log.e(TAG, "onAuthenticationResult: failed to authenticate");
            if (request_new_account) {
                // "Please enter a valid username/password.
                message.setText(getText(R.string.login_activity_bad_account));
                scroll_view.smoothScrollTo(0, 0);
                username_edit.requestFocus();
                username_edit.setSelected(true);
            } else {
                // "Please enter a valid password." (Used when the
                // account is already in the database but the password
                // doesn't work.)
                message.setText(getText(R.string.login_activity_bad_password));
                scroll_view.smoothScrollTo(0, 0);
                password_edit.requestFocus();
                password_edit.setSelected(true);
            }
        }
    }

    public void onAuthenticationCancel() {
        Log.i(TAG, "onAuthenticationCancel()");

        // Our task is complete, so clear it out
        auth_task = null;

        // Hide the progress dialog
        hideProgress();
    }

    // Shows the progress UI for a lengthy operation.
    private void showProgress() {
        showDialog(0);
    }

    // Hides the progress UI for a lengthy operation.
    private void hideProgress() {
        if (progress_dialog != null) {
            progress_dialog.dismiss();
            progress_dialog = null;
        }
    }

    // Represents an asynchronous task used to authenticate a user against the
    // ClearOS Server
    public class UserLoginTask extends AsyncTask<Void, Void, String> {
        protected String doInBackground(Void... params) {
            // We do the actual work of authenticating the user
            // in the mdRest class.
            try {
                return mdRest.Login(hostname, username, password, null);
            } catch (Exception e) {
                Log.e(TAG, "UserLoginTask.doInBackground: failed to authenticate", e);
                return null;
            }
        }

        protected void onPostExecute(final String authToken) {
            // On a successful authentication, call back into the Activity to
            // communicate the authToken (or null for an error).
            onAuthenticationResult(authToken);
        }

        protected void onCancelled() {
            // If the action was canceled (by the user clicking the cancel
            // button in the progress dialog), then call back into the
            // activity to let it know.
            onAuthenticationCancel();
        }
    }
}

// vi: expandtab shiftwidth=4 softtabstop=4 tabstop=4