package au.id.teda.broadband.usage.authenticator;
import android.accounts.Account;
import android.accounts.AccountAuthenticatorActivity;
import android.accounts.AccountManager;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.method.PasswordTransformationMethod;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import au.id.teda.broadband.usage.R;
import au.id.teda.broadband.usage.activity.InitialiseActivity;
import au.id.teda.broadband.usage.helper.ConnectivityHelper;
import au.id.teda.broadband.usage.syncadapter.DummyContentProvider;
import au.id.teda.broadband.usage.activity.SettingsActivity;
import au.id.teda.broadband.usage.util.FontUtils;
import au.id.teda.broadband.usage.util.NetworkUtilities;
//TODO: Rewrite activity for better error display and add type of account (peak_offpeak or anytime)
public class AuthenticatorActivity extends AccountAuthenticatorActivity {
/** Debug tag **/
//private static final String DEBUG_TAG = BaseActivity.DEBUG_TAG;
/** The Intent flag to confirm credentials. */
public static final String PARAM_CONFIRM_CREDENTIALS = "confirmCredentials";
/** The Intent extra to store password. */
public static final String PARAM_PASSWORD = "password";
/** The Intent extra to store username. */
public static final String PARAM_USERNAME = "username";
/** Keep track of the login task so can cancel it if requested */
private UserLoginTask mAuthTask = null;
/** Keep track of the progress dialog so we can dismiss it */
private Dialog mDialog = null;
private boolean mDialogShowing;
/** Account manager object **/
private static AccountManager mAccountManager;
private static String accountType;
private static AccountAuthenticator mAccountAuthenticator;
/** Download manager **/
static NetworkUtilities mNetworkUtilities;
private static TextView mMessage;
private static String mPassword;
private EditText mPasswordEdit;
private static String mUsername;
private EditText mUsernameEdit;
private CheckBox mShowPasswordCbox;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_authenticator);
/** Set up account instance **/
mAccountAuthenticator = new AccountAuthenticator(this);
mNetworkUtilities = new NetworkUtilities(this);
mAccountManager = AccountManager.get(this);
accountType = AccountAuthenticator.ACCOUNT_TYPE;
/** Set up activity view **/
mMessage = (TextView) findViewById(R.id.message_tv);
mUsernameEdit = (EditText) findViewById(R.id.username_et);
mPasswordEdit = (EditText) findViewById(R.id.password_et);
mShowPasswordCbox = (CheckBox) findViewById(R.id.show_password_cbox);
setUsernamePasswordEditText();
/** Check if there has been a screen orientation change **/
Object retained = getLastNonConfigurationInstance();
if ( retained instanceof UserLoginTask ) {
// Associate orientation new activity with async task
mAuthTask = (UserLoginTask) retained;
mAuthTask.setActivity(this);
// Show dialog again
showMyDialog();
}
// Set font to Roboto on SDK < 11
if (Build.VERSION.SDK_INT < 11) {
ViewGroup godfatherView = (ViewGroup) this.getWindow().getDecorView();
FontUtils.setRobotoFont(this, godfatherView);
}
}
/** After a screen orientation change, this method is invoked. **/
@Override
public Object onRetainNonConfigurationInstance() {
// Using state save task so destroy old task
if (mAuthTask != null){
mAuthTask.detach();
}
return(mAuthTask);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
protected void onPause(){
super.onPause();
// Dismiss dialog so we don't get window leaks
dismissMyDialog();
}
/** Activity method called once asyncTask complete **/
private void onTaskCompleted(boolean userPassCheck) {
// Tidy up task
mAuthTask = null;
dismissMyDialog();
if (userPassCheck){
addAccount();
} else {
showAuthenticatinFailure();
}
}
private void showMyDialog(){
// Set up dialog
mDialog = new Dialog(this);
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setContentView(R.layout.dialog_indeterminate_progress_spinner);
mDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
mDialog.show();
// Set display boolean to true
mDialogShowing = true;
}
private void dismissMyDialog(){
if (mDialogShowing) {
mDialog.dismiss();
mDialogShowing = false;
}
}
/**
* Set username and password into edit text if set
*/
private void setUsernamePasswordEditText() {
// Get username and password for account
if (mAccountAuthenticator.isAccountAuthenticated()){
mUsernameEdit.setText(mAccountAuthenticator.getUsername());
mPasswordEdit.setText(mAccountAuthenticator.getPassword());
mMessage.setText(R.string.authenticator_activity_account_set);
}
}
/**
* On click event for button
* @param view
*/
public void onClickAddAccount(View view) {
// Get username and password from edit_text's
mUsername = mUsernameEdit.getText().toString();
mPassword = mPasswordEdit.getText().toString();
ConnectivityHelper mNetwork = new ConnectivityHelper(this);
// Check if we like what was put into the username and password et's
if (TextUtils.isEmpty(mUsername) || TextUtils.isEmpty(mPassword)) {
mMessage.setText(getMessage());
} else {
// Kick off a background task to perform the user login attempt.
if (mNetwork.isConnected()){
// Start async task
mAuthTask = new UserLoginTask(this);
mAuthTask.execute();
} else {
// Set message text to connection error
mMessage.setText(R.string.authenticator_activity_no_connectivity);
toaster(getString(R.string.authenticator_activity_no_connectivity));
}
}
}
/**
* Returns the message to be displayed at the top of the login dialog box.
*/
private CharSequence getMessage() {
if (TextUtils.isEmpty(mUsername)) {
// If no username, then we ask the user to log in using an
// appropriate service.
return getText(R.string.authenticator_activity_no_username);
}
if (TextUtils.isEmpty(mPassword)) {
// We have an account but no password
return getText(R.string.authenticator_activity_no_password);
}
return null;
}
/**
* Add account to manager
*/
private void addAccount(){
// This is the magic that adds the account to the Android Account Manager
final Account account = new Account(mUsername, accountType);
mAccountManager.addAccountExplicitly(account, mPassword, null);
// Account is Syncable
ContentResolver.setIsSyncable(account, DummyContentProvider.PROVIDER, 1);
// Sync account automatically
ContentResolver.setSyncAutomatically(account, DummyContentProvider.PROVIDER, true);
// Sync every day as default
ContentResolver.addPeriodicSync(account, DummyContentProvider.PROVIDER, new Bundle(), SettingsActivity.TWENTY_FOUR_HOURS);
final Intent intent = new Intent();
intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mUsername);
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, accountType);
setAccountAuthenticatorResult(intent.getExtras());
setResult(RESULT_OK, intent);
//finish();
Intent i = new Intent(this, InitialiseActivity.class);
startActivity(i);
}
/**
* On click method for showing or hiding password
* @param view
*/
public void onClickShowPassword(View view) {
if (mShowPasswordCbox.isChecked()) {
// Show password if check box checked
mPasswordEdit.setTransformationMethod(null);
// Move to cursor to end of edit text
mPasswordEdit.setSelection(mPasswordEdit.getText().length());
} else {
// Else hide password
mPasswordEdit.setTransformationMethod(new PasswordTransformationMethod());
// Move to cursor to end of edit text
mPasswordEdit.setSelection(mPasswordEdit.getText().length());
}
}
/**
* Show a toast method
* @param message
*/
private void toaster(String message){
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
private void showAuthenticatinFailure() {
mMessage.setText(R.string.authenticator_activity_failure);
toaster(getString(R.string.authenticator_activity_failure));
}
/**
* This class represents an asynchronous task used to authenticate a user against XML parser
* @author iteda
*
*/
static class UserLoginTask extends AsyncTask<Void, Boolean, Boolean> {
private AuthenticatorActivity activity;
private boolean completed;
UserLoginTask(AuthenticatorActivity activity){
this.activity = activity;
}
/** Complete before we execute task **/
protected void onPreExecute(){
// Show progress in UI thread dialog before executing task
activity.showMyDialog();
}
/** Task to be complete **/
@Override
protected Boolean doInBackground(Void... params) {
// We do the actual work of authenticating the user in DownloadVolumeUsage class.
try {
return mNetworkUtilities.authenticate(mUsername, mPassword);
} catch (Exception ex) {
return false;
}
}
@Override
protected void onPostExecute(Boolean userPassCheck) {
completed = true;
notifyActivityTaskCompleted(userPassCheck);
}
@Override
protected void onCancelled() {
// Nothing to see here
}
void detach(){
activity = null;
}
void setActivity(AuthenticatorActivity activity) {
this.activity = activity;
if (completed){
notifyActivityTaskCompleted(false);
}
}
/**
* Helper method to notify the activity that this task was completed.
* @param userPassCheck
*/
private void notifyActivityTaskCompleted(Boolean userPassCheck) {
if ( null != activity ) {
activity.onTaskCompleted(userPassCheck);
}
}
}
}