de.uni_koblenz_landau.apow.LoginActivity.java Source code

Java tutorial

Introduction

Here is the source code for de.uni_koblenz_landau.apow.LoginActivity.java

Source

/**
 * Apow - a mobile EHR Management System for low-resource environments
 * in developing countries, exemplified by rural Ghana
 * Copyright (C) 2014 Martin Landua
 *
 * 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 de.uni_koblenz_landau.apow;

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

import de.uni_koblenz_landau.apow.dialogs.SignedOffDialog;
import de.uni_koblenz_landau.apow.helper.Constants;
import de.uni_koblenz_landau.apow.helper.CustomActivity;
import de.uni_koblenz_landau.apow.helper.Helper;
import de.uni_koblenz_landau.apow.helper.ListViewItem;
import de.uni_koblenz_landau.apow.tasks.LocationWebInterface;
import de.uni_koblenz_landau.apow.tasks.LocationWebTask;
import de.uni_koblenz_landau.apow.tasks.LoginInterface;
import de.uni_koblenz_landau.apow.tasks.LoginTask;
import de.uni_koblenz_landau.apow.tasks.NFCTagReaderInterface;
import de.uni_koblenz_landau.apow.tasks.NFCTagReaderTask;
import de.uni_koblenz_landau.apow.tasks.SetupInterface;
import de.uni_koblenz_landau.apow.tasks.SetupTask;
import de.uni_koblenz_landau.apow.tasks.TaskActivity;
import de.uni_koblenz_landau.apow.tasks.TaskActivityReference;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Activity for login
 *
 * @author Martin Landua
 *
 * Sources:
 * http://code.tutsplus.com/tutorials/reading-nfc-tags-with-android--mobile-17278
 */
public class LoginActivity extends CustomActivity
        implements TaskActivity, LoginInterface, SetupInterface, LocationWebInterface, NFCTagReaderInterface {

    // Constants
    private static final String ARG_AUTO_SIGN_OFF_DISMISSED = "auto_sign_off_dismissed";
    private static final String ARG_NFC = "nfc";
    private static final String ARG_NFC_STATE = "nfc_state";
    private static final String ARG_FIRST_RUN = "first_run";
    private static final String ARG_LOCATIONS = "locations";
    private static final String ARG_LOCATION_SELECTION = "location_selection";
    private static final String ARG_PROGRESS = "progress";
    public static final String ARG_AUTO_LOGOUT = "auto_logout";
    private static final String SIGNED_OFF_DIALOG_ID = "signed_off_dialog";
    private static final String MIME_TEXT_PLAIN = "text/plain";
    public static final int STATUS_DATABASE = 1;
    public static final int STATUS_DATABASE_ERROR = 2;
    public static final int STATUS_SYNC_FETCH_FACTS = 3;
    public static final int STATUS_SYNC_FETCH_USERDATA = 4;
    public static final int STATUS_CONNECTION_ERROR = 5;
    public static final int STATUS_OK = 6;
    public static final int STATUS_CHECK_LOGIN = 7;
    public static final int STATUS_LOGIN_WRONG = 8;

    // Tasks
    private LoginTask mLoginTask = null;
    private SetupTask mSetupTask = null;
    private NFCTagReaderTask mNFCTagReaderTask = null;
    private LocationWebTask mLocationWebTask = null;

    // UI Variables
    private Boolean mAutoSignOffDismissed;
    private String mNFCTag;
    private String mLoginPassword;
    private String mDatabasePassword;
    private String mDatabaseConfirm;
    private String mServerUsername;
    private String mServerPassword;
    private int mLocationID;
    private Boolean mFirstRun;
    private int mNFCTextDrawable;
    private NfcAdapter mNfcAdapter;
    private Boolean mProgress;
    private List<ListViewItem> mLocations;

    // UI references.
    private Toolbar mToolbar;
    private View mLoginFormView;
    private EditText mLoginPasswordView;
    private TextView mLoginNFCText;
    private View mSetupFormView;
    private TextView mSetupNFCText;
    private EditText mSetupDatabasePasswordView;
    private EditText mSetupDatabaseConfirmView;
    private EditText mSetupServerUsernameView;
    private EditText mSetupServerPasswordView;
    private Spinner mSetupLocationView;
    private View mStatusView;
    private TextView mStatusMessageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Re-attach Tasks.
        TaskActivityReference.getInstance().attach(LoginTask.TASK_ID, this);
        TaskActivityReference.getInstance().attach(SetupTask.TASK_ID, this);
        TaskActivityReference.getInstance().attach(NFCTagReaderTask.TASK_ID, this);
        TaskActivityReference.getInstance().attach(LocationWebTask.TASK_ID, this);

        // Create UI references.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = this.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.setStatusBarColor(this.getResources().getColor(R.color.color_primary_dark));
        }
        setContentView(R.layout.login_activity);
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        if (mToolbar != null) {
            setSupportActionBar(mToolbar);
        }

        mSetupLocationView = (Spinner) findViewById(R.id.login_setup_locations);
        mStatusView = findViewById(R.id.login_status);
        mStatusMessageView = (TextView) findViewById(R.id.login_status_message);
        mLoginFormView = findViewById(R.id.login_login);
        mLoginPasswordView = (EditText) findViewById(R.id.login_login_password);
        mLoginPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
                if (id == R.id.login || id == EditorInfo.IME_NULL) {
                    login(textView);
                    return true;
                }
                return false;
            }
        });
        mLoginNFCText = (TextView) findViewById(R.id.login_login_nfc);
        mSetupFormView = findViewById(R.id.login_setup);
        mSetupNFCText = (TextView) findViewById(R.id.login_setup_nfc);

        mSetupDatabasePasswordView = (EditText) findViewById(R.id.login_setup_database_password);
        mSetupDatabaseConfirmView = (EditText) findViewById(R.id.login_setup_database_password_confirm);
        mSetupServerUsernameView = (EditText) findViewById(R.id.login_login_server_user);
        mSetupServerPasswordView = (EditText) findViewById(R.id.login_login_server_password);

        //mFirstRun = true;
        mFirstRun = getSharedPreferences(Constants.PREFERENCE, MODE_PRIVATE).getBoolean(ARG_FIRST_RUN, true);
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

        // Restore UI from saved instance or load data.
        if (savedInstanceState != null) {
            mNFCTag = savedInstanceState.getString(ARG_NFC);
            mNFCTextDrawable = savedInstanceState.getInt(ARG_NFC_STATE);
            mAutoSignOffDismissed = savedInstanceState.getBoolean(ARG_AUTO_SIGN_OFF_DISMISSED);
            mProgress = savedInstanceState.getBoolean(ARG_PROGRESS);
            if (mFirstRun) {
                mLocations = savedInstanceState.getParcelableArrayList(ARG_LOCATIONS);
                if (mLocations != null) {
                    ArrayAdapter<ListViewItem> adapter = new ArrayAdapter<>(this,
                            android.R.layout.simple_spinner_item, mLocations);
                    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    mSetupLocationView.setAdapter(adapter);
                    mSetupLocationView.setSelection(savedInstanceState.getInt(ARG_LOCATION_SELECTION));
                }
            }
        } else {
            mProgress = false;
            mAutoSignOffDismissed = false;
            mNFCTag = "";
            mNFCTextDrawable = R.drawable.empty;
            if (mFirstRun) {
                loadLocations();
            }
        }
        mLoginNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, mNFCTextDrawable, 0);
        mSetupNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, mNFCTextDrawable, 0);

        if (mFirstRun) {
            mSetupFormView.setVisibility(View.VISIBLE);
            mLoginFormView.setVisibility(View.GONE);
            this.setTitle(R.string.login_setup_title);
        } else {
            mSetupFormView.setVisibility(View.GONE);
            mLoginFormView.setVisibility(View.VISIBLE);
            this.setTitle(R.string.login_login_title);
        }

        if (getIntent().getBooleanExtra(ARG_AUTO_LOGOUT, false) && !mAutoSignOffDismissed) {
            SignedOffDialog dialog = new SignedOffDialog();
            dialog.show(getSupportFragmentManager(), SIGNED_OFF_DIALOG_ID);
            mAutoSignOffDismissed = true;
        }
        showProgress(mProgress);
        setNFCState();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Detach tasks for preventing memory leaks.
        TaskActivityReference.getInstance().detach(LoginTask.TASK_ID);
        TaskActivityReference.getInstance().detach(SetupTask.TASK_ID);
        TaskActivityReference.getInstance().detach(NFCTagReaderTask.TASK_ID);
        TaskActivityReference.getInstance().detach(LocationWebTask.TASK_ID);
    }

    @Override
    protected void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putString(ARG_NFC, mNFCTag);
        savedInstanceState.putInt(ARG_NFC_STATE, mNFCTextDrawable);
        savedInstanceState.putBoolean(ARG_AUTO_SIGN_OFF_DISMISSED, mAutoSignOffDismissed);
        savedInstanceState.putBoolean(ARG_PROGRESS, mProgress);
        if (mFirstRun) {
            savedInstanceState.putParcelableArrayList(ARG_LOCATIONS, (ArrayList<ListViewItem>) mLocations);
            savedInstanceState.putInt(ARG_LOCATION_SELECTION, mSetupLocationView.getSelectedItemPosition());
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        setIntent(intent);
        String action = intent.getAction();

        // If tag is detected, start reading it.
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) && MIME_TEXT_PLAIN.equals(intent.getType())) {
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            readNFCTag(tag);
        }
    }

    /**
     * Start task to read a NFC tag
     * @param tag Tag
     */
    private void readNFCTag(Tag tag) {
        // Abort if task is already running.
        if (mNFCTagReaderTask != null) {
            return;
        }
        mLoginNFCText.setError(null);
        mSetupNFCText.setError(null);
        mNFCTextDrawable = R.drawable.empty;
        mLoginNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.empty, 0);
        mSetupNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.empty, 0);

        mNFCTagReaderTask = new NFCTagReaderTask();
        TaskActivityReference.getInstance().addTask(NFCTagReaderTask.TASK_ID, mNFCTagReaderTask, this);
        mNFCTagReaderTask.execute(tag);
    }

    /**
     * Called by NFCTagReaderTask, when reading is finished.
     */
    @Override
    public void onNFCTagReaderFinished(String result) {
        mNFCTagReaderTask = null;

        mNFCTag = result;
        mLoginNFCText.setError(null);
        mSetupNFCText.setError(null);
        mNFCTextDrawable = R.drawable.ic_action_accept_light;
        mLoginNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
        mSetupNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
        mLoginNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accept_light, 0);
        mSetupNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accept_light, 0);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Start scanning for NFC tags.
        setupForegroundDispatch(this, mNfcAdapter);
        setNFCState();
    }

    /**
     * Start scanning for NFC tags.
     * @param activity The Activity requesting to the foreground dispatch.
     * @param adapter The NfcAdapter used for the foreground dispatch.
     */
    private static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
        if (adapter != null) {
            // Add intents for NFC.
            final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
            intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

            final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0,
                    intent, 0);

            IntentFilter[] filters = new IntentFilter[1];
            String[][] techList = new String[][] {};

            filters[0] = new IntentFilter();
            filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
            filters[0].addCategory(Intent.CATEGORY_DEFAULT);
            try {
                filters[0].addDataType(MIME_TEXT_PLAIN);
            } catch (MalformedMimeTypeException e) {
                e.printStackTrace();
            }

            adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
        }
    }

    /**
     * Sets NFC status view.
     */
    private void setNFCState() {
        if (mNfcAdapter != null) {
            // If NFC is not enabled, show message.
            if (mNfcAdapter.isEnabled()) {
                if (mNFCTextDrawable == R.drawable.ic_action_error) {
                    mNFCTextDrawable = R.drawable.empty;
                    mLoginNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.empty, 0);
                    mSetupNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.empty, 0);
                }
                mLoginNFCText.setText(R.string.login_nfc);
                mSetupNFCText.setText(R.string.login_nfc);
            } else {
                mLoginNFCText.setText(R.string.login_nfc_disabled);
                mSetupNFCText.setText(R.string.login_nfc_disabled);
                mNFCTextDrawable = R.drawable.ic_action_error;
                mLoginNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_error, 0);
                mSetupNFCText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_error, 0);
            }
        }
    }

    @Override
    protected void onPause() {
        // Stop scanning for NFC tags.
        stopForegroundDispatch(this, mNfcAdapter);
        super.onPause();
    }

    /**
     * Stop scanning for NFC tags.
      * @param activity The Activity requesting to the foreground dispatch.
      * @param adapter The NfcAdapter used for the foreground dispatch.
     */
    private static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
        if (adapter != null) {
            adapter.disableForegroundDispatch(activity);
        }
    }

    /**
     * Called by onClick of NFC status view.
     * @param view View
     */
    public void openNFCSettings(View view) {
        if (mNfcAdapter != null && !mNfcAdapter.isEnabled()) {
            startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
        }
    }

    /**
     * Checks input and logs in.
     */
    public void login(View view) {
        // Abort if task is already running.
        if (mLoginTask != null || mFirstRun) {
            return;
        }

        // Reset errors.
        mLoginPasswordView.setError(null);

        // Store UI values.
        mLoginPassword = mLoginPasswordView.getText().toString();

        boolean cancel = false;
        View focusView = null;

        // Check input.
        if (TextUtils.isEmpty(mLoginPassword)) {
            mLoginPasswordView.setError(getString(R.string.error_field_required));
            focusView = mLoginPasswordView;
            cancel = true;
        } else if (mLoginPassword.length() < 4) {
            mLoginPasswordView.setError(getString(R.string.error_invalid_password));
            focusView = mLoginPasswordView;
            cancel = true;
        }

        if (TextUtils.isEmpty(mNFCTag)) {
            mLoginNFCText.setError(getString(R.string.error_no_tag));
            focusView = mLoginNFCText;
            cancel = true;
        }

        // When there are no error start login task.
        if (cancel) {
            focusView.requestFocus();
        } else {
            mStatusMessageView.setText(R.string.login_login_progress);
            showProgress(true);
            mLoginTask = new LoginTask();
            TaskActivityReference.getInstance().addTask(LoginTask.TASK_ID, mLoginTask, this);
            mLoginTask.execute(Helper.hash(mNFCTag + mLoginPassword));
        }
    }

    /**
     * Called by login task, when login is finished.
     */
    @Override
    public void onLoginFinished(Boolean success) {
        mLoginTask = null;
        showProgress(false);
        // Leave activity.
        if (success) {
            Intent intent = new Intent(this, PatientListActivity.class);
            startActivity(intent);
            // Start automatic logout timer.
            getApp().startWaiter();
            finish();
        } else {
            // Show error.
            Toast.makeText(this, R.string.login_login_error, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Checks input and setups database.
     */
    public void setup(View view) {
        if (mSetupTask != null || !mFirstRun) {
            return;
        }

        // Reset errors.
        mSetupDatabasePasswordView.setError(null);
        mSetupDatabaseConfirmView.setError(null);
        mSetupServerUsernameView.setError(null);
        mSetupServerPasswordView.setError(null);

        // Store UI values.
        mDatabasePassword = mSetupDatabasePasswordView.getText().toString();
        mDatabaseConfirm = mSetupDatabaseConfirmView.getText().toString();
        mServerUsername = mSetupServerUsernameView.getText().toString();
        mServerPassword = mSetupServerPasswordView.getText().toString();

        Boolean cancel = false;
        View focusView = null;

        // Check input.
        if (mSetupLocationView.getAdapter() != null) {
            mLocationID = ((ListViewItem) mSetupLocationView.getSelectedItem()).getId();
        } else {
            Toast.makeText(this, R.string.error_connection, Toast.LENGTH_SHORT).show();
            focusView = mSetupLocationView;
            cancel = true;
        }

        if (TextUtils.isEmpty(mDatabasePassword)) {
            mSetupDatabasePasswordView.setError(getString(R.string.error_field_required));
            focusView = mSetupDatabasePasswordView;
            cancel = true;
        } else if (mDatabasePassword.length() < 4) {
            mSetupDatabasePasswordView.setError(getString(R.string.error_invalid_password));
            focusView = mSetupDatabasePasswordView;
            cancel = true;
        }

        if (TextUtils.isEmpty(mDatabaseConfirm)) {
            mSetupDatabaseConfirmView.setError(getString(R.string.error_field_required));
            focusView = mSetupDatabaseConfirmView;
            cancel = true;
        } else if (!mDatabaseConfirm.equals(mDatabasePassword)) {
            mSetupDatabaseConfirmView.setError(getString(R.string.error_confirm_password));
            focusView = mSetupDatabaseConfirmView;
            cancel = true;
        }

        if (TextUtils.isEmpty(mServerUsername)) {
            mSetupServerUsernameView.setError(getString(R.string.error_field_required));
            focusView = mSetupServerUsernameView;
            cancel = true;
        }

        if (TextUtils.isEmpty(mServerPassword)) {
            mSetupServerPasswordView.setError(getString(R.string.error_field_required));
            focusView = mSetupServerPasswordView;
            cancel = true;
        }

        if (TextUtils.isEmpty(mNFCTag)) {
            mSetupNFCText.setError(getString(R.string.error_no_tag));
            focusView = mSetupNFCText;
            cancel = true;
        }

        // When there are no error start login task.
        if (cancel) {
            focusView.requestFocus();
        } else {
            mStatusMessageView.setText(R.string.login_setup_progress);
            showProgress(true);
            mSetupTask = new SetupTask(Helper.hash(mNFCTag + mDatabasePassword), mServerUsername, mServerPassword,
                    mLocationID);
            TaskActivityReference.getInstance().addTask(SetupTask.TASK_ID, mSetupTask, this);
            mSetupTask.execute();
        }
    }

    /**
     * Called by setup task, when setup is finished.
     */
    @Override
    public void onSetupFinished(Integer status) {
        mSetupTask = null;
        showProgress(false);
        if (status == STATUS_OK) {
            // Set flag for successful initialization.
            getSharedPreferences(Constants.PREFERENCE, MODE_PRIVATE).edit().putBoolean(ARG_FIRST_RUN, false)
                    .commit();
            // Leave activity.
            Intent intent = new Intent(this, PatientListActivity.class);
            startActivity(intent);
            // Start automatic logout timer.
            getApp().startWaiter();
            finish();
            // Show errors.
        } else if (status == STATUS_DATABASE_ERROR) {
            Toast.makeText(this, R.string.login_setup_error, Toast.LENGTH_SHORT).show();
        } else if (status == STATUS_CONNECTION_ERROR) {
            Toast.makeText(this, R.string.error_connection, Toast.LENGTH_SHORT).show();
        } else if (status == STATUS_LOGIN_WRONG) {
            Toast.makeText(this, R.string.login_setup_login_wrong, Toast.LENGTH_SHORT).show();
        }
    }

    // Show progress of setup task.
    @Override
    public void updateStatus(int status) {
        String message = "";
        switch (status) {
        case STATUS_DATABASE:
            message = getString(R.string.login_setup_status_database);
            break;
        case STATUS_CHECK_LOGIN:
            message = getString(R.string.login_setup_status_check_login);
            break;
        case STATUS_SYNC_FETCH_FACTS:
            message = getString(R.string.login_setup_status_fetch_facts);
            break;
        case STATUS_SYNC_FETCH_USERDATA:
            message = getString(R.string.login_setup_status_sync_fetch_userdata);
            break;
        }
        mStatusMessageView.setText(message);
    }

    /**
     * Shows the progress UI and hides the login form.
     */
    private void showProgress(final boolean show) {
        mProgress = show;
        InputMethodManager inputManager = (InputMethodManager) getActivity()
                .getSystemService(FragmentActivity.INPUT_METHOD_SERVICE);
        if (getActivity().getCurrentFocus() != null) {
            inputManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
                    InputMethodManager.HIDE_NOT_ALWAYS);
        }
        int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);

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

        if (mFirstRun) {
            mSetupFormView.setVisibility(View.VISIBLE);
            mSetupFormView.animate().setDuration(shortAnimTime).alpha(show ? 0 : 1)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            mSetupFormView.setVisibility(show ? View.GONE : View.VISIBLE);
                        }
                    });
        } else {
            mLoginFormView.setVisibility(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);
                        }
                    });
        }
    }

    @Override
    public Activity getActivity() {
        return this;
    }

    /**
     * Fetches locations.
     */
    public void loadLocations() {
        if (mLocationWebTask != null || mSetupLocationView.getAdapter() != null) {
            return;
        }

        mStatusMessageView.setText(R.string.login_setup_locations_progress);
        showProgress(true);
        mLocationWebTask = new LocationWebTask();
        TaskActivityReference.getInstance().addTask(LocationWebTask.TASK_ID, mLocationWebTask, this);
        mLocationWebTask.execute();
    }

    @Override
    public void onLocationsFetched(List<ListViewItem> result) {
        mLocationWebTask = null;
        showProgress(false);
        if (result != null) {
            mLocations = result;
            ArrayAdapter<ListViewItem> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item,
                    result);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            mSetupLocationView.setAdapter(adapter);
        } else {
            // show error
            Toast.makeText(this, R.string.error_connection, Toast.LENGTH_SHORT).show();
        }

    }
}