diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5a0eca1f4..85e9c6d60 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -268,16 +268,12 @@
android:label="@string/account_setup_outgoing_title"
>
+
-
-
-
-
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
-
-
-
+ android:paddingTop="@dimen/setup_padding_top"
+ android:paddingLeft="@dimen/setup_padding_left"
+ android:paddingRight="@dimen/setup_padding_right" >
-
-
+
+
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/res/layout-sw600dp-land/account_setup_buttons.xml b/res/layout-sw600dp-land/account_setup_buttons.xml
new file mode 100644
index 000000000..2ee760767
--- /dev/null
+++ b/res/layout-sw600dp-land/account_setup_buttons.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
diff --git a/res/layout-sw600dp-land/account_setup_names.xml b/res/layout-sw600dp-land/account_setup_names.xml
deleted file mode 100644
index 568576423..000000000
--- a/res/layout-sw600dp-land/account_setup_names.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout-sw600dp-land/account_setup_options.xml b/res/layout-sw600dp-land/account_setup_options.xml
deleted file mode 100644
index 814cf079b..000000000
--- a/res/layout-sw600dp-land/account_setup_options.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout-sw600dp-port/account_setup.xml b/res/layout-sw600dp-port/account_setup.xml
new file mode 100644
index 000000000..f9589b597
--- /dev/null
+++ b/res/layout-sw600dp-port/account_setup.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout-sw600dp-port/account_setup_options.xml b/res/layout-sw600dp-port/account_setup_options.xml
deleted file mode 100644
index 0d53e6f17..000000000
--- a/res/layout-sw600dp-port/account_setup_options.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout/account_setup_names.xml b/res/layout/account_setup.xml
similarity index 50%
rename from res/layout/account_setup_names.xml
rename to res/layout/account_setup.xml
index f0e3a7073..965a4722b 100644
--- a/res/layout/account_setup_names.xml
+++ b/res/layout/account_setup.xml
@@ -1,5 +1,5 @@
-
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true" >
+
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingTop="@dimen/setup_fragment_padding_top"
+ android:paddingLeft="@dimen/setup_fragment_padding_left"
+ android:paddingRight="@dimen/setup_fragment_padding_right" >
+
+
-
-
+
+
diff --git a/res/layout/account_setup_buttons.xml b/res/layout/account_setup_buttons.xml
index 242340bb7..55edf31d8 100644
--- a/res/layout/account_setup_buttons.xml
+++ b/res/layout/account_setup_buttons.xml
@@ -14,23 +14,22 @@
limitations under the License.
-->
-
+
+ android:id="@+id/previous"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="@dimen/setup_buttons_padding_left"
+ style="@style/accountSetupButton"
+ android:text="@string/previous_action" />
-
+ android:id="@+id/next"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginRight="@dimen/setup_buttons_padding_right"
+ style="@style/accountSetupButton"
+ android:text="@string/next_action" />
+
\ No newline at end of file
diff --git a/res/layout-sw600dp/account_setup_names_common.xml b/res/layout/account_setup_fragment_container.xml
similarity index 62%
rename from res/layout-sw600dp/account_setup_names_common.xml
rename to res/layout/account_setup_fragment_container.xml
index 66c4cefe7..ba0af41cf 100644
--- a/res/layout-sw600dp/account_setup_names_common.xml
+++ b/res/layout/account_setup_fragment_container.xml
@@ -1,5 +1,5 @@
-
-
-
-
+
-
-
-
+
+
diff --git a/res/layout/account_setup_options.xml b/res/layout/account_setup_options.xml
deleted file mode 100644
index 7a629c94c..000000000
--- a/res/layout/account_setup_options.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/com/android/email/activity/ActivityHelper.java b/src/com/android/email/activity/ActivityHelper.java
index ebab0e54a..f435ed12d 100644
--- a/src/com/android/email/activity/ActivityHelper.java
+++ b/src/com/android/email/activity/ActivityHelper.java
@@ -32,6 +32,7 @@ import com.android.emailcommon.provider.Account;
*
* Common code used by the activities and the fragments.
*/
+@Deprecated
public final class ActivityHelper {
private ActivityHelper() {
}
diff --git a/src/com/android/email/activity/setup/AccountCreationFragment.java b/src/com/android/email/activity/setup/AccountCreationFragment.java
new file mode 100644
index 000000000..e4322c3ed
--- /dev/null
+++ b/src/com/android/email/activity/setup/AccountCreationFragment.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2014 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.email.activity.setup;
+
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.Fragment;
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.Loader;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+
+import com.android.email.service.EmailServiceUtils;
+import com.android.email2.ui.MailActivityEmail;
+import com.android.emailcommon.provider.Account;
+import com.android.emailcommon.service.EmailServiceProxy;
+import com.android.mail.preferences.AccountPreferences;
+import com.android.mail.ui.MailAsyncTaskLoader;
+import com.android.mail.utils.LogUtils;
+
+import java.io.IOException;
+
+/**
+ * This retained headless fragment acts as a container for the multi-step task of creating the
+ * AccountManager account and saving our account object to the database, as well as some misc
+ * related background tasks.
+ */
+public class AccountCreationFragment extends Fragment {
+ public static final int REQUEST_CODE_ACCEPT_POLICIES = 1;
+
+ private static final String ACCOUNT_TAG = "account";
+ private static final String SYNC_EMAIL_TAG = "email";
+ private static final String SYNC_CALENDAR_TAG = "calendar";
+ private static final String SYNC_CONTACTS_TAG = "contacts";
+ private static final String NOTIFICATIONS_TAG = "notifications";
+
+ private static final String SAVESTATE_STAGE = "AccountCreationFragment.stage";
+ private static final int STAGE_BEFORE_ACCOUNT_SECURITY = 0;
+ private static final int STAGE_REFRESHING_ACCOUNT = 1;
+ private static final int STAGE_WAITING_FOR_ACCOUNT_SECURITY = 2;
+ private static final int STAGE_AFTER_ACCOUNT_SECURITY = 3;
+ private int mStage = 0;
+
+ private Context mAppContext;
+ private final Handler mHandler;
+
+ AccountCreationFragment() {
+ mHandler = new Handler();
+ }
+
+ public static AccountCreationFragment newInstance(Account account, boolean syncEmail,
+ boolean syncCalendar, boolean syncContacts, boolean enableNotifications) {
+ final Bundle args = new Bundle(5);
+ args.putParcelable(AccountCreationFragment.ACCOUNT_TAG, account);
+ args.putBoolean(AccountCreationFragment.SYNC_EMAIL_TAG, syncEmail);
+ args.putBoolean(AccountCreationFragment.SYNC_CALENDAR_TAG, syncCalendar);
+ args.putBoolean(AccountCreationFragment.SYNC_CONTACTS_TAG, syncContacts);
+ args.putBoolean(AccountCreationFragment.NOTIFICATIONS_TAG, enableNotifications);
+
+ final AccountCreationFragment f = new AccountCreationFragment();
+ f.setArguments(args);
+ return f;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setRetainInstance(true);
+ mAppContext = getActivity().getApplicationContext();
+ if (savedInstanceState != null) {
+ mStage = savedInstanceState.getInt(SAVESTATE_STAGE);
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(SAVESTATE_STAGE, mStage);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ switch (mStage) {
+ case STAGE_BEFORE_ACCOUNT_SECURITY:
+ kickBeforeAccountSecurityLoader();
+ break;
+ case STAGE_REFRESHING_ACCOUNT:
+ kickRefreshingAccountLoader();
+ break;
+ case STAGE_WAITING_FOR_ACCOUNT_SECURITY:
+ // TODO: figure out when we might get here and what to do if we do
+ break;
+ case STAGE_AFTER_ACCOUNT_SECURITY:
+ kickAfterAccountSecurityLoader();
+ break;
+ }
+ }
+
+ private void kickBeforeAccountSecurityLoader() {
+ final LoaderManager loaderManager = getLoaderManager();
+
+ loaderManager.destroyLoader(STAGE_REFRESHING_ACCOUNT);
+ loaderManager.destroyLoader(STAGE_AFTER_ACCOUNT_SECURITY);
+ loaderManager.initLoader(STAGE_BEFORE_ACCOUNT_SECURITY, getArguments(),
+ new BeforeAccountSecurityCallbacks());
+ }
+
+ private void kickRefreshingAccountLoader() {
+ final LoaderManager loaderManager = getLoaderManager();
+
+ loaderManager.destroyLoader(STAGE_BEFORE_ACCOUNT_SECURITY);
+ loaderManager.destroyLoader(STAGE_AFTER_ACCOUNT_SECURITY);
+ loaderManager.initLoader(STAGE_REFRESHING_ACCOUNT, getArguments(),
+ new RefreshAccountCallbacks());
+ }
+
+ private void kickAfterAccountSecurityLoader() {
+ final LoaderManager loaderManager = getLoaderManager();
+
+ loaderManager.destroyLoader(STAGE_BEFORE_ACCOUNT_SECURITY);
+ loaderManager.destroyLoader(STAGE_REFRESHING_ACCOUNT);
+ loaderManager.initLoader(STAGE_AFTER_ACCOUNT_SECURITY, getArguments(),
+ new AfterAccountSecurityCallbacks());
+ }
+
+ private class BeforeAccountSecurityCallbacks
+ implements LoaderManager.LoaderCallbacks {
+ public BeforeAccountSecurityCallbacks() {}
+
+ @Override
+ public Loader onCreateLoader(int id, Bundle args) {
+ final Account account = args.getParcelable(ACCOUNT_TAG);
+ final boolean email = args.getBoolean(SYNC_EMAIL_TAG);
+ final boolean calendar = args.getBoolean(SYNC_CALENDAR_TAG);
+ final boolean contacts = args.getBoolean(SYNC_CONTACTS_TAG);
+ final boolean notificationsEnabled = args.getBoolean(NOTIFICATIONS_TAG);
+
+ /**
+ * Task loader returns true if we created the account, false if we bailed out.
+ */
+ return new MailAsyncTaskLoader(mAppContext) {
+ @Override
+ protected void onDiscardResult(Boolean result) {}
+
+ @Override
+ public Boolean loadInBackground() {
+ // Set the incomplete flag here to avoid reconciliation issues
+ account.mFlags |= Account.FLAGS_INCOMPLETE;
+
+ AccountSettingsUtils.commitSettings(mAppContext, account);
+ final AccountManagerFuture future =
+ EmailServiceUtils.setupAccountManagerAccount(mAppContext, account,
+ email, calendar, contacts, null);
+
+ boolean createSuccess = false;
+ try {
+ future.getResult();
+ createSuccess = true;
+ } catch (OperationCanceledException e) {
+ LogUtils.d(LogUtils.TAG, "addAccount was canceled");
+ } catch (IOException e) {
+ LogUtils.d(LogUtils.TAG, "addAccount failed: " + e);
+ } catch (AuthenticatorException e) {
+ LogUtils.d(LogUtils.TAG, "addAccount failed: " + e);
+ }
+ if (!createSuccess) {
+ return false;
+ }
+ // We can move the notification setting to the inbox FolderPreferences
+ // later, once we know what the inbox is
+ new AccountPreferences(mAppContext, account.getEmailAddress())
+ .setDefaultInboxNotificationsEnabled(notificationsEnabled);
+
+ // Now that AccountManager account creation is complete, clear the
+ // INCOMPLETE flag
+ account.mFlags &= ~Account.FLAGS_INCOMPLETE;
+ AccountSettingsUtils.commitSettings(mAppContext, account);
+
+ return true;
+ }
+ };
+ }
+
+ @Override
+ public void onLoadFinished(Loader loader, Boolean success) {
+ if (success == null || !isResumed()) {
+ return;
+ }
+ if (success) {
+ mStage = STAGE_REFRESHING_ACCOUNT;
+ kickRefreshingAccountLoader();
+ } else {
+ final AccountSetupFinal activity = (AccountSetupFinal)getActivity();
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (!isResumed()) {
+ return;
+ }
+ // Can't do this from within onLoadFinished
+ activity.destroyAccountCreationFragment();
+ activity.showCreateAccountErrorDialog();
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {}
+ }
+
+ private class RefreshAccountCallbacks implements LoaderManager.LoaderCallbacks {
+
+ @Override
+ public Loader onCreateLoader(int id, Bundle args) {
+ final Account account = args.getParcelable(ACCOUNT_TAG);
+ return new MailAsyncTaskLoader(mAppContext) {
+ @Override
+ protected void onDiscardResult(Account result) {}
+
+ @Override
+ public Account loadInBackground() {
+ account.refresh(mAppContext);
+ return account;
+ }
+ };
+ }
+
+ @Override
+ public void onLoadFinished(Loader loader, Account account) {
+ if (account == null || !isResumed()) {
+ return;
+ }
+
+ getArguments().putParcelable(ACCOUNT_TAG, account);
+
+ if ((account.mFlags & Account.FLAGS_SECURITY_HOLD) != 0) {
+ final Intent intent = AccountSecurity
+ .actionUpdateSecurityIntent(getActivity(), account.mId, false);
+ startActivityForResult(intent, REQUEST_CODE_ACCEPT_POLICIES);
+ mStage = STAGE_WAITING_FOR_ACCOUNT_SECURITY;
+ } else {
+ mStage = STAGE_AFTER_ACCOUNT_SECURITY;
+ kickAfterAccountSecurityLoader();
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {}
+ }
+
+ private class AfterAccountSecurityCallbacks
+ implements LoaderManager.LoaderCallbacks {
+ @Override
+ public Loader onCreateLoader(int id, Bundle args) {
+ final Account account = args.getParcelable(ACCOUNT_TAG);
+ return new MailAsyncTaskLoader(mAppContext) {
+ @Override
+ protected void onDiscardResult(Account result) {}
+
+ @Override
+ public Account loadInBackground() {
+ // Clear the security hold flag now
+ account.mFlags &= ~Account.FLAGS_SECURITY_HOLD;
+ AccountSettingsUtils.commitSettings(mAppContext, account);
+ // Start up services based on new account(s)
+ MailActivityEmail.setServicesEnabledSync(mAppContext);
+ EmailServiceUtils
+ .startService(mAppContext, account.mHostAuthRecv.mProtocol);
+ return account;
+ }
+ };
+ }
+
+ @Override
+ public void onLoadFinished(final Loader loader, final Account account) {
+ // Need to do this from a runnable because this triggers fragment transactions
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (account == null || !isResumed()) {
+ return;
+ }
+
+ // Move to final setup screen
+ AccountSetupFinal activity = (AccountSetupFinal) getActivity();
+ activity.getSetupData().setAccount(account);
+ activity.proceedFromAccountCreationFragment();
+
+ // Update the folder list (to get our starting folders, e.g. Inbox)
+ final EmailServiceProxy proxy = EmailServiceUtils.getServiceForAccount(activity,
+ account.mId);
+ try {
+ proxy.updateFolderList(account.mId);
+ } catch (RemoteException e) {
+ // It's all good
+ }
+
+ }
+ });
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {}
+ }
+
+ /**
+ * This is called after the AccountSecurity activity completes.
+ */
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mStage = STAGE_AFTER_ACCOUNT_SECURITY;
+ // onResume() will be called immediately after this to kick the next loader
+ }
+}
diff --git a/src/com/android/email/activity/setup/AccountSetupBasics.java b/src/com/android/email/activity/setup/AccountSetupBasics.java
index 67892ff92..00af3139f 100644
--- a/src/com/android/email/activity/setup/AccountSetupBasics.java
+++ b/src/com/android/email/activity/setup/AccountSetupBasics.java
@@ -42,7 +42,6 @@ import android.widget.Button;
import android.widget.Toast;
import com.android.email.R;
-import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
@@ -208,7 +207,6 @@ public class AccountSetupBasics extends AccountSetupActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ActivityHelper.debugSetWindowFlags(this);
// Check for forced account creation first, as it comes from an externally-generated
// intent and won't have any SetupData prepared.
@@ -718,7 +716,7 @@ public class AccountSetupBasics extends AccountSetupActivity
public void onCheckSettingsComplete(int result, SetupDataFragment setupData) {
mSetupData = setupData;
if (result == AccountCheckSettingsFragment.CHECK_SETTINGS_OK) {
- AccountSetupOptions.actionOptions(this, mSetupData);
+ AccountSetupFinal.actionFinal(this, mSetupData);
mReportAccountAuthenticatorError = false;
finish();
}
diff --git a/src/com/android/email/activity/setup/AccountSetupFinal.java b/src/com/android/email/activity/setup/AccountSetupFinal.java
new file mode 100644
index 000000000..765fbaf46
--- /dev/null
+++ b/src/com/android/email/activity/setup/AccountSetupFinal.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2014 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.email.activity.setup;
+
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.app.LoaderManager;
+import android.app.ProgressDialog;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.Loader;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.email.R;
+import com.android.email.activity.UiUtilities;
+import com.android.email.provider.AccountBackupRestore;
+import com.android.email.service.EmailServiceUtils;
+import com.android.emailcommon.provider.Account;
+import com.android.emailcommon.provider.EmailContent;
+import com.android.mail.ui.MailAsyncTaskLoader;
+import com.android.mail.utils.LogUtils;
+
+public class AccountSetupFinal extends AccountSetupActivity implements View.OnClickListener {
+ private static final String SAVESTATE_IS_PROCESSING_KEY =
+ "com.android.email.AccountSetupFinal.is_processing";
+ private static final String SAVESTATE_STATE = "com.android.email.AccountSetupFinal.state";
+
+ private static final String ACCOUNT_CREATION_FRAGMENT_TAG = "AccountCreationFragment";
+ private static final String ACCOUNT_FINALIZE_FRAGMENT_TAG = "AccountFinalizeFragment";
+
+ private static final String CREATE_ACCOUNT_DIALOG_TAG = "CreateAccountDialog";
+
+ private static final String CONTENT_FRAGMENT_TAG = "AccountSetupContentFragment";
+
+ private static final int STATE_OPTIONS = 0;
+ private static final int STATE_NAMES = 1;
+ private int mState = STATE_OPTIONS;
+
+ private boolean mIsProcessing = false;
+
+ private Button mNextButton;
+
+ public static void actionFinal(Activity fromActivity, SetupDataFragment setupData) {
+ final Intent intent = new ForwardingIntent(fromActivity, AccountSetupFinal.class);
+ intent.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupData);
+ fromActivity.startActivity(intent);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.account_setup);
+
+ if (savedInstanceState != null) {
+ mIsProcessing = savedInstanceState.getBoolean(SAVESTATE_IS_PROCESSING_KEY, false);
+ mState = savedInstanceState.getInt(SAVESTATE_STATE, STATE_OPTIONS);
+ } else {
+ // If we're not restoring from a previous state, we want to configure the initial screen
+ mState = STATE_OPTIONS;
+ updateHeadline();
+ updateContentFragment();
+ }
+
+ UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
+ mNextButton = UiUtilities.getView(this, R.id.next);
+ mNextButton.setOnClickListener(this);
+
+ if (!mIsProcessing
+ && mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
+ // If we are just visiting here to fill in details, exit immediately
+ getFragmentManager().executePendingTransactions();
+ initiateAccountCreation();
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(SAVESTATE_IS_PROCESSING_KEY, mIsProcessing);
+ }
+
+ /**
+ * Set the headline text according to mState.
+ */
+ private void updateHeadline() {
+ TextView headlineView = UiUtilities.getView(this, R.id.headline);
+ switch (mState) {
+ case STATE_OPTIONS:
+ headlineView.setText(R.string.account_setup_options_headline);
+ break;
+ case STATE_NAMES:
+ headlineView.setText(R.string.account_setup_names_headline);
+ break;
+ }
+ }
+
+ /**
+ * Swap in the new fragment according to mState. This pushes the current fragment onto the back
+ * stack, so only call it once per transition.
+ */
+ private void updateContentFragment() {
+ final Fragment f;
+ switch (mState) {
+ case STATE_OPTIONS:
+ f = new AccountSetupOptionsFragment();
+ break;
+ case STATE_NAMES:
+ f = new AccountSetupNamesFragment();
+ break;
+ default:
+ throw new IllegalStateException("Unknown state " + mState);
+ }
+ final FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.replace(R.id.setup_fragment_container, f, CONTENT_FRAGMENT_TAG);
+ ft.addToBackStack(null);
+ ft.commit();
+ }
+
+ /**
+ * Retrieve the current content fragment
+ * @return The content fragment or null if it wasn't found for some reason
+ */
+ private Fragment getContentFragment() {
+ return getFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG);
+ }
+
+ /**
+ * Main choreography function to handle moving forward through scenes. Moving back should be
+ * generally handled for us by the back stack
+ */
+ protected void proceed() {
+ mIsProcessing = false;
+ setNextButtonEnabled(true);
+
+ switch (mState) {
+ case STATE_OPTIONS:
+ mState = STATE_NAMES;
+ updateHeadline();
+ updateContentFragment();
+ if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
+ getFragmentManager().executePendingTransactions();
+ initiateAccountFinalize();
+ }
+ break;
+ case STATE_NAMES:
+ finishActivity();
+ break;
+ }
+ }
+
+ /**
+ * Block the back key if we are currently processing the "next" key"
+ */
+ @Override
+ public void onBackPressed() {
+ if (mIsProcessing) {
+ return;
+ }
+ if (mState == STATE_NAMES) {
+ finishActivity();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ private void finishActivity() {
+ if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_NO_ACCOUNTS) {
+ AccountSetupBasics.actionAccountCreateFinishedWithResult(this);
+ } else if (mSetupData.getFlowMode() != SetupDataFragment.FLOW_MODE_NORMAL) {
+ AccountSetupBasics.actionAccountCreateFinishedAccountFlow(this);
+ } else {
+ final Account account = mSetupData.getAccount();
+ if (account != null) {
+ AccountSetupBasics.actionAccountCreateFinished(this, account);
+ }
+ }
+ finish();
+ }
+
+ /**
+ * Respond to clicks in the "Next" or "Previous" buttons
+ */
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.next:
+ // Debounce touches
+ if (!mIsProcessing) {
+ switch (mState) {
+ case STATE_OPTIONS:
+ initiateAccountCreation();
+ break;
+ case STATE_NAMES:
+ initiateAccountFinalize();
+ break;
+ }
+ setNextButtonEnabled(false);
+ }
+ break;
+ case R.id.previous:
+ onBackPressed();
+ break;
+ }
+ }
+
+ public void setNextButtonEnabled(final boolean enabled) {
+ mNextButton.setEnabled(enabled);
+ }
+
+ /**
+ * Ths is called when the user clicks the "done" button.
+ * It collects the data from the UI, updates the setup account record, and launches a fragment
+ * which handles creating the account in the system and database.
+ */
+ private void initiateAccountCreation() {
+ mIsProcessing = true;
+
+ final Account account = mSetupData.getAccount();
+ if (account.mHostAuthRecv == null) {
+ throw new IllegalStateException("in AccountSetupOptions with null mHostAuthRecv");
+ }
+
+ final AccountSetupOptionsFragment fragment = (AccountSetupOptionsFragment)
+ getContentFragment();
+ if (fragment == null) {
+ throw new IllegalStateException("Fragment missing!");
+ }
+
+ account.setDisplayName(account.getEmailAddress());
+ int newFlags = account.getFlags() & ~(Account.FLAGS_BACKGROUND_ATTACHMENTS);
+ final EmailServiceUtils.EmailServiceInfo serviceInfo =
+ EmailServiceUtils.getServiceInfo(getApplicationContext(),
+ account.mHostAuthRecv.mProtocol);
+ if (serviceInfo.offerAttachmentPreload && fragment.getBackgroundAttachmentsValue()) {
+ newFlags |= Account.FLAGS_BACKGROUND_ATTACHMENTS;
+ }
+ account.setFlags(newFlags);
+ account.setSyncInterval(fragment.getCheckFrequencyValue());
+ final Integer syncWindowValue = fragment.getAccountSyncWindowValue();
+ if (syncWindowValue != null) {
+ account.setSyncLookback(syncWindowValue);
+ }
+
+ // Finish setting up the account, and commit it to the database
+ if (mSetupData.getPolicy() != null) {
+ account.mFlags |= Account.FLAGS_SECURITY_HOLD;
+ account.mPolicy = mSetupData.getPolicy();
+ }
+
+ // Finally, write the completed account (for the first time) and then
+ // install it into the Account manager as well. These are done off-thread.
+ // The account manager will report back via the callback, which will take us to
+ // the next operations.
+ final boolean syncEmail = fragment.getSyncEmailValue();
+ final boolean syncCalendar = serviceInfo.syncCalendar && fragment.getSyncCalendarValue();
+ final boolean syncContacts = serviceInfo.syncContacts && fragment.getSyncContactsValue();
+ final boolean enableNotifications = fragment.getNotifyValue();
+
+ final Fragment f = AccountCreationFragment.newInstance(account, syncEmail, syncCalendar,
+ syncContacts, enableNotifications);
+ final FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.add(f, ACCOUNT_CREATION_FRAGMENT_TAG);
+ ft.commit();
+
+ showCreateAccountDialog();
+ }
+
+ /**
+ * Called by the account creation fragment after it has completed.
+ * We do a small amount of work here before moving on to the next state.
+ */
+ public void proceedFromAccountCreationFragment() {
+ destroyAccountCreationFragment();
+ // If the account manager initiated the creation, and success was not reported,
+ // then we assume that we're giving up (for any reason) - report failure.
+ final AccountAuthenticatorResponse authenticatorResponse =
+ mSetupData.getAccountAuthenticatorResponse();
+ if (authenticatorResponse != null) {
+ authenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
+ mSetupData.setAccountAuthenticatorResponse(null);
+ }
+ proceed();
+ }
+
+ public void destroyAccountCreationFragment() {
+ dismissCreateAccountDialog();
+
+ final Fragment f = getFragmentManager().findFragmentByTag(ACCOUNT_CREATION_FRAGMENT_TAG);
+ if (f == null) {
+ LogUtils.wtf(LogUtils.TAG, "Couldn't find AccountCreationFragment to destroy");
+ }
+ final FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.remove(f);
+ ft.commit();
+ }
+
+
+ public static class CreateAccountDialogFragment extends DialogFragment {
+ CreateAccountDialogFragment() {}
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ /// Show "Creating account..." dialog
+ final ProgressDialog d = new ProgressDialog(getActivity());
+ d.setIndeterminate(true);
+ d.setMessage(getString(R.string.account_setup_creating_account_msg));
+ return d;
+ }
+ }
+
+ protected void showCreateAccountDialog() {
+ new CreateAccountDialogFragment().show(getFragmentManager(), CREATE_ACCOUNT_DIALOG_TAG);
+ }
+
+ protected void dismissCreateAccountDialog() {
+ final DialogFragment f = (DialogFragment)
+ getFragmentManager().findFragmentByTag(CREATE_ACCOUNT_DIALOG_TAG);
+ if (f != null) {
+ f.dismiss();
+ }
+ }
+
+ public static class CreateAccountErrorDialogFragment extends DialogFragment
+ implements DialogInterface.OnClickListener {
+ public CreateAccountErrorDialogFragment() {}
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final String message = getString(R.string.account_setup_failed_dlg_auth_message,
+ R.string.system_account_create_failed);
+
+ return new AlertDialog.Builder(getActivity())
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setTitle(getString(R.string.account_setup_failed_dlg_title))
+ .setMessage(message)
+ .setCancelable(true)
+ .setPositiveButton(
+ getString(R.string.account_setup_failed_dlg_edit_details_action), this)
+ .create();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ getActivity().finish();
+ }
+ }
+
+ /**
+ * This is called if MailService.setupAccountManagerAccount() fails for some reason
+ */
+ protected void showCreateAccountErrorDialog() {
+ new CreateAccountErrorDialogFragment().show(getFragmentManager(), null);
+ }
+
+ private void initiateAccountFinalize() {
+ mIsProcessing = true;
+
+ AccountSetupNamesFragment fragment = (AccountSetupNamesFragment) getContentFragment();
+ // Update account object from UI
+ final Account account = mSetupData.getAccount();
+ final String description = fragment.getDescription();
+ if (!TextUtils.isEmpty(description)) {
+ account.setDisplayName(description);
+ }
+ account.setSenderName(fragment.getSenderName());
+
+ final Fragment f = AccountFinalizeFragment.newInstance(account);
+ final FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.add(f, ACCOUNT_FINALIZE_FRAGMENT_TAG);
+ ft.commit();
+ }
+
+
+ private static class AccountFinalizeFragment extends Fragment {
+ private static final String ACCOUNT_TAG = "account";
+
+ private static final int FINAL_ACCOUNT_TASK_LOADER_ID = 0;
+
+ private Context mAppContext;
+
+ public static AccountFinalizeFragment newInstance(Account account) {
+ final AccountFinalizeFragment f = new AccountFinalizeFragment();
+ final Bundle args = new Bundle(1);
+ args.putParcelable(ACCOUNT_TAG, account);
+ f.setArguments(args);
+ return f;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mAppContext = getActivity().getApplicationContext();
+
+ setRetainInstance(true);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ getLoaderManager().initLoader(FINAL_ACCOUNT_TASK_LOADER_ID, getArguments(),
+ new LoaderManager.LoaderCallbacks() {
+ @Override
+ public Loader onCreateLoader(int id, Bundle args) {
+ final Account accountArg = args.getParcelable(ACCOUNT_TAG);
+ return new FinalSetupTaskLoader(mAppContext, accountArg);
+ }
+
+ @Override
+ public void onLoadFinished(Loader loader, Boolean success) {
+ if (success && isResumed()) {
+ AccountSetupFinal activity = (AccountSetupFinal) getActivity();
+ activity.finishActivity();
+ }
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {
+ }
+ });
+ }
+
+ /**
+ * Final account setup work is handled in this Loader:
+ * Commit final values to provider
+ * Trigger account backup
+ */
+ private static class FinalSetupTaskLoader extends MailAsyncTaskLoader {
+
+ private final Account mAccount;
+
+ public FinalSetupTaskLoader(Context context, Account account) {
+ super(context);
+ mAccount = account;
+ }
+
+ Account getAccount() {
+ return mAccount;
+ }
+
+ @Override
+ public Boolean loadInBackground() {
+ // Update the account in the database
+ final ContentValues cv = new ContentValues();
+ cv.put(EmailContent.AccountColumns.DISPLAY_NAME, mAccount.getDisplayName());
+ cv.put(EmailContent.AccountColumns.SENDER_NAME, mAccount.getSenderName());
+ mAccount.update(getContext(), cv);
+
+ // Update the backup (side copy) of the accounts
+ AccountBackupRestore.backup(getContext());
+
+ return true;
+ }
+
+ @Override
+ protected void onDiscardResult(Boolean result) {}
+ }
+ }
+}
diff --git a/src/com/android/email/activity/setup/AccountSetupIncoming.java b/src/com/android/email/activity/setup/AccountSetupIncoming.java
index 6b8c592cf..10a5d2ce8 100644
--- a/src/com/android/email/activity/setup/AccountSetupIncoming.java
+++ b/src/com/android/email/activity/setup/AccountSetupIncoming.java
@@ -25,7 +25,6 @@ import android.view.View.OnClickListener;
import android.widget.Button;
import com.android.email.R;
-import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.service.EmailServiceUtils;
import com.android.email.service.EmailServiceUtils.EmailServiceInfo;
@@ -63,7 +62,6 @@ public class AccountSetupIncoming extends AccountSetupActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ActivityHelper.debugSetWindowFlags(this);
final HostAuth hostAuth = mSetupData.getAccount().mHostAuthRecv;
mServiceInfo = EmailServiceUtils.getServiceInfo(this, hostAuth.mProtocol);
@@ -196,7 +194,7 @@ public class AccountSetupIncoming extends AccountSetupActivity
if (mServiceInfo.usesSmtp) {
AccountSetupOutgoing.actionOutgoingSettings(this, mSetupData);
} else {
- AccountSetupOptions.actionOptions(this, mSetupData);
+ AccountSetupFinal.actionFinal(this, mSetupData);
finish();
}
}
diff --git a/src/com/android/email/activity/setup/AccountSetupNames.java b/src/com/android/email/activity/setup/AccountSetupNames.java
deleted file mode 100644
index 31ed9d68f..000000000
--- a/src/com/android/email/activity/setup/AccountSetupNames.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2008 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.email.activity.setup;
-
-import android.app.Activity;
-import android.app.LoaderManager;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-
-import com.android.email.R;
-import com.android.email.activity.ActivityHelper;
-import com.android.email.activity.UiUtilities;
-import com.android.email.provider.AccountBackupRestore;
-import com.android.emailcommon.provider.Account;
-import com.android.emailcommon.provider.EmailContent.AccountColumns;
-import com.android.mail.ui.MailAsyncTaskLoader;
-
-/**
- * Final screen of setup process. Collect account nickname and/or username.
- */
-public class AccountSetupNames extends AccountSetupActivity {
- private static final int REQUEST_SECURITY = 0;
-
- private Button mNextButton;
- private static final String SAVESTATE_ISCOMPLETING_TAG = "isCompleting";
- private boolean mIsCompleting = false;
- private static final int FINAL_ACCOUNT_TASK_LOADER_ID = 0;
- private static final String ACCOUNT_TAG = "account";
- private Bundle mFinalAccountTaskLoaderArgs;
- private LoaderManager.LoaderCallbacks mFinalAccountTaskLoaderCallbacks;
-
- public static void actionSetNames(Activity fromActivity, SetupDataFragment setupData) {
- ForwardingIntent intent = new ForwardingIntent(fromActivity, AccountSetupNames.class);
- intent.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupData);
- fromActivity.startActivity(intent);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (savedInstanceState != null) {
- mIsCompleting = savedInstanceState.getBoolean(SAVESTATE_ISCOMPLETING_TAG);
- }
-
- ActivityHelper.debugSetWindowFlags(this);
- setContentView(R.layout.account_setup_names);
-
- mNextButton = UiUtilities.getView(this, R.id.next);
- mNextButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- onNext();
- }
- });
-
- // Proceed immediately if in account creation mode
- if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
- onNext();
- }
-
- if (mIsCompleting) {
- startFinalSetupTaskLoader(getSetupData().getAccount());
- }
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putBoolean(SAVESTATE_ISCOMPLETING_TAG, mIsCompleting);
- }
-
- /**
- * Block the back key if we are currently processing the "next" key"
- */
- @Override
- public void onBackPressed() {
- if (!mIsCompleting) {
- finishActivity();
- }
- }
-
- private void finishActivity() {
- if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_NO_ACCOUNTS) {
- AccountSetupBasics.actionAccountCreateFinishedWithResult(this);
- } else if (mSetupData.getFlowMode() != SetupDataFragment.FLOW_MODE_NORMAL) {
- AccountSetupBasics.actionAccountCreateFinishedAccountFlow(this);
- } else {
- final Account account = mSetupData.getAccount();
- if (account != null) {
- AccountSetupBasics.actionAccountCreateFinished(this, account);
- }
- }
- finish();
- }
-
- public void setNextButtonEnabled(boolean enabled) {
- mNextButton.setEnabled(enabled);
- }
-
- /**
- * After clicking the next button, we'll start an async task to commit the data
- * and other steps to finish the creation of the account.
- */
- private void onNext() {
- mNextButton.setEnabled(false); // Protect against double-tap.
- mIsCompleting = true;
-
- AccountSetupNamesFragment fragment = (AccountSetupNamesFragment)
- getFragmentManager().findFragmentById(R.id.names_fragment);
- // Update account object from UI
- final Account account = mSetupData.getAccount();
- final String description = fragment.getDescription();
- if (!TextUtils.isEmpty(description)) {
- account.setDisplayName(description);
- }
- account.setSenderName(fragment.getSenderName());
-
- startFinalSetupTaskLoader(account);
- }
-
- private void startFinalSetupTaskLoader(Account account) {
- if (mFinalAccountTaskLoaderArgs == null) {
- mFinalAccountTaskLoaderArgs = new Bundle(1);
- mFinalAccountTaskLoaderArgs.putParcelable(ACCOUNT_TAG, account);
-
- final Context appContext = getApplicationContext();
- mFinalAccountTaskLoaderCallbacks = new LoaderManager.LoaderCallbacks() {
- @Override
- public Loader onCreateLoader(int id, Bundle args) {
- final Account accountArg = args.getParcelable(ACCOUNT_TAG);
- return new FinalSetupTaskLoader(appContext, accountArg);
- }
-
- @Override
- public void onLoadFinished(Loader loader, Boolean isSecurityHold) {
- if (isSecurityHold) {
- final FinalSetupTaskLoader finalSetupTaskLoader =
- (FinalSetupTaskLoader)loader;
- final Intent i = AccountSecurity.actionUpdateSecurityIntent(
- appContext, finalSetupTaskLoader.getAccount().mId, false);
- startActivityForResult(i, REQUEST_SECURITY);
- } else {
- finishActivity();
- }
- }
-
- @Override
- public void onLoaderReset(Loader loader) {}
- };
- }
- getLoaderManager().initLoader(FINAL_ACCOUNT_TASK_LOADER_ID, mFinalAccountTaskLoaderArgs,
- mFinalAccountTaskLoaderCallbacks);
- }
-
- /**
- * Final account setup work is handled in this AsyncTask:
- * Commit final values to provider
- * Trigger account backup
- * Check for security hold
- *
- * When this completes, we return to UI thread for the following steps:
- * If security hold, dispatch to AccountSecurity activity
- * Otherwise, return to AccountSetupBasics for conclusion.
- *
- * TODO: If there was *any* indication that security might be required, we could at least
- * force the DeviceAdmin activation step, without waiting for the initial sync/handshake
- * to fail.
- * TODO: If the user doesn't update the security, don't go to the MessageList.
- */
- private static class FinalSetupTaskLoader extends MailAsyncTaskLoader {
-
- private final Account mAccount;
-
- public FinalSetupTaskLoader(Context context, Account account) {
- super(context);
- mAccount = account;
- }
-
- Account getAccount() {
- return mAccount;
- }
-
- @Override
- public Boolean loadInBackground() {
- // Update the account in the database
- final ContentValues cv = new ContentValues();
- cv.put(AccountColumns.DISPLAY_NAME, mAccount.getDisplayName());
- cv.put(AccountColumns.SENDER_NAME, mAccount.getSenderName());
- mAccount.update(getContext(), cv);
-
- // Update the backup (side copy) of the accounts
- AccountBackupRestore.backup(getContext());
-
- return Account.isSecurityHold(getContext(), mAccount.mId);
- }
-
- @Override
- protected void onDiscardResult(Boolean result) {}
- }
-
- /**
- * Handle the eventual result from the security update activity
- *
- * TODO: If the user doesn't update the security, don't go to the MessageList.
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_SECURITY:
- finishActivity();
- }
- super.onActivityResult(requestCode, resultCode, data);
- }
-
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupNamesFragment.java b/src/com/android/email/activity/setup/AccountSetupNamesFragment.java
index 458caf60c..490be6ebd 100644
--- a/src/com/android/email/activity/setup/AccountSetupNamesFragment.java
+++ b/src/com/android/email/activity/setup/AccountSetupNamesFragment.java
@@ -158,7 +158,7 @@ public class AccountSetupNamesFragment extends Fragment {
mName.setError(null);
}
}
- final AccountSetupNames activity = (AccountSetupNames) getActivity();
+ final AccountSetupFinal activity = (AccountSetupFinal) getActivity();
activity.setNextButtonEnabled(enableNextButton);
}
diff --git a/src/com/android/email/activity/setup/AccountSetupOptions.java b/src/com/android/email/activity/setup/AccountSetupOptions.java
deleted file mode 100644
index 96478a91f..000000000
--- a/src/com/android/email/activity/setup/AccountSetupOptions.java
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (C) 2008 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.email.activity.setup;
-
-import android.accounts.AccountAuthenticatorResponse;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.app.LoaderManager;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.Loader;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.view.View;
-import android.view.View.OnClickListener;
-
-import com.android.email.R;
-import com.android.email.activity.ActivityHelper;
-import com.android.email.activity.UiUtilities;
-import com.android.email.service.EmailServiceUtils;
-import com.android.email2.ui.MailActivityEmail;
-import com.android.emailcommon.Logging;
-import com.android.emailcommon.provider.Account;
-import com.android.emailcommon.service.EmailServiceProxy;
-import com.android.mail.preferences.AccountPreferences;
-import com.android.mail.ui.MailAsyncTaskLoader;
-import com.android.mail.utils.LogUtils;
-
-import java.io.IOException;
-
-public class AccountSetupOptions extends AccountSetupActivity implements OnClickListener {
- private static final String EXTRA_IS_PROCESSING_KEY = "com.android.email.is_processing";
- private static final String ACCOUNT_FINALIZE_FRAGMENT_TAG = "AccountFinalizeFragment";
-
- private boolean mDonePressed = false;
- private boolean mIsProcessing = false;
-
- public static final int REQUEST_CODE_ACCEPT_POLICIES = 1;
-
-
- public static void actionOptions(Activity fromActivity, SetupDataFragment setupData) {
- final Intent intent = new ForwardingIntent(fromActivity, AccountSetupOptions.class);
- intent.putExtra(SetupDataFragment.EXTRA_SETUP_DATA, setupData);
- fromActivity.startActivity(intent);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ActivityHelper.debugSetWindowFlags(this);
- setContentView(R.layout.account_setup_options);
-
- UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
- UiUtilities.getView(this, R.id.next).setOnClickListener(this);
-
-
-
- mIsProcessing = savedInstanceState != null &&
- savedInstanceState.getBoolean(EXTRA_IS_PROCESSING_KEY, false);
- if (mIsProcessing) {
- // We are already processing, so just show the dialog until we finish
- showCreateAccountDialog();
- } else if (mSetupData.getFlowMode() == SetupDataFragment.FLOW_MODE_FORCE_CREATE) {
- // If we are just visiting here to fill in details, exit immediately
- onDone();
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putBoolean(EXTRA_IS_PROCESSING_KEY, mIsProcessing);
- }
-
- @Override
- public void finish() {
- // If the account manager initiated the creation, and success was not reported,
- // then we assume that we're giving up (for any reason) - report failure.
- final AccountAuthenticatorResponse authenticatorResponse =
- mSetupData.getAccountAuthenticatorResponse();
- if (authenticatorResponse != null) {
- authenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
- mSetupData.setAccountAuthenticatorResponse(null);
- }
- super.finish();
- }
-
- /**
- * Respond to clicks in the "Next" or "Previous" buttons
- */
- @Override
- public void onClick(View view) {
- switch (view.getId()) {
- case R.id.next:
- // Don't allow this more than once (Exchange accounts call an async method
- // before finish()'ing the Activity, which allows this code to potentially be
- // executed multiple times
- if (!mDonePressed) {
- onDone();
- mDonePressed = true;
- }
- break;
- case R.id.previous:
- onBackPressed();
- break;
- }
- }
-
- /**
- * Ths is called when the user clicks the "done" button.
- * It collects the data from the UI, updates the setup account record, and commits
- * the account to the database (making it real for the first time.)
- * Finally, we call setupAccountManagerAccount(), which will eventually complete via callback.
- */
- private void onDone() {
- final Account account = mSetupData.getAccount();
- if (account.isSaved()) {
- // Disrupting the normal flow could get us here, but if the account is already
- // saved, we've done this work
- return;
- } else if (account.mHostAuthRecv == null) {
- throw new IllegalStateException("in AccountSetupOptions with null mHostAuthRecv");
- }
-
- final AccountSetupOptionsFragment fragment = (AccountSetupOptionsFragment)
- getFragmentManager().findFragmentById(R.id.options_fragment);
- if (fragment == null) {
- throw new IllegalStateException("Fragment missing!");
- }
-
- mIsProcessing = true;
- account.setDisplayName(account.getEmailAddress());
- int newFlags = account.getFlags() & ~(Account.FLAGS_BACKGROUND_ATTACHMENTS);
- final EmailServiceUtils.EmailServiceInfo serviceInfo =
- EmailServiceUtils.getServiceInfo(getApplicationContext(),
- account.mHostAuthRecv.mProtocol);
- if (serviceInfo.offerAttachmentPreload && fragment.getBackgroundAttachmentsValue()) {
- newFlags |= Account.FLAGS_BACKGROUND_ATTACHMENTS;
- }
- account.setFlags(newFlags);
- account.setSyncInterval(fragment.getCheckFrequencyValue());
- final Integer syncWindowValue = fragment.getAccountSyncWindowValue();
- if (syncWindowValue != null) {
- account.setSyncLookback(syncWindowValue);
- }
-
- // Finish setting up the account, and commit it to the database
- // Set the incomplete flag here to avoid reconciliation issues in ExchangeService
- account.mFlags |= Account.FLAGS_INCOMPLETE;
- if (mSetupData.getPolicy() != null) {
- account.mFlags |= Account.FLAGS_SECURITY_HOLD;
- account.mPolicy = mSetupData.getPolicy();
- }
-
- // Finally, write the completed account (for the first time) and then
- // install it into the Account manager as well. These are done off-thread.
- // The account manager will report back via the callback, which will take us to
- // the next operations.
- final Bundle args = new Bundle(5);
- args.putParcelable(AccountFinalizeFragment.ACCOUNT_TAG, account);
- args.putBoolean(AccountFinalizeFragment.SYNC_EMAIL_TAG, fragment.getSyncEmailValue());
- final boolean calendar = serviceInfo.syncCalendar && fragment.getSyncCalendarValue();
- args.putBoolean(AccountFinalizeFragment.SYNC_CALENDAR_TAG, calendar);
- final boolean contacts = serviceInfo.syncContacts && fragment.getSyncContactsValue();
- args.putBoolean(AccountFinalizeFragment.SYNC_CONTACTS_TAG, contacts);
- args.putBoolean(AccountFinalizeFragment.NOTIFICATIONS_TAG, fragment.getNotifyValue());
-
- final Fragment f = new AccountFinalizeFragment();
- f.setArguments(args);
- final FragmentTransaction ft = getFragmentManager().beginTransaction();
- ft.add(f, ACCOUNT_FINALIZE_FRAGMENT_TAG);
- ft.commit();
-
- showCreateAccountDialog();
- }
-
- public void destroyAccountFinalizeFragment() {
- final Fragment f = getFragmentManager().findFragmentByTag(ACCOUNT_FINALIZE_FRAGMENT_TAG);
- if (f == null) {
- LogUtils.wtf(LogUtils.TAG, "Couldn't find AccountFinalizeFragment to destroy");
- }
- final FragmentTransaction ft = getFragmentManager().beginTransaction();
- ft.remove(f);
- ft.commit();
- }
-
- /**
- * This retained headless fragment acts as a container for the multi-step task of creating the
- * AccountManager account and saving our account object to the database, as well as some misc
- * related background tasks.
- *
- * TODO: move this to a separate file, probably
- */
- public static class AccountFinalizeFragment extends Fragment {
- public static final String ACCOUNT_TAG = "account";
- public static final String SYNC_EMAIL_TAG = "email";
- public static final String SYNC_CALENDAR_TAG = "calendar";
- public static final String SYNC_CONTACTS_TAG = "contacts";
- public static final String NOTIFICATIONS_TAG = "notifications";
-
- private static final String SAVESTATE_STAGE = "AccountFinalizeFragment.stage";
- private static final int STAGE_BEFORE_ACCOUNT_SECURITY = 0;
- private static final int STAGE_REFRESHING_ACCOUNT = 1;
- private static final int STAGE_WAITING_FOR_ACCOUNT_SECURITY = 2;
- private static final int STAGE_AFTER_ACCOUNT_SECURITY = 3;
- private int mStage = 0;
-
- private Context mAppContext;
- private final Handler mHandler;
-
- AccountFinalizeFragment() {
- mHandler = new Handler();
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setRetainInstance(true);
- mAppContext = getActivity().getApplicationContext();
- if (savedInstanceState != null) {
- mStage = savedInstanceState.getInt(SAVESTATE_STAGE);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putInt(SAVESTATE_STAGE, mStage);
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- switch (mStage) {
- case STAGE_BEFORE_ACCOUNT_SECURITY:
- kickBeforeAccountSecurityLoader();
- break;
- case STAGE_REFRESHING_ACCOUNT:
- kickRefreshingAccountLoader();
- break;
- case STAGE_WAITING_FOR_ACCOUNT_SECURITY:
- // TODO: figure out when we might get here and what to do if we do
- break;
- case STAGE_AFTER_ACCOUNT_SECURITY:
- kickAfterAccountSecurityLoader();
- break;
- }
- }
-
- private void kickBeforeAccountSecurityLoader() {
- final LoaderManager loaderManager = getLoaderManager();
-
- loaderManager.destroyLoader(STAGE_REFRESHING_ACCOUNT);
- loaderManager.destroyLoader(STAGE_AFTER_ACCOUNT_SECURITY);
- loaderManager.initLoader(STAGE_BEFORE_ACCOUNT_SECURITY, getArguments(),
- new BeforeAccountSecurityCallbacks());
- }
-
- private void kickRefreshingAccountLoader() {
- final LoaderManager loaderManager = getLoaderManager();
-
- loaderManager.destroyLoader(STAGE_BEFORE_ACCOUNT_SECURITY);
- loaderManager.destroyLoader(STAGE_AFTER_ACCOUNT_SECURITY);
- loaderManager.initLoader(STAGE_REFRESHING_ACCOUNT, getArguments(),
- new RefreshAccountCallbacks());
- }
-
- private void kickAfterAccountSecurityLoader() {
- final LoaderManager loaderManager = getLoaderManager();
-
- loaderManager.destroyLoader(STAGE_BEFORE_ACCOUNT_SECURITY);
- loaderManager.destroyLoader(STAGE_REFRESHING_ACCOUNT);
- loaderManager.initLoader(STAGE_AFTER_ACCOUNT_SECURITY, getArguments(),
- new AfterAccountSecurityCallbacks());
- }
-
- private class BeforeAccountSecurityCallbacks
- implements LoaderManager.LoaderCallbacks {
- public BeforeAccountSecurityCallbacks() {}
-
- @Override
- public Loader onCreateLoader(int id, Bundle args) {
- final Account account = args.getParcelable(ACCOUNT_TAG);
- final boolean email = args.getBoolean(SYNC_EMAIL_TAG);
- final boolean calendar = args.getBoolean(SYNC_CALENDAR_TAG);
- final boolean contacts = args.getBoolean(SYNC_CONTACTS_TAG);
- final boolean notificationsEnabled = args.getBoolean(NOTIFICATIONS_TAG);
-
- /**
- * Task loader returns true if we created the account, false if we bailed out.
- */
- return new MailAsyncTaskLoader(mAppContext) {
- @Override
- protected void onDiscardResult(Boolean result) {}
-
- @Override
- public Boolean loadInBackground() {
- AccountSettingsUtils.commitSettings(mAppContext, account);
- final AccountManagerFuture future =
- EmailServiceUtils.setupAccountManagerAccount(mAppContext, account,
- email, calendar, contacts, null);
-
- boolean createSuccess = false;
- try {
- future.getResult();
- createSuccess = true;
- } catch (OperationCanceledException e) {
- LogUtils.d(Logging.LOG_TAG, "addAccount was canceled");
- } catch (IOException e) {
- LogUtils.d(Logging.LOG_TAG, "addAccount failed: " + e);
- } catch (AuthenticatorException e) {
- LogUtils.d(Logging.LOG_TAG, "addAccount failed: " + e);
- }
- if (!createSuccess) {
- return false;
- }
- // We can move the notification setting to the inbox FolderPreferences
- // later, once we know what the inbox is
- new AccountPreferences(mAppContext, account.getEmailAddress())
- .setDefaultInboxNotificationsEnabled(notificationsEnabled);
-
- // Now that AccountManager account creation is complete, clear the
- // INCOMPLETE flag
- account.mFlags &= ~Account.FLAGS_INCOMPLETE;
- AccountSettingsUtils.commitSettings(mAppContext, account);
-
- return true;
- }
- };
- }
-
- @Override
- public void onLoadFinished(Loader loader, Boolean success) {
- if (success == null || !isResumed()) {
- return;
- }
- if (success) {
- mStage = STAGE_REFRESHING_ACCOUNT;
- kickRefreshingAccountLoader();
- } else {
- final AccountSetupOptions activity = (AccountSetupOptions)getActivity();
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (!isResumed()) {
- return;
- }
- // Can't do this from within onLoadFinished
- activity.destroyAccountFinalizeFragment();
- activity.showCreateAccountErrorDialog();
- }
- });
- }
- }
-
- @Override
- public void onLoaderReset(Loader loader) {}
- }
-
- private class RefreshAccountCallbacks implements LoaderManager.LoaderCallbacks {
-
- @Override
- public Loader onCreateLoader(int id, Bundle args) {
- final Account account = args.getParcelable(ACCOUNT_TAG);
- return new MailAsyncTaskLoader(mAppContext) {
- @Override
- protected void onDiscardResult(Account result) {}
-
- @Override
- public Account loadInBackground() {
- account.refresh(mAppContext);
- return account;
- }
- };
- }
-
- @Override
- public void onLoadFinished(Loader loader, Account account) {
- if (account == null || !isResumed()) {
- return;
- }
-
- getArguments().putParcelable(ACCOUNT_TAG, account);
-
- if ((account.mFlags & Account.FLAGS_SECURITY_HOLD) != 0) {
- final Intent intent = AccountSecurity
- .actionUpdateSecurityIntent(getActivity(), account.mId, false);
- startActivityForResult(intent,
- AccountSetupOptions.REQUEST_CODE_ACCEPT_POLICIES);
- mStage = STAGE_WAITING_FOR_ACCOUNT_SECURITY;
- } else {
- mStage = STAGE_AFTER_ACCOUNT_SECURITY;
- kickAfterAccountSecurityLoader();
- }
- }
-
- @Override
- public void onLoaderReset(Loader loader) {}
- }
-
- private class AfterAccountSecurityCallbacks
- implements LoaderManager.LoaderCallbacks {
- @Override
- public Loader onCreateLoader(int id, Bundle args) {
- final Account account = args.getParcelable(ACCOUNT_TAG);
- return new MailAsyncTaskLoader(mAppContext) {
- @Override
- protected void onDiscardResult(Account result) {}
-
- @Override
- public Account loadInBackground() {
- // Clear the security hold flag now
- account.mFlags &= ~Account.FLAGS_SECURITY_HOLD;
- AccountSettingsUtils.commitSettings(mAppContext, account);
- // Start up services based on new account(s)
- MailActivityEmail.setServicesEnabledSync(mAppContext);
- EmailServiceUtils
- .startService(mAppContext, account.mHostAuthRecv.mProtocol);
- return account;
- }
- };
- }
-
- @Override
- public void onLoadFinished(Loader loader, Account account) {
- if (account == null || !isResumed()) {
- return;
- }
-
- // Move to final setup screen
- AccountSetupOptions activity = (AccountSetupOptions) getActivity();
- activity.getSetupData().setAccount(account);
- activity.proceed();
-
- // Update the folder list (to get our starting folders, e.g. Inbox)
- final EmailServiceProxy proxy = EmailServiceUtils.getServiceForAccount(activity,
- account.mId);
- try {
- proxy.updateFolderList(account.mId);
- } catch (RemoteException e) {
- // It's all good
- }
- }
-
- @Override
- public void onLoaderReset(Loader loader) {}
- }
-
- /**
- * This is called after the AccountSecurity activity completes.
- */
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- mStage = STAGE_AFTER_ACCOUNT_SECURITY;
- // onResume() will be called immediately after this to kick the next loader
- }
- }
-
- public static class CreateAccountDialogFragment extends DialogFragment {
- CreateAccountDialogFragment() {}
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- /// Show "Creating account..." dialog
- final ProgressDialog d = new ProgressDialog(getActivity());
- d.setIndeterminate(true);
- d.setMessage(getString(R.string.account_setup_creating_account_msg));
- return d;
- }
- }
-
- private void showCreateAccountDialog() {
- new CreateAccountDialogFragment().show(getFragmentManager(), null);
- }
-
- public static class CreateAccountErrorDialogFragment extends DialogFragment
- implements DialogInterface.OnClickListener {
- public CreateAccountErrorDialogFragment() {}
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final String message = getString(R.string.account_setup_failed_dlg_auth_message,
- R.string.system_account_create_failed);
-
- return new AlertDialog.Builder(getActivity())
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setTitle(getString(R.string.account_setup_failed_dlg_title))
- .setMessage(message)
- .setCancelable(true)
- .setPositiveButton(
- getString(R.string.account_setup_failed_dlg_edit_details_action), this)
- .create();
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- getActivity().finish();
- }
- }
-
- /**
- * This is called if MailService.setupAccountManagerAccount() fails for some reason
- */
- private void showCreateAccountErrorDialog() {
- new CreateAccountErrorDialogFragment().show(getFragmentManager(), null);
- }
-
- /**
- * Background account creation has completed, so proceed to the next screen.
- */
- private void proceed() {
- AccountSetupNames.actionSetNames(this, mSetupData);
- finish();
- }
-}
diff --git a/src/com/android/email/activity/setup/AccountSetupOutgoing.java b/src/com/android/email/activity/setup/AccountSetupOutgoing.java
index c7570cf7c..e30ccd9fa 100644
--- a/src/com/android/email/activity/setup/AccountSetupOutgoing.java
+++ b/src/com/android/email/activity/setup/AccountSetupOutgoing.java
@@ -17,9 +17,7 @@
package com.android.email.activity.setup;
import com.android.email.R;
-import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
-import com.android.emailcommon.provider.Account;
import android.app.Activity;
import android.app.FragmentTransaction;
@@ -51,7 +49,6 @@ public class AccountSetupOutgoing extends AccountSetupActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ActivityHelper.debugSetWindowFlags(this);
setContentView(R.layout.account_setup_outgoing);
mFragment = (AccountSetupOutgoingFragment)
@@ -113,7 +110,7 @@ public class AccountSetupOutgoing extends AccountSetupActivity
public void onCheckSettingsComplete(int result, SetupDataFragment setupData) {
mSetupData = setupData;
if (result == AccountCheckSettingsFragment.CHECK_SETTINGS_OK) {
- AccountSetupOptions.actionOptions(this, mSetupData);
+ AccountSetupFinal.actionFinal(this, mSetupData);
finish();
}
}
diff --git a/tests/src/com/android/email/activity/setup/AccountSetupOptionsTests.java b/tests/src/com/android/email/activity/setup/AccountSetupFinalTests.java
similarity index 91%
rename from tests/src/com/android/email/activity/setup/AccountSetupOptionsTests.java
rename to tests/src/com/android/email/activity/setup/AccountSetupFinalTests.java
index 300e96ea4..b1f74e2ad 100644
--- a/tests/src/com/android/email/activity/setup/AccountSetupOptionsTests.java
+++ b/tests/src/com/android/email/activity/setup/AccountSetupFinalTests.java
@@ -27,9 +27,6 @@ import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import com.android.email.R;
-import com.android.email.activity.setup.AccountSetupOptions;
-import com.android.email.activity.setup.SetupDataFragment;
-import com.android.email.activity.setup.SpinnerOption;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
@@ -38,19 +35,19 @@ import java.net.URISyntaxException;
/**
* Tests of basic UI logic in the AccountSetupOptions screen.
* You can run this entire test case with:
- * runtest -c com.android.email.activity.setup.AccountSetupOptionsTests email
+ * runtest -c com.android.email.activity.setup.AccountSetupFinalTests email
*/
@Suppress
@MediumTest
-public class AccountSetupOptionsTests
- extends ActivityInstrumentationTestCase2 {
+public class AccountSetupFinalTests
+ extends ActivityInstrumentationTestCase2 {
- private AccountSetupOptions mActivity;
+ private AccountSetupFinal mActivity;
private Spinner mCheckFrequencyView;
private CheckBox mBackgroundAttachmentsView;
- public AccountSetupOptionsTests() {
- super(AccountSetupOptions.class);
+ public AccountSetupFinalTests() {
+ super(AccountSetupFinal.class);
}
/**
@@ -157,7 +154,7 @@ public class AccountSetupOptionsTests
for (int i = 0; i < sa.getCount(); ++i) {
SpinnerOption so = (SpinnerOption) sa.getItem(i);
- if (so != null && ((Integer)so.value).intValue() == value) {
+ if (so != null && ((Integer)so.value) == value) {
return true;
}
}