blob: 9605f09b3fb684b43d733314b44896335ac7b672 [file] [log] [blame]
/*
* Copyright (C) 2012 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.android.mail.ui;
import com.android.mail.R;
import com.android.mail.analytics.Analytics;
import com.android.mail.providers.Account;
import com.android.mail.providers.MailAppProvider;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogTag;
import java.util.ArrayList;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.LoaderManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentResolver;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
/**
* An activity that shows the list of all the available accounts and return the
* one selected in onResult().
*/
public class MailboxSelectionActivity extends AppCompatActivity implements OnClickListener,
LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
// Used to save our instance state
private static final String CREATE_SHORTCUT_KEY = "createShortcut";
private static final String CREATE_WIDGET_KEY = "createWidget";
private static final String WIDGET_ID_KEY = "widgetId";
private static final String WAITING_FOR_ADD_ACCOUNT_RESULT_KEY = "waitingForAddAccountResult";
private static final String ACCOUNT = "name";
private static final String[] COLUMN_NAMES = { ACCOUNT };
protected static final String LOG_TAG = LogTag.getLogTag();
private static final int RESULT_CREATE_ACCOUNT = 2;
private static final int LOADER_ACCOUNT_CURSOR = 0;
private static final String TAG_WAIT = "wait-fragment";
private final int[] VIEW_IDS = { R.id.mailbox_name };
private boolean mCreateShortcut = false;
private boolean mConfigureWidget = false;
private SimpleCursorAdapter mAdapter;
private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
// Boolean to indicate that we are waiting for the result from an add account
// operation. This boolean is necessary, as there is no guarantee on whether the
// AccountManager callback or onResume will be called first.
boolean mWaitingForAddAccountResult = false;
// Can only do certain actions if the Activity is resumed (e.g. setVisible)
private boolean mResumed = false;
private Handler mHandler = new Handler();
private ListView mList;
private View mContent;
private View mWait;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.mailbox_selection_activity);
mList = (ListView) findViewById(android.R.id.list);
mList.setOnItemClickListener(this);
mContent = findViewById(R.id.content);
mWait = findViewById(R.id.wait);
if (icicle != null) {
restoreState(icicle);
} else {
if (Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
mCreateShortcut = true;
}
mAppWidgetId = getIntent().getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
mConfigureWidget = true;
}
}
// We set the default title to "Gmail" or "Google Mail" for consistency
// in Task Switcher. If this is for create shortcut or configure widget,
// we should set the title to "Select account".
if (mCreateShortcut || mConfigureWidget) {
setTitle(getResources().getString(R.string.activity_mailbox_selection));
}
findViewById(R.id.first_button).setOnClickListener(this);
// Initially, assume that the main view is invisible. It will be made visible,
// if we display the account list
setVisible(false);
setResult(RESULT_CANCELED);
}
@Override
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
icicle.putBoolean(CREATE_SHORTCUT_KEY, mCreateShortcut);
icicle.putBoolean(CREATE_WIDGET_KEY, mConfigureWidget);
if (mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
icicle.putInt(WIDGET_ID_KEY, mAppWidgetId);
}
icicle.putBoolean(WAITING_FOR_ADD_ACCOUNT_RESULT_KEY, mWaitingForAddAccountResult);
}
@Override
public void onStart() {
super.onStart();
Analytics.getInstance().activityStart(this);
}
@Override
protected void onStop() {
super.onStop();
Analytics.getInstance().activityStop(this);
}
@Override
public void onResume() {
super.onResume();
mResumed = true;
// Only fetch the accounts, if we are not handling a response from the
// launched child activity.
if (!mWaitingForAddAccountResult) {
setupWithAccounts();
}
}
@Override
public void onPause() {
super.onPause();
mResumed = false;
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
/**
* Restores the activity state from a bundle
*/
private void restoreState(Bundle icicle) {
if (icicle.containsKey(CREATE_SHORTCUT_KEY)) {
mCreateShortcut = icicle.getBoolean(CREATE_SHORTCUT_KEY);
}
if (icicle.containsKey(CREATE_WIDGET_KEY)) {
mConfigureWidget = icicle.getBoolean(CREATE_WIDGET_KEY);
}
if (icicle.containsKey(WIDGET_ID_KEY)) {
mAppWidgetId = icicle.getInt(WIDGET_ID_KEY);
}
if (icicle.containsKey(WAITING_FOR_ADD_ACCOUNT_RESULT_KEY)) {
mWaitingForAddAccountResult = icicle.getBoolean(WAITING_FOR_ADD_ACCOUNT_RESULT_KEY);
}
}
private void setupWithAccounts() {
final ContentResolver resolver = getContentResolver();
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
Cursor cursor = null;
try {
cursor = resolver.query(MailAppProvider.getAccountsUri(),
UIProvider.ACCOUNTS_PROJECTION, null, null, null);
completeSetupWithAccounts(cursor);
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
}.execute();
}
private void completeSetupWithAccounts(final Cursor accounts) {
mHandler.post(new Runnable() {
@Override
public void run() {
updateAccountList(accounts);
}
});
}
private void updateAccountList(final Cursor accounts) {
boolean displayAccountList = true;
// Configuring a widget or shortcut.
if (mConfigureWidget || mCreateShortcut) {
if (accounts == null || accounts.getCount() == 0) {
// No account found, show Add Account screen, for both the widget or
// shortcut creation process
// No account found, show Add Account screen, for both the widget or
// shortcut creation process
final Intent noAccountIntent = MailAppProvider.getNoAccountIntent(this);
if (noAccountIntent != null) {
startActivityForResult(noAccountIntent, RESULT_CREATE_ACCOUNT);
}
// No reason to display the account list
displayAccountList = false;
// Indicate that we need to handle the response from the add account action
// This allows us to process the results that we get in the AddAccountCallback
mWaitingForAddAccountResult = true;
} else if (mConfigureWidget && accounts.getCount() == 1) {
mWait.setVisibility(View.GONE);
// When configuring a widget, if there is only one account, automatically
// choose that account.
accounts.moveToFirst();
selectAccount(Account.builder().buildFrom(accounts));
// No reason to display the account list
displayAccountList = false;
}
}
if (displayAccountList) {
mContent.setVisibility(View.VISIBLE);
// We are about to display the list, make this activity visible
// But only if the Activity is not paused!
if (mResumed) {
setVisible(true);
}
mAdapter = new SimpleCursorAdapter(this, R.layout.mailbox_item, accounts,
COLUMN_NAMES, VIEW_IDS, 0) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
TextView accountView = (TextView) v.findViewById(R.id.mailbox_name);
final Account account = Account.builder().buildFrom((Cursor) getItem(position));
accountView.setText(account.getDisplayName());
return v;
}
};
mList.setAdapter(mAdapter);
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectAccount(Account.builder().buildFrom((Cursor) mAdapter.getItem(position)));
}
private void selectAccount(Account account) {
if (mCreateShortcut || mConfigureWidget) {
// Invoked for a shortcut creation
final Intent intent = new Intent(this, getFolderSelectionActivity());
intent.setFlags(
Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_FORWARD_RESULT);
intent.setAction(mCreateShortcut ?
Intent.ACTION_CREATE_SHORTCUT : AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
if (mConfigureWidget) {
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
}
intent.putExtra(FolderSelectionActivity.EXTRA_ACCOUNT_SHORTCUT, account);
startActivity(intent);
finish();
} else {
// TODO: (mindyp) handle changing the account for this shortcut.
finish();
}
}
/**
* Return the class responsible for launching the folder selection activity.
*/
protected Class<?> getFolderSelectionActivity() {
return FolderSelectionActivity.class;
}
@Override
public void onClick(View v) {
final int id = v.getId();
if (id == R.id.first_button) {
setResult(RESULT_CANCELED);
finish();
}
}
@Override
protected final void onActivityResult(int request, int result, Intent data) {
if (request == RESULT_CREATE_ACCOUNT) {
// We were waiting for the user to create an account
if (result != RESULT_OK) {
finish();
} else {
// Watch for accounts to show up!
// restart the loader to get the updated list of accounts
getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this);
showWaitFragment(null);
}
}
}
private void showWaitFragment(Account account) {
WaitFragment fragment = getWaitFragment();
if (fragment != null) {
fragment.updateAccount(account);
} else {
mWait.setVisibility(View.VISIBLE);
replaceFragment(WaitFragment.newInstance(account, false /* expectingMessages */),
FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_WAIT);
}
mContent.setVisibility(View.GONE);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case LOADER_ACCOUNT_CURSOR:
return new CursorLoader(this, MailAppProvider.getAccountsUri(),
UIProvider.ACCOUNTS_PROJECTION, null, null, null);
}
return null;
}
private WaitFragment getWaitFragment() {
return (WaitFragment) getFragmentManager().findFragmentByTag(TAG_WAIT);
}
private int replaceFragment(Fragment fragment, int transition, String tag) {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.setTransition(transition);
fragmentTransaction.replace(R.id.wait, fragment, tag);
final int transactionId = fragmentTransaction.commitAllowingStateLoss();
return transactionId;
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
// Do nothing.
}
@Override
public void onLoadFinished(Loader<Cursor> cursor, Cursor data) {
if (data != null && data.moveToFirst()) {
// there are accounts now!
Account account;
ArrayList<Account> accounts = new ArrayList<Account>();
ArrayList<Account> initializedAccounts = new ArrayList<Account>();
do {
account = Account.builder().buildFrom(data);
if (account.isAccountReady()) {
initializedAccounts.add(account);
}
accounts.add(account);
} while (data.moveToNext());
if (initializedAccounts.size() > 0) {
mWait.setVisibility(View.GONE);
getLoaderManager().destroyLoader(LOADER_ACCOUNT_CURSOR);
mContent.setVisibility(View.VISIBLE);
updateAccountList(data);
} else {
// Show "waiting"
account = accounts.size() > 0 ? accounts.get(0) : null;
showWaitFragment(account);
}
}
}
@Override
public void onBackPressed() {
mWaitingForAddAccountResult = false;
// If we are showing the wait fragment, just exit.
if (getWaitFragment() != null) {
finish();
} else {
super.onBackPressed();
}
}
}