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