AccountSetupBasics.java revision 12b82d9374947c9268217f45befe8a74bd9b60d7
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.email.activity.setup; 18 19import com.android.email.EmailAddressValidator; 20import com.android.email.R; 21import com.android.email.VendorPolicyLoader; 22import com.android.email.activity.ActivityHelper; 23import com.android.email.activity.UiUtilities; 24import com.android.email.activity.Welcome; 25import com.android.email.activity.setup.AccountSettingsUtils.Provider; 26import com.android.email.mail.Store; 27import com.android.emailcommon.Logging; 28import com.android.emailcommon.provider.EmailContent; 29import com.android.emailcommon.provider.EmailContent.Account; 30import com.android.emailcommon.provider.HostAuth; 31import com.android.emailcommon.utility.Utility; 32 33import android.accounts.AccountAuthenticatorResponse; 34import android.accounts.AccountManager; 35import android.app.Activity; 36import android.app.ActivityManager; 37import android.app.AlertDialog; 38import android.app.Dialog; 39import android.app.DialogFragment; 40import android.app.FragmentTransaction; 41import android.content.Context; 42import android.content.DialogInterface; 43import android.content.Intent; 44import android.os.AsyncTask; 45import android.os.Bundle; 46import android.text.Editable; 47import android.text.TextUtils; 48import android.text.TextWatcher; 49import android.util.Log; 50import android.view.View; 51import android.view.View.OnClickListener; 52import android.widget.Button; 53import android.widget.CheckBox; 54import android.widget.EditText; 55import android.widget.TextView; 56import android.widget.Toast; 57 58import java.net.URISyntaxException; 59import java.util.concurrent.Callable; 60import java.util.concurrent.ExecutionException; 61import java.util.concurrent.FutureTask; 62 63/** 64 * Prompts the user for the email address and password. Also prompts for "Use this account as 65 * default" if this is the 2nd+ account being set up. 66 * 67 * If the domain is well-known, the account is configured fully and checked immediately 68 * using AccountCheckSettingsFragment. If this succeeds we proceed directly to AccountSetupOptions. 69 * 70 * If the domain is not known, or the user selects Manual setup, we invoke the 71 * AccountSetupAccountType activity where the user can begin to manually configure the account. 72 * 73 * === Support for automated testing == 74 * This activity can also be launched directly via ACTION_CREATE_ACCOUNT. This is intended 75 * only for use by continuous test systems, and is currently only available when 76 * {@link ActivityManager#isRunningInTestHarness()} is set. To use this mode, you must construct 77 * an intent which contains all necessary information to create the account. No connection 78 * checking is done, so the account may or may not actually work. Here is a sample command, for a 79 * gmail account "test_account" with a password of "test_password". 80 * 81 * $ adb shell am start -a com.android.email.CREATE_ACCOUNT \ 82 * -e EMAIL test_account@gmail.com \ 83 * -e USER "Test Account Name" \ 84 * -e INCOMING imap+ssl+://test_account:test_password@imap.gmail.com \ 85 * -e OUTGOING smtp+ssl+://test_account:test_password@smtp.gmail.com 86 * 87 * Note: For accounts that require the full email address in the login, encode the @ as %40. 88 * Note: Exchange accounts that require device security policies cannot be created automatically. 89 */ 90public class AccountSetupBasics extends AccountSetupActivity 91 implements OnClickListener, TextWatcher, AccountCheckSettingsFragment.Callbacks { 92 93 private final static boolean ENTER_DEBUG_SCREEN = true; 94 95 /** 96 * Direct access for forcing account creation 97 * For use by continuous automated test system (e.g. in conjunction with monkey tests) 98 */ 99 private final String ACTION_CREATE_ACCOUNT = "com.android.email.CREATE_ACCOUNT"; 100 private final String EXTRA_CREATE_ACCOUNT_EMAIL = "EMAIL"; 101 private final String EXTRA_CREATE_ACCOUNT_USER = "USER"; 102 private final String EXTRA_CREATE_ACCOUNT_INCOMING = "INCOMING"; 103 private final String EXTRA_CREATE_ACCOUNT_OUTGOING = "OUTGOING"; 104 private final Boolean DEBUG_ALLOW_NON_TEST_HARNESS_CREATION = false; 105 106 private final static String STATE_KEY_PROVIDER = "AccountSetupBasics.provider"; 107 108 // NOTE: If you change this value, confirm that the new interval exists in arrays.xml 109 private final static int DEFAULT_ACCOUNT_CHECK_INTERVAL = 15; 110 111 // Support for UI 112 private TextView mWelcomeView; 113 private EditText mEmailView; 114 private EditText mPasswordView; 115 private CheckBox mDefaultView; 116 private EmailAddressValidator mEmailValidator = new EmailAddressValidator(); 117 private Provider mProvider; 118 private Button mManualButton; 119 private Button mNextButton; 120 private boolean mNextButtonInhibit; 121 private boolean mPaused; 122 private boolean mReportAccountAuthenticatorError; 123 124 // FutureTask to look up the owner 125 FutureTask<String> mOwnerLookupTask; 126 127 public static void actionNewAccount(Activity fromActivity) { 128 SetupData.init(SetupData.FLOW_MODE_NORMAL); 129 fromActivity.startActivity(new Intent(fromActivity, AccountSetupBasics.class)); 130 } 131 132 /** 133 * This generates setup data that can be used to start a self-contained account creation flow 134 * for exchange accounts. 135 */ 136 public static Intent actionSetupExchangeIntent(Context context) { 137 SetupData.init(SetupData.FLOW_MODE_ACCOUNT_MANAGER_EAS); 138 return new Intent(context, AccountSetupBasics.class); 139 } 140 141 /** 142 * This generates setup data that can be used to start a self-contained account creation flow 143 * for pop/imap accounts. 144 */ 145 public static Intent actionSetupPopImapIntent(Context context) { 146 SetupData.init(SetupData.FLOW_MODE_ACCOUNT_MANAGER_POP_IMAP); 147 return new Intent(context, AccountSetupBasics.class); 148 } 149 150 public static void actionAccountCreateFinishedAccountFlow(Activity fromActivity) { 151 Intent i= new Intent(fromActivity, AccountSetupBasics.class); 152 // If we're in the "account flow" (from AccountManager), we want to return to the caller 153 // (in the settings app) 154 SetupData.init(SetupData.FLOW_MODE_RETURN_TO_CALLER); 155 i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 156 fromActivity.startActivity(i); 157 } 158 159 public static void actionAccountCreateFinished(final Activity fromActivity, 160 final long accountId) { 161 Utility.runAsync(new Runnable() { 162 public void run() { 163 Intent i = new Intent(fromActivity, AccountSetupBasics.class); 164 // If we're not in the "account flow" (from AccountManager), we want to show the 165 // message list for the new inbox 166 Account account = Account.restoreAccountWithId(fromActivity, accountId); 167 SetupData.init(SetupData.FLOW_MODE_RETURN_TO_MESSAGE_LIST, account); 168 i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 169 fromActivity.startActivity(i); 170 }}); 171 } 172 173 @Override 174 public void onCreate(Bundle savedInstanceState) { 175 super.onCreate(savedInstanceState); 176 ActivityHelper.debugSetWindowFlags(this); 177 178 // Check for forced account creation first, as it comes from an externally-generated 179 // intent and won't have any SetupData prepared. 180 String action = getIntent().getAction(); 181 if (ACTION_CREATE_ACCOUNT.equals(action)) { 182 SetupData.init(SetupData.FLOW_MODE_FORCE_CREATE); 183 } 184 185 int flowMode = SetupData.getFlowMode(); 186 if (flowMode == SetupData.FLOW_MODE_RETURN_TO_CALLER) { 187 // Return to the caller who initiated account creation 188 finish(); 189 return; 190 } else if (flowMode == SetupData.FLOW_MODE_RETURN_TO_MESSAGE_LIST) { 191 Account account = SetupData.getAccount(); 192 if (account != null && account.mId >= 0) { 193 // Show the message list for the new account 194 Welcome.actionOpenAccountInbox(this, account.mId); 195 finish(); 196 return; 197 } 198 } 199 200 setContentView(R.layout.account_setup_basics); 201 202 mWelcomeView = (TextView) UiUtilities.getView(this, R.id.instructions); 203 mEmailView = (EditText) UiUtilities.getView(this, R.id.account_email); 204 mPasswordView = (EditText) UiUtilities.getView(this, R.id.account_password); 205 mDefaultView = (CheckBox) UiUtilities.getView(this, R.id.account_default); 206 207 mEmailView.addTextChangedListener(this); 208 mPasswordView.addTextChangedListener(this); 209 210 // If there are one or more accounts already in existence, then display 211 // the "use as default" checkbox (it defaults to hidden). 212 new DisplayCheckboxTask().execute(); 213 214 boolean manualButtonDisplayed = true; 215 boolean alternateStrings = false; 216 if (flowMode == SetupData.FLOW_MODE_ACCOUNT_MANAGER_EAS) { 217 // No need for manual button -> next is appropriate 218 manualButtonDisplayed = false; 219 // Swap welcome text for EAS-specific text 220 alternateStrings = VendorPolicyLoader.getInstance(this).useAlternateExchangeStrings(); 221 setTitle(alternateStrings 222 ? R.string.account_setup_basics_exchange_title_alternate 223 : R.string.account_setup_basics_exchange_title); 224 mWelcomeView.setText(alternateStrings 225 ? R.string.accounts_welcome_exchange_alternate 226 : R.string.accounts_welcome_exchange); 227 } 228 229 // Configure buttons 230 mManualButton = (Button) UiUtilities.getView(this, R.id.manual_setup); 231 mNextButton = (Button) UiUtilities.getView(this, R.id.next); 232 mManualButton.setVisibility(manualButtonDisplayed ? View.VISIBLE : View.INVISIBLE); 233 mManualButton.setOnClickListener(this); 234 mNextButton.setOnClickListener(this); 235 // Force disabled until validator notifies otherwise 236 onEnableProceedButtons(false); 237 // Lightweight debounce while Async tasks underway 238 mNextButtonInhibit = false; 239 240 // Set aside incoming AccountAuthenticatorResponse, if there was any 241 AccountAuthenticatorResponse authenticatorResponse = 242 getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE); 243 SetupData.setAccountAuthenticatorResponse(authenticatorResponse); 244 if (authenticatorResponse != null) { 245 // When this Activity is called as part of account authentification flow, 246 // we are responsible for eventually reporting the result (success or failure) to 247 // the account manager. Most exit paths represent an failed or abandoned setup, 248 // so the default is to report the error. Success will be reported by the code in 249 // AccountSetupOptions that commits the finally created account. 250 mReportAccountAuthenticatorError = true; 251 } 252 253 // Load fields, but only once 254 String userName = SetupData.getUsername(); 255 if (userName != null) { 256 mEmailView.setText(userName); 257 SetupData.setUsername(null); 258 } 259 String password = SetupData.getPassword(); 260 if (userName != null) { 261 mPasswordView.setText(password); 262 SetupData.setPassword(null); 263 } 264 265 // Handle force account creation immediately (now that fragment is set up) 266 // This is never allowed in a normal user build and will exit immediately. 267 if (SetupData.getFlowMode() == SetupData.FLOW_MODE_FORCE_CREATE) { 268 if (!DEBUG_ALLOW_NON_TEST_HARNESS_CREATION && 269 !ActivityManager.isRunningInTestHarness()) { 270 Log.e(Logging.LOG_TAG, 271 "ERROR: Force account create only allowed while in test harness"); 272 finish(); 273 return; 274 } 275 Intent intent = getIntent(); 276 String email = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_EMAIL); 277 String user = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_USER); 278 String incoming = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_INCOMING); 279 String outgoing = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_OUTGOING); 280 if (TextUtils.isEmpty(email) || TextUtils.isEmpty(user) || 281 TextUtils.isEmpty(incoming) || TextUtils.isEmpty(outgoing)) { 282 Log.e(Logging.LOG_TAG, "ERROR: Force account create requires extras EMAIL, USER, " + 283 "INCOMING, OUTGOING"); 284 finish(); 285 return; 286 } 287 forceCreateAccount(email, user, incoming, outgoing); 288 onCheckSettingsComplete(AccountCheckSettingsFragment.CHECK_SETTINGS_OK); // calls finish 289 return; 290 } 291 292 if (savedInstanceState != null && savedInstanceState.containsKey(STATE_KEY_PROVIDER)) { 293 mProvider = (Provider) savedInstanceState.getSerializable(STATE_KEY_PROVIDER); 294 } 295 296 // Launch a worker to look up the owner name. It should be ready well in advance of 297 // the time the user clicks next or manual. 298 mOwnerLookupTask = new FutureTask<String>(mOwnerLookupCallable); 299 Utility.runAsync(mOwnerLookupTask); 300 } 301 302 @Override 303 public void onPause() { 304 super.onPause(); 305 mPaused = true; 306 } 307 308 @Override 309 public void onResume() { 310 super.onResume(); 311 mPaused = false; 312 } 313 314 @Override 315 public void finish() { 316 // If the account manager initiated the creation, and success was not reported, 317 // then we assume that we're giving up (for any reason) - report failure. 318 if (mReportAccountAuthenticatorError) { 319 AccountAuthenticatorResponse authenticatorResponse = 320 SetupData.getAccountAuthenticatorResponse(); 321 if (authenticatorResponse != null) { 322 authenticatorResponse.onError(AccountManager.ERROR_CODE_CANCELED, "canceled"); 323 SetupData.setAccountAuthenticatorResponse(null); 324 } 325 } 326 super.finish(); 327 } 328 329 @Override 330 public void onSaveInstanceState(Bundle outState) { 331 super.onSaveInstanceState(outState); 332 if (mProvider != null) { 333 outState.putSerializable(STATE_KEY_PROVIDER, mProvider); 334 } 335 } 336 337 /** 338 * Implements OnClickListener 339 */ 340 @Override 341 public void onClick(View v) { 342 switch (v.getId()) { 343 case R.id.next: 344 // Simple debounce - just ignore while async checks are underway 345 if (mNextButtonInhibit) { 346 return; 347 } 348 onNext(); 349 break; 350 case R.id.manual_setup: 351 onManualSetup(false); 352 break; 353 } 354 } 355 356 /** 357 * Implements TextWatcher 358 */ 359 public void afterTextChanged(Editable s) { 360 validateFields(); 361 } 362 363 /** 364 * Implements TextWatcher 365 */ 366 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 367 } 368 369 /** 370 * Implements TextWatcher 371 */ 372 public void onTextChanged(CharSequence s, int start, int before, int count) { 373 } 374 375 private void validateFields() { 376 boolean valid = Utility.isTextViewNotEmpty(mEmailView) 377 && Utility.isTextViewNotEmpty(mPasswordView) 378 && mEmailValidator.isValid(mEmailView.getText().toString().trim()); 379 onEnableProceedButtons(valid); 380 381 // Warn (but don't prevent) if password has leading/trailing spaces 382 AccountSettingsUtils.checkPasswordSpaces(this, mPasswordView); 383 } 384 385 /** 386 * Return an existing username if found, or null. This is the result of the Callable (below). 387 */ 388 private String getOwnerName() { 389 String result = null; 390 try { 391 result = mOwnerLookupTask.get(); 392 } catch (InterruptedException e) { 393 } catch (ExecutionException e) { 394 } 395 return result; 396 } 397 398 /** 399 * Callable that returns the username (based on other accounts) or null. 400 */ 401 private Callable<String> mOwnerLookupCallable = new Callable<String>() { 402 public String call() { 403 Context context = AccountSetupBasics.this; 404 String name = null; 405 long defaultId = Account.getDefaultAccountId(context); 406 if (defaultId != -1) { 407 Account account = Account.restoreAccountWithId(context, defaultId); 408 if (account != null) { 409 name = account.getSenderName(); 410 } 411 } 412 return name; 413 } 414 }; 415 416 /** 417 * Finish the auto setup process, in some cases after showing a warning dialog. 418 */ 419 private void finishAutoSetup() { 420 String email = mEmailView.getText().toString().trim(); 421 String password = mPasswordView.getText().toString(); 422 423 try { 424 mProvider.expandTemplates(email); 425 426 Account account = SetupData.getAccount(); 427 HostAuth recvAuth = account.getOrCreateHostAuthRecv(this); 428 Utility.setHostAuthFromString(recvAuth, mProvider.incomingUri); 429 recvAuth.setLogin(mProvider.incomingUsername, password); 430 431 HostAuth sendAuth = account.getOrCreateHostAuthSend(this); 432 Utility.setHostAuthFromString(sendAuth, mProvider.outgoingUri); 433 sendAuth.setLogin(mProvider.outgoingUsername, password); 434 435 // Populate the setup data, assuming that the duplicate account check will succeed 436 populateSetupData(getOwnerName(), email, mDefaultView.isChecked()); 437 438 // Stop here if the login credentials duplicate an existing account 439 // Launch an Async task to do the work 440 new DuplicateCheckTask(this, recvAuth.mAddress, mProvider.incomingUsername).execute(); 441 } catch (URISyntaxException e) { 442 /* 443 * If there is some problem with the URI we give up and go on to manual setup. 444 * Technically speaking, AutoDiscover is OK here, since the user clicked "Next" 445 * to get here. This will not happen in practice because we don't expect to 446 * find any EAS accounts in the providers list. 447 */ 448 onManualSetup(true); 449 } 450 } 451 452 /** 453 * Async task that continues the work of finishAutoSetup(). Checks for a duplicate 454 * account and then either alerts the user, or continues. 455 */ 456 private class DuplicateCheckTask extends AsyncTask<Void, Void, Account> { 457 private final Context mContext; 458 private final String mCheckHost; 459 private final String mCheckLogin; 460 461 public DuplicateCheckTask(Context context, String checkHost, String checkLogin) { 462 mContext = context; 463 mCheckHost = checkHost; 464 mCheckLogin = checkLogin; 465 // Prevent additional clicks on the next button during Async lookup 466 mNextButtonInhibit = true; 467 } 468 469 @Override 470 protected Account doInBackground(Void... params) { 471 EmailContent.Account account = Utility.findExistingAccount(mContext, -1, 472 mCheckHost, mCheckLogin); 473 return account; 474 } 475 476 @Override 477 protected void onPostExecute(Account duplicateAccount) { 478 mNextButtonInhibit = false; 479 // Exit immediately if the user left before we finished 480 if (mPaused) return; 481 // Show duplicate account warning, or proceed 482 if (duplicateAccount != null) { 483 DuplicateAccountDialogFragment dialogFragment = 484 DuplicateAccountDialogFragment.newInstance(duplicateAccount.mDisplayName); 485 dialogFragment.show(getFragmentManager(), DuplicateAccountDialogFragment.TAG); 486 return; 487 } else { 488 AccountCheckSettingsFragment checkerFragment = 489 AccountCheckSettingsFragment.newInstance( 490 SetupData.CHECK_INCOMING | SetupData.CHECK_OUTGOING, null); 491 FragmentTransaction transaction = getFragmentManager().beginTransaction(); 492 transaction.add(checkerFragment, AccountCheckSettingsFragment.TAG); 493 transaction.addToBackStack("back"); 494 transaction.commit(); 495 } 496 } 497 } 498 499 500 /** 501 * When "next" button is clicked 502 */ 503 private void onNext() { 504 // Try auto-configuration from XML providers (unless in EAS mode, we can skip it) 505 if (SetupData.getFlowMode() != SetupData.FLOW_MODE_ACCOUNT_MANAGER_EAS) { 506 String email = mEmailView.getText().toString().trim(); 507 String[] emailParts = email.split("@"); 508 String domain = emailParts[1].trim(); 509 mProvider = AccountSettingsUtils.findProviderForDomain(this, domain); 510 if (mProvider != null) { 511 if (mProvider.note != null) { 512 NoteDialogFragment dialogFragment = 513 NoteDialogFragment.newInstance(mProvider.note); 514 dialogFragment.show(getFragmentManager(), NoteDialogFragment.TAG); 515 } else { 516 finishAutoSetup(); 517 } 518 return; 519 } 520 } 521 // Can't use auto setup (although EAS accounts may still be able to AutoDiscover) 522 onManualSetup(true); 523 } 524 525 /** 526 * When "manual setup" button is clicked 527 * 528 * @param allowAutoDiscover - true if the user clicked 'next' and (if the account is EAS) 529 * it's OK to use autodiscover. false to prevent autodiscover and go straight to manual setup. 530 * Ignored for IMAP & POP accounts. 531 */ 532 private void onManualSetup(boolean allowAutoDiscover) { 533 String email = mEmailView.getText().toString().trim(); 534 String password = mPasswordView.getText().toString(); 535 String[] emailParts = email.split("@"); 536 String user = emailParts[0].trim(); 537 String domain = emailParts[1].trim(); 538 539 // Alternate entry to the debug options screen (for devices without a physical keyboard: 540 // Username: d@d.d 541 // Password: debug 542 if (ENTER_DEBUG_SCREEN && "d@d.d".equals(email) && "debug".equals(password)) { 543 mEmailView.setText(""); 544 mPasswordView.setText(""); 545 AccountSettings.actionSettingsWithDebug(this); 546 return; 547 } 548 549 Account account = SetupData.getAccount(); 550 HostAuth recvAuth = account.getOrCreateHostAuthRecv(this); 551 recvAuth.setLogin(user, password); 552 recvAuth.setConnection("placeholder", domain, HostAuth.PORT_UNKNOWN, HostAuth.FLAG_NONE); 553 554 HostAuth sendAuth = account.getOrCreateHostAuthSend(this); 555 sendAuth.setLogin(user, password); 556 sendAuth.setConnection("placeholder", domain, HostAuth.PORT_UNKNOWN, HostAuth.FLAG_NONE); 557 558 populateSetupData(getOwnerName(), email, mDefaultView.isChecked()); 559 560 SetupData.setAllowAutodiscover(allowAutoDiscover); 561 AccountSetupAccountType.actionSelectAccountType(this); 562 } 563 564 /** 565 * To support continuous testing, we allow the forced creation of accounts. 566 * This works in a manner fairly similar to automatic setup, in which the complete server 567 * Uri's are available, except that we will also skip checking (as if both checks were true) 568 * and all other UI. 569 * 570 * @param email The email address for the new account 571 * @param user The user name for the new account 572 * @param incoming The URI-style string defining the incoming account 573 * @param outgoing The URI-style string defining the outgoing account 574 */ 575 private void forceCreateAccount(String email, String user, String incoming, String outgoing) { 576 Account account = SetupData.getAccount(); 577 try { 578 HostAuth recvAuth = account.getOrCreateHostAuthRecv(this); 579 Utility.setHostAuthFromString(recvAuth, incoming); 580 581 HostAuth sendAuth = account.getOrCreateHostAuthSend(this); 582 Utility.setHostAuthFromString(sendAuth, outgoing); 583 584 populateSetupData(user, email, false); 585 } catch (URISyntaxException e) { 586 // If we can't set up the URL, don't continue - account setup pages will fail too 587 Toast.makeText( 588 this, R.string.account_setup_username_password_toast, Toast.LENGTH_LONG).show(); 589 } 590 } 591 592 /** 593 * Populate SetupData's account with complete setup info. 594 */ 595 private void populateSetupData(String senderName, String senderEmail, boolean isDefault) { 596 Account account = SetupData.getAccount(); 597 account.setSenderName(senderName); 598 account.setEmailAddress(senderEmail); 599 account.setDisplayName(senderEmail); 600 account.setDefaultAccount(isDefault); 601 SetupData.setDefault(isDefault); // TODO - why duplicated, if already set in account 602 603 String protocol = account.mHostAuthRecv.mProtocol; 604 // Set sync and delete policies for specific inbound account types 605 if (Store.STORE_SCHEME_IMAP.equals(protocol)) { 606 // Delete policy must be set explicitly, because IMAP does not provide a UI selection 607 // for it. This logic needs to be followed in the auto setup flow as well. 608 account.setDeletePolicy(EmailContent.Account.DELETE_POLICY_ON_DELETE); 609 } 610 611 if (Store.STORE_SCHEME_EAS.equals(protocol)) { 612 account.setSyncInterval(Account.CHECK_INTERVAL_PUSH); 613 } else { 614 account.setSyncInterval(DEFAULT_ACCOUNT_CHECK_INTERVAL); 615 } 616 } 617 618 /** 619 * Implements AccountCheckSettingsFragment.Callbacks 620 * 621 * This is used in automatic setup mode to jump directly down to the options screen. 622 * 623 * This is the only case where we finish() this activity but account setup is continuing, 624 * so we inhibit reporting any error back to the Account manager. 625 */ 626 @Override 627 public void onCheckSettingsComplete(int result) { 628 if (result == AccountCheckSettingsFragment.CHECK_SETTINGS_OK) { 629 AccountSetupOptions.actionOptions(this); 630 mReportAccountAuthenticatorError = false; 631 finish(); 632 } 633 } 634 635 /** 636 * Implements AccountCheckSettingsFragment.Callbacks 637 * This is overridden only by AccountSetupExchange 638 */ 639 @Override 640 public void onAutoDiscoverComplete(int result, HostAuth hostAuth) { 641 throw new IllegalStateException(); 642 } 643 644 /** 645 * AsyncTask checks count of accounts and displays "use this account as default" checkbox 646 * if there are more than one. 647 */ 648 private class DisplayCheckboxTask extends AsyncTask<Void, Void, Integer> { 649 650 @Override 651 protected Integer doInBackground(Void... params) { 652 return EmailContent.count(AccountSetupBasics.this, EmailContent.Account.CONTENT_URI); 653 } 654 655 @Override 656 protected void onPostExecute(Integer numAccounts) { 657 if (numAccounts > 0) { 658 Activity a = AccountSetupBasics.this; 659 UiUtilities.setVisibilitySafe(mDefaultView, View.VISIBLE); 660 UiUtilities.setVisibilitySafe(a, R.id.account_default_divider_1, View.VISIBLE); 661 UiUtilities.setVisibilitySafe(a, R.id.account_default_divider_2, View.VISIBLE); 662 } 663 } 664 } 665 666 private void onEnableProceedButtons(boolean enabled) { 667 mManualButton.setEnabled(enabled); 668 mNextButton.setEnabled(enabled); 669 } 670 671 /** 672 * Dialog fragment to show "setup note" dialog 673 */ 674 public static class NoteDialogFragment extends DialogFragment { 675 private final static String TAG = "NoteDialogFragment"; 676 677 // Argument bundle keys 678 private final static String BUNDLE_KEY_NOTE = "NoteDialogFragment.Note"; 679 680 /** 681 * Create the dialog with parameters 682 */ 683 public static NoteDialogFragment newInstance(String note) { 684 NoteDialogFragment f = new NoteDialogFragment(); 685 Bundle b = new Bundle(); 686 b.putString(BUNDLE_KEY_NOTE, note); 687 f.setArguments(b); 688 return f; 689 } 690 691 @Override 692 public Dialog onCreateDialog(Bundle savedInstanceState) { 693 Context context = getActivity(); 694 final String note = getArguments().getString(BUNDLE_KEY_NOTE); 695 696 return new AlertDialog.Builder(context) 697 .setIconAttribute(android.R.attr.alertDialogIcon) 698 .setTitle(android.R.string.dialog_alert_title) 699 .setMessage(note) 700 .setPositiveButton( 701 R.string.okay_action, 702 new DialogInterface.OnClickListener() { 703 public void onClick(DialogInterface dialog, int which) { 704 Activity a = getActivity(); 705 if (a instanceof AccountSetupBasics) { 706 ((AccountSetupBasics)a).finishAutoSetup(); 707 } 708 dismiss(); 709 } 710 }) 711 .setNegativeButton( 712 context.getString(R.string.cancel_action), 713 null) 714 .create(); 715 } 716 } 717} 718