Convert setup to use checker fragment

* Activities modified to use new check-settings fragment:
  * AccountSetupBasics (auto-setup for imap/pop)
  * AccountSetupIncoming
  * AccountSetupOutgoing

Next CL: Same work for exchange, and terminate old CheckSettings activity.

Change-Id: If5c5bfe331161b2429f7d7a4bd13290932f03c47
This commit is contained in:
Andrew Stadler 2010-09-10 15:50:55 -07:00
parent ad0c1253c7
commit fd14496c49
10 changed files with 210 additions and 121 deletions

View File

@ -26,6 +26,7 @@ import com.android.email.mail.Store;
import com.android.email.provider.EmailContent.Account;
import com.android.email.service.EmailServiceProxy;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
@ -50,10 +51,8 @@ import android.util.Log;
* conditions.
*
* TODO support for account setup, including
* - general workflow
* - autodiscover
* - forwarding account security info
* TODO Change progress dialog from AlertDialog to ProgressDialog (can't use builder)
*/
public class AccountCheckSettingsFragment extends Fragment {
@ -84,10 +83,20 @@ public class AccountCheckSettingsFragment extends Fragment {
private String mErrorMessage;
private ErrorDialog mErrorDialog;
private SecurityRequiredDialog mSecurityRequiredDialog;
// Support for AsyncTask and account checking
AccountCheckTask mAccountCheckTask;
/**
* Callback interface for any target or activity doing account check settings
*/
public interface Callbacks {
/**
* CheckSettings completed with no errors
*/
public void onCheckSettingsOk();
}
/**
* Create a retained, invisible fragment that checks accounts
*
@ -183,14 +192,8 @@ public class AccountCheckSettingsFragment extends Fragment {
// 2. exit self
fm.popBackStack();
// 3. report OK back to target fragment
Fragment target = getTargetFragment();
if (target instanceof AccountServerBaseFragment) {
AccountServerBaseFragment f = (AccountServerBaseFragment) target;
f.onCheckSettingsOk();
} else {
// STOPSHIP: Remove if not needed. May need to handle Account setup here
throw new IllegalStateException();
}
Callbacks callbackTarget = getCallbackTarget();
callbackTarget.onCheckSettingsOk();
} else if (newState == STATE_CHECK_SHOW_SECURITY) {
// 1. get rid of progress dialog (if any)
recoverAndDismissCheckingDialog();
@ -218,6 +221,21 @@ public class AccountCheckSettingsFragment extends Fragment {
}
}
/**
* Find the callback target, either a target fragment or the activity
*/
private Callbacks getCallbackTarget() {
Fragment target = getTargetFragment();
if (target instanceof Callbacks) {
return (Callbacks) target;
}
Activity activity = getActivity();
if (activity instanceof Callbacks) {
return (Callbacks) activity;
}
throw new IllegalStateException();
}
/**
* Recover and dismiss the progress dialog fragment
*/
@ -262,14 +280,8 @@ public class AccountCheckSettingsFragment extends Fragment {
private void onSecurityRequiredDialogButtonOk(boolean okPressed) {
// 1. handle OK - notify that security is OK and we can proceed
if (okPressed) {
Fragment target = getTargetFragment();
if (target instanceof AccountServerBaseFragment) {
AccountServerBaseFragment f = (AccountServerBaseFragment) target;
f.onCheckSettingsOk();
} else {
// STOPSHIP: Remove if not needed. May need to handle Account setup here
throw new IllegalStateException();
}
Callbacks callbackTarget = getCallbackTarget();
callbackTarget.onCheckSettingsOk();
}
// 2. kill self
getFragmentManager().popBackStack();

View File

@ -34,7 +34,8 @@ import android.view.MenuItem;
* Activity callback during onAttach
* Present "Next" button and respond to its clicks
*/
public abstract class AccountServerBaseFragment extends Fragment {
public abstract class AccountServerBaseFragment extends Fragment
implements AccountCheckSettingsFragment.Callbacks {
protected Context mContext;
protected Callback mCallback = EmptyCallback.INSTANCE;
@ -49,17 +50,27 @@ public abstract class AccountServerBaseFragment extends Fragment {
* @param enable true to enable proceed/next button, false to disable
*/
public void onEnableProceedButtons(boolean enable);
/**
* Called when user clicks "next"
* Called when user clicks "next". Starts account checker.
* @param checkMode values from {@link SetupData}
* @param target the fragment that requested the check
*/
public void onProceedNext(int checkMode);
public void onProceedNext(int checkMode, AccountServerBaseFragment target);
/**
* Called when account checker returns "ok". Fragments are responsible for saving
* own edited data; This is primarily for the activity to do post-check navigation.
* @param setupMode signals if we were editing or creating
*/
public void onCheckSettingsOk(int setupMode);
}
private static class EmptyCallback implements Callback {
public static final Callback INSTANCE = new EmptyCallback();
@Override public void onEnableProceedButtons(boolean enable) { }
@Override public void onProceedNext(int checkMode) { }
@Override public void onProceedNext(int checkMode, AccountServerBaseFragment target) { }
@Override public void onCheckSettingsOk(int setupMode) { }
}
/**
@ -144,11 +155,19 @@ public abstract class AccountServerBaseFragment extends Fragment {
}
/**
* Implements AccountCheckSettingsFragment.Callbacks
*
* Handle OK result from check settings. Save settings, and exit to previous fragment.
*/
@Override
public void onCheckSettingsOk() {
saveSettingsAfterEdit();
getActivity().onBackPressed();
if (SetupData.getFlowMode() == SetupData.FLOW_MODE_EDIT) {
saveSettingsAfterEdit();
} else {
saveSettingsAfterSetup();
}
// Signal to owning activity that a settings check was OK
mCallback.onCheckSettingsOk(SetupData.getFlowMode());
}
/**
@ -156,6 +175,11 @@ public abstract class AccountServerBaseFragment extends Fragment {
*/
public abstract void saveSettingsAfterEdit();
/**
* Save settings after "OK" result from checker. Concrete classes must implement.
*/
public abstract void saveSettingsAfterSetup();
/**
* Respond to a click of the "Next" button. Concrete classes must implement.
*/

View File

@ -39,7 +39,6 @@ import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@ -49,7 +48,14 @@ import android.widget.Button;
import java.util.List;
/**
* Handles account preferences using multi-pane arrangement when possible.
* Handles account preferences, using multi-pane arrangement when possible.
*
* This activity uses the following fragments:
* AccountSettingsFragment
* Account{Incoming/Outgoing/Exchange}Fragment
* AccountCheckSettingsFragment
* GeneralPreferences
* DebugFragment
*
* TODO: In Account settings in Phone UI, change title
* TODO: Rework all remaining calls to DB from UI thread
@ -207,23 +213,6 @@ public class AccountSettingsXL extends PreferenceActivity implements OnClickList
return result;
}
/**
* After verifying a new server configuration, we return here and continue. If editing
* succeeded, we do "back" to exit the settings screen.
*
* TODO: This goes away when we move checksettings into a fragment as well
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (mCurrentFragment instanceof AccountServerBaseFragment) {
AccountServerBaseFragment f = (AccountServerBaseFragment) mCurrentFragment;
f.saveSettingsAfterEdit();
}
onBackPressed();
}
}
private void enableDebugMenu() {
mShowDebugMenu = true;
invalidateHeaders();
@ -492,10 +481,20 @@ public class AccountSettingsXL extends PreferenceActivity implements OnClickList
public void onEnableProceedButtons(boolean enable) {
// This is not used - it's a callback for the legacy activities
}
@Override
public void onProceedNext(int setupMode) {
// TODO - this will be a fragment launch, with a fragment target result
AccountSetupCheckSettings.actionCheckSettings(AccountSettingsXL.this, setupMode);
public void onProceedNext(int checkMode, AccountServerBaseFragment target) {
AccountCheckSettingsFragment checkerFragment =
AccountCheckSettingsFragment.newInstance(checkMode, target);
startPreferenceFragment(checkerFragment, true);
}
/**
* After verifying a new server configuration as OK, we return here and continue. This
* simply does a "back" to exit the settings screen.
*/
public void onCheckSettingsOk(int setupMode) {
onBackPressed();
}
}

View File

@ -23,6 +23,7 @@ import com.android.email.activity.Welcome;
import com.android.email.provider.EmailContent.Account;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@ -30,15 +31,17 @@ import android.view.Menu;
import android.view.MenuItem;
/**
* Prompts the user for the email address and password. Also prompts for
* "Use this account as default" if this is the 2nd+ account being set up.
* Attempts to lookup default settings for the domain the user specified. If the
* domain is known the settings are handed off to the AccountSetupCheckSettings
* activity. If no settings are found the settings are handed off to the
* AccountSetupAccountType activity.
* Prompts the user for the email address and password. Also prompts for "Use this account as
* default" if this is the 2nd+ account being set up.
*
* If the domain is well-known, the account is configured fully and checked immediately
* using AccountCheckSettingsFragment. If this succeeds we proceed directly to AccountSetupOptions.
*
* If the domain is not known, or the user selects Manual setup, we invoke the
* AccountSetupAccountType activity where the user can begin to manually configure the account.
*/
public class AccountSetupBasics extends AccountSetupActivity
implements AccountSetupBasicsFragment.Callback {
implements AccountSetupBasicsFragment.Callback, AccountCheckSettingsFragment.Callbacks {
private AccountSetupBasicsFragment mFragment;
private boolean mManualButtonDisplayed;
@ -119,7 +122,7 @@ public class AccountSetupBasics extends AccountSetupActivity
mFragment = (AccountSetupBasicsFragment)
getFragmentManager().findFragmentById(R.id.setup_basics_fragment);
mManualButtonDisplayed = true;
boolean alternateStrings = false;
if (flowMode == SetupData.FLOW_MODE_ACCOUNT_MANAGER_EAS) {
@ -136,7 +139,9 @@ public class AccountSetupBasics extends AccountSetupActivity
mFragment.setCallback(this, alternateStrings);
}
/**
/**
* Implements AccountCheckSettingsFragment.Callbacks
*
* This is used in automatic setup mode to jump directly down to the names screen.
*
* NOTE: With this organization, it is *not* possible to auto-create an exchange account,
@ -144,11 +149,9 @@ public class AccountSetupBasics extends AccountSetupActivity
* skipping here).
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
AccountSetupOptions.actionOptions(this);
finish();
}
public void onCheckSettingsOk() {
AccountSetupOptions.actionOptions(this);
finish();
}
/**
@ -157,7 +160,7 @@ public class AccountSetupBasics extends AccountSetupActivity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
int menuId = mManualButtonDisplayed
? R.menu.account_setup_manual_next_option
? R.menu.account_setup_manual_next_option
: R.menu.account_setup_next_option;
getMenuInflater().inflate(menuId, menu);
return super.onCreateOptionsMenu(menu);
@ -207,11 +210,20 @@ public class AccountSetupBasics extends AccountSetupActivity
/**
* Implements AccountSetupBasicsFragment.Callback
*
* This is called when auto-setup (from hardcoded server info) is attempted.
* Replace the name/password fragment with the account checker, which will begin to
* check incoming/outgoing.
*/
@Override
public void onProceedAutomatic() {
AccountSetupCheckSettings.actionCheckSettings(this,
SetupData.CHECK_INCOMING | SetupData.CHECK_OUTGOING);
AccountCheckSettingsFragment checkerFragment =
AccountCheckSettingsFragment.newInstance(
SetupData.CHECK_INCOMING | SetupData.CHECK_OUTGOING, null);
FragmentTransaction transaction = getFragmentManager().openTransaction();
transaction.replace(R.id.setup_basics_fragment, checkerFragment);
transaction.addToBackStack("back");
transaction.commit();
}
/**

View File

@ -201,6 +201,13 @@ public class AccountSetupExchange extends AccountSetupActivity
// Otherwise, proceed into this activity for manual setup
}
/**
* Implements AccountServerBaseFragment.Callback
*/
public void onProceedNext(int checkMode, AccountServerBaseFragment target) {
AccountSetupCheckSettings.actionCheckSettings(this, checkMode);
}
/**
* Implements AccountServerBaseFragment.Callback
*/
@ -215,8 +222,10 @@ public class AccountSetupExchange extends AccountSetupActivity
/**
* Implements AccountServerBaseFragment.Callback
* TODO - should never happen, we don't use checksettings fragment (yet) for account setup
*/
public void onProceedNext(int checkMode) {
AccountSetupCheckSettings.actionCheckSettings(this, checkMode);
public void onCheckSettingsOk(int setupMode) {
throw new IllegalStateException();
}
}

View File

@ -49,10 +49,8 @@ import java.net.URISyntaxException;
/**
* Provides generic setup for Exchange accounts.
*
* TODO: The manifest for this activity has it ignore config changes, because
* we don't want to restart on every orientation - this would launch autodiscover again.
* Do not attempt to define orientation-specific resources, they won't be loaded.
* What we really need here is a more "sticky" way to prevent that problem.
* This fragment is used by AccountSetupExchange (for creating accounts) and by AccountSettingsXL
* (for editing existing accounts).
*/
public class AccountSetupExchangeFragment extends AccountServerBaseFragment
implements OnCheckedChangeListener {
@ -315,6 +313,14 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
AccountBackupRestore.backupAccounts(mContext);
}
/**
* TODO reconcile this generic entry point with setHostAuthFromAutodiscover
*/
@Override
public void saveSettingsAfterSetup() {
// TODO implement
}
/**
* Entry point from Activity after entering new settings and verifying them. For setup mode.
*/
@ -396,7 +402,7 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
((PreferenceActivity)activity).startPreferenceFragment(checkerFragment, true);
} else {
// STOPSHIP remove this old code
mCallback.onProceedNext(SetupData.CHECK_INCOMING);
mCallback.onProceedNext(SetupData.CHECK_INCOMING, this);
}
}
}

View File

@ -20,9 +20,16 @@ import com.android.email.R;
import com.android.email.provider.EmailContent;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
/**
* Provides setup flow for IMAP/POP accounts.
*
* Uses AccountSetupIncomingFragment for primary UI. Uses AccountCheckSettingsFragment to validate
* the settings as entered. If the account is OK, proceeds to AccountSetupOutgoing.
*/
public class AccountSetupIncoming extends AccountSetupActivity
implements AccountSetupIncomingFragment.Callback {
@ -53,39 +60,41 @@ public class AccountSetupIncoming extends AccountSetupActivity
}
/**
* After verifying a new server configuration, we return here and continue. If editing an
* existing account, we simply finish(). If creating a new account, we move to the next phase.
* Implements AccountServerBaseFragment.Callback
*
* Launches the account checker. Positive results are reported to onCheckSettingsOk().
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (SetupData.getFlowMode() == SetupData.FLOW_MODE_EDIT) {
mFragment.saveSettingsAfterEdit();
} else {
mFragment.saveSettingsAfterSetup();
AccountSetupOutgoing.actionOutgoingSettings(this, SetupData.getFlowMode(),
SetupData.getAccount());
}
finish();
}
public void onProceedNext(int checkMode, AccountServerBaseFragment target) {
AccountCheckSettingsFragment checkerFragment =
AccountCheckSettingsFragment.newInstance(checkMode, target);
FragmentTransaction transaction = getFragmentManager().openTransaction();
transaction.replace(R.id.setup_fragment, checkerFragment);
transaction.addToBackStack("back");
transaction.commit();
}
/**
* Implements AccountServerBaseFragment.Callback
*/
public void onEnableProceedButtons(boolean enabled) {
public void onEnableProceedButtons(boolean enable) {
boolean wasEnabled = mNextButtonEnabled;
mNextButtonEnabled = enabled;
mNextButtonEnabled = enable;
if (enabled != wasEnabled) {
if (enable != wasEnabled) {
invalidateOptionsMenu();
}
}
/**
* Implements AccountServerBaseFragment.Callback
*
* If the checked settings are OK, proceed to outgoing settings screen
*/
public void onProceedNext(int checkMode) {
AccountSetupCheckSettings.actionCheckSettings(this, checkMode);
public void onCheckSettingsOk(int setupMode) {
if (SetupData.getFlowMode() != SetupData.FLOW_MODE_EDIT) {
AccountSetupOutgoing.actionOutgoingSettings(this, SetupData.getFlowMode(),
SetupData.getAccount());
finish();
}
}
}

View File

@ -26,7 +26,6 @@ import com.android.email.provider.EmailContent.Account;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
@ -43,6 +42,12 @@ import android.widget.TextView;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Provides UI for IMAP/POP account settings.
*
* This fragment is used by AccountSetupIncoming (for creating accounts) and by AccountSettingsXL
* (for editing existing accounts).
*/
public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
private final static String STATE_KEY_CREDENTIAL =
@ -381,6 +386,7 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
/**
* Entry point from Activity after entering new settings and verifying them. For setup mode.
*/
@Override
public void saveSettingsAfterSetup() {
EmailContent.Account account = SetupData.getAccount();
@ -459,15 +465,6 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
setupAccount.setDeletePolicy(
(Integer)((SpinnerOption)mDeletePolicyView.getSelectedItem()).value);
// STOPSHIP - use new checker fragment only during account settings (TODO: account setup)
Activity activity = getActivity();
if (activity instanceof PreferenceActivity) {
AccountCheckSettingsFragment checkerFragment =
AccountCheckSettingsFragment.newInstance(SetupData.CHECK_INCOMING, this);
((PreferenceActivity)activity).startPreferenceFragment(checkerFragment, true);
} else {
// STOPSHIP remove this old code
mCallback.onProceedNext(SetupData.CHECK_INCOMING);
}
mCallback.onProceedNext(SetupData.CHECK_INCOMING, this);
}
}

View File

@ -17,13 +17,19 @@
package com.android.email.activity.setup;
import com.android.email.R;
import com.android.email.provider.EmailContent;
import com.android.email.provider.EmailContent.Account;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
/**
* Provides setup flow for SMTP (for IMAP/POP accounts).
*
* Uses AccountSetupOutgoingFragment for primary UI. Uses AccountCheckSettingsFragment to validate
* the settings as entered. If the account is OK, proceeds to AccountSetupOptions.
*/
public class AccountSetupOutgoing extends Activity
implements AccountSetupOutgoingFragment.Callback {
@ -52,38 +58,40 @@ public class AccountSetupOutgoing extends Activity
}
/**
* After verifying a new server configuration, we return here and continue. If editing an
* existing account, we simply finish(). If creating a new account, we move to the next phase.
* Implements AccountServerBaseFragment.Callback
*
* Launches the account checker. Positive results are reported to onCheckSettingsOk().
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
EmailContent.Account account = SetupData.getAccount();
if (resultCode == RESULT_OK) {
if (SetupData.getFlowMode() == SetupData.FLOW_MODE_EDIT) {
mFragment.saveSettingsAfterEdit();
} else {
AccountSetupOptions.actionOptions(this);
}
finish();
}
public void onProceedNext(int checkMode, AccountServerBaseFragment target) {
AccountCheckSettingsFragment checkerFragment =
AccountCheckSettingsFragment.newInstance(checkMode, target);
FragmentTransaction transaction = getFragmentManager().openTransaction();
transaction.replace(R.id.setup_fragment, checkerFragment);
transaction.addToBackStack("back");
transaction.commit();
}
/**
* Implements AccountServerBaseFragment.Callback
*/
public void onEnableProceedButtons(boolean enabled) {
public void onEnableProceedButtons(boolean enable) {
boolean wasEnabled = mNextButtonEnabled;
mNextButtonEnabled = enabled;
mNextButtonEnabled = enable;
if (enabled != wasEnabled) {
if (enable != wasEnabled) {
invalidateOptionsMenu();
}
}
/**
* Implements AccountServerBaseFragment.Callback
*
* If the checked settings are OK, proceed to options screen
*/
public void onProceedNext(int checkMode) {
AccountSetupCheckSettings.actionCheckSettings(this, checkMode);
public void onCheckSettingsOk(int setupMode) {
if (SetupData.getFlowMode() != SetupData.FLOW_MODE_EDIT) {
AccountSetupOptions.actionOptions(this);
}
finish();
}
}

View File

@ -44,6 +44,12 @@ import android.widget.Spinner;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Provides UI for SMTP account settings (for IMAP/POP accounts).
*
* This fragment is used by AccountSetupOutgoing (for creating accounts) and by AccountSettingsXL
* (for editing existing accounts).
*/
public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
implements OnCheckedChangeListener {
private static final int SMTP_PORTS[] = {
@ -335,6 +341,13 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
AccountBackupRestore.backupAccounts(mContext);
}
/**
* Entry point from Activity after entering new settings and verifying them. For setup mode.
*/
@Override
public void saveSettingsAfterSetup() {
}
/**
* Attempt to create a URI from the fields provided. Throws URISyntaxException if there's
* a problem with the user input.
@ -382,7 +395,7 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
((PreferenceActivity)activity).startPreferenceFragment(checkerFragment, true);
} else {
// STOPSHIP remove this old code
mCallback.onProceedNext(SetupData.CHECK_OUTGOING);
mCallback.onProceedNext(SetupData.CHECK_OUTGOING, this);
}
}
}