AccountSettingsFragment.java revision 2959a7e073c87e2fa5fab42ec543b352a91cf187
1/* 2 * Copyright (C) 2010 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.R; 21import com.android.email.Utility; 22import com.android.email.mail.MessagingException; 23import com.android.email.mail.Sender; 24import com.android.email.mail.Store; 25import com.android.email.provider.EmailContent; 26import com.android.email.provider.EmailContent.Account; 27import com.android.email.provider.EmailContent.HostAuth; 28 29import android.app.Activity; 30import android.app.AlertDialog; 31import android.app.Dialog; 32import android.app.DialogFragment; 33import android.app.Fragment; 34import android.app.FragmentTransaction; 35import android.content.ContentResolver; 36import android.content.ContentValues; 37import android.content.Context; 38import android.content.DialogInterface; 39import android.content.SharedPreferences; 40import android.os.AsyncTask; 41import android.os.Bundle; 42import android.os.Vibrator; 43import android.preference.CheckBoxPreference; 44import android.preference.EditTextPreference; 45import android.preference.ListPreference; 46import android.preference.Preference; 47import android.preference.PreferenceCategory; 48import android.preference.PreferenceFragment; 49import android.preference.RingtonePreference; 50import android.provider.Calendar; 51import android.provider.ContactsContract; 52import android.util.Log; 53 54/** 55 * Fragment containing the main logic for account settings. This also calls out to other 56 * fragments for server settings. 57 * 58 * TODO: Remove or make async the mAccountDirty reload logic. Probably no longer needed. 59 * TODO: Can we defer calling addPreferencesFromResource() until after we load the account? This 60 * could reduce flicker. 61 */ 62public class AccountSettingsFragment extends PreferenceFragment { 63 64 // Keys used for arguments bundle 65 private static final String BUNDLE_KEY_ACCOUNT_ID = "AccountSettingsFragment.AccountId"; 66 67 private static final String PREFERENCE_CATEGORY_TOP = "account_settings"; 68 private static final String PREFERENCE_DESCRIPTION = "account_description"; 69 private static final String PREFERENCE_NAME = "account_name"; 70 private static final String PREFERENCE_SIGNATURE = "account_signature"; 71 private static final String PREFERENCE_FREQUENCY = "account_check_frequency"; 72 private static final String PREFERENCE_DEFAULT = "account_default"; 73 private static final String PREFERENCE_CATEGORY_NOTIFICATIONS = "account_notifications"; 74 private static final String PREFERENCE_NOTIFY = "account_notify"; 75 private static final String PREFERENCE_VIBRATE_WHEN = "account_settings_vibrate_when"; 76 private static final String PREFERENCE_RINGTONE = "account_ringtone"; 77 private static final String PREFERENCE_CATEGORY_SERVER = "account_servers"; 78 private static final String PREFERENCE_INCOMING = "incoming"; 79 private static final String PREFERENCE_OUTGOING = "outgoing"; 80 private static final String PREFERENCE_SYNC_CONTACTS = "account_sync_contacts"; 81 private static final String PREFERENCE_SYNC_CALENDAR = "account_sync_calendar"; 82 private static final String PREFERENCE_SYNC_EMAIL = "account_sync_email"; 83 private static final String PREFERENCE_DELETE_ACCOUNT = "delete_account"; 84 85 // These strings must match account_settings_vibrate_when_* strings in strings.xml 86 private static final String PREFERENCE_VALUE_VIBRATE_WHEN_ALWAYS = "always"; 87 private static final String PREFERENCE_VALUE_VIBRATE_WHEN_SILENT = "silent"; 88 private static final String PREFERENCE_VALUE_VIBRATE_WHEN_NEVER = "never"; 89 90 private EditTextPreference mAccountDescription; 91 private EditTextPreference mAccountName; 92 private EditTextPreference mAccountSignature; 93 private ListPreference mCheckFrequency; 94 private ListPreference mSyncWindow; 95 private CheckBoxPreference mAccountDefault; 96 private CheckBoxPreference mAccountNotify; 97 private ListPreference mAccountVibrateWhen; 98 private RingtonePreference mAccountRingtone; 99 private CheckBoxPreference mSyncContacts; 100 private CheckBoxPreference mSyncCalendar; 101 private CheckBoxPreference mSyncEmail; 102 103 private Context mContext; 104 private Account mAccount; 105 private boolean mAccountDirty; 106 private long mDefaultAccountId; 107 private Callback mCallback = EmptyCallback.INSTANCE; 108 private boolean mStarted; 109 private boolean mLoaded; 110 private boolean mSaveOnExit; 111 112 // Async Tasks 113 private AsyncTask<?,?,?> mLoadAccountTask; 114 115 /** 116 * Callback interface that owning activities must provide 117 */ 118 public interface Callback { 119 public void onIncomingSettings(Account account); 120 public void onOutgoingSettings(Account account); 121 public void abandonEdit(); 122 public void deleteAccount(Account account); 123 } 124 125 private static class EmptyCallback implements Callback { 126 public static final Callback INSTANCE = new EmptyCallback(); 127 @Override public void onIncomingSettings(Account account) { } 128 @Override public void onOutgoingSettings(Account account) { } 129 @Override public void abandonEdit() { } 130 @Override public void deleteAccount(Account account) { } 131 } 132 133 /** 134 * If launching with an arguments bundle, use this method to build the arguments. 135 * @param accountId The account being modified 136 */ 137 public static Bundle buildArguments(long accountId) { 138 Bundle b = new Bundle(); 139 b.putLong(BUNDLE_KEY_ACCOUNT_ID, accountId); 140 return b; 141 } 142 143 /** 144 * Called when a fragment is first attached to its activity. 145 * {@link #onCreate(Bundle)} will be called after this. 146 */ 147 @Override 148 public void onAttach(Activity activity) { 149 super.onAttach(activity); 150 151 mContext = activity; 152 153 // Notify the activity that we're here. 154 if (activity instanceof AccountSettingsXL) { 155 ((AccountSettingsXL)activity).onAttach(this); 156 } 157 } 158 159 /** 160 * Called to do initial creation of a fragment. This is called after 161 * {@link #onAttach(Activity)} and before {@link #onActivityCreated(Bundle)}. 162 */ 163 @Override 164 public void onCreate(Bundle savedInstanceState) { 165 if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { 166 Log.d(Email.LOG_TAG, "AccountSettingsFragment onCreate"); 167 } 168 super.onCreate(savedInstanceState); 169 170 // Load the preferences from an XML resource 171 addPreferencesFromResource(R.xml.account_settings_preferences); 172 173 // Start loading the account data, if provided in the arguments 174 // If not, activity must call startLoadingAccount() directly 175 Bundle b = getArguments(); 176 if (b != null) { 177 long accountId = b.getLong(BUNDLE_KEY_ACCOUNT_ID, -1); 178 if (accountId >= 0 && !mLoaded) { 179 startLoadingAccount(accountId); 180 } 181 } 182 183 mAccountDirty = false; 184 } 185 186 @Override 187 public void onActivityCreated(Bundle savedInstanceState) { 188 if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { 189 Log.d(Email.LOG_TAG, "AccountSettingsFragment onActivityCreated"); 190 } 191 super.onActivityCreated(savedInstanceState); 192 } 193 194 /** 195 * Called when the Fragment is visible to the user. 196 */ 197 @Override 198 public void onStart() { 199 if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { 200 Log.d(Email.LOG_TAG, "AccountSettingsFragment onStart"); 201 } 202 super.onStart(); 203 mStarted = true; 204 205 // If the loaded account is ready now, load the UI 206 if (mAccount != null && !mLoaded) { 207 loadSettings(); 208 } 209 } 210 211 /** 212 * Called when the fragment is visible to the user and actively running. 213 * TODO: Don't read account data on UI thread. This should be fixed by removing the need 214 * to do this, not by spinning up yet another thread. 215 */ 216 @Override 217 public void onResume() { 218 if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { 219 Log.d(Email.LOG_TAG, "AccountSettingsFragment onResume"); 220 } 221 super.onResume(); 222 223 if (mAccountDirty) { 224 // if we are coming back from editing incoming or outgoing settings, 225 // we need to refresh them here so we don't accidentally overwrite the 226 // old values we're still holding here 227 mAccount.mHostAuthRecv = 228 HostAuth.restoreHostAuthWithId(mContext, mAccount.mHostAuthKeyRecv); 229 mAccount.mHostAuthSend = 230 HostAuth.restoreHostAuthWithId(mContext, mAccount.mHostAuthKeySend); 231 // Because "delete policy" UI is on edit incoming settings, we have 232 // to refresh that as well. 233 Account refreshedAccount = Account.restoreAccountWithId(mContext, mAccount.mId); 234 if (refreshedAccount == null || mAccount.mHostAuthRecv == null 235 || mAccount.mHostAuthSend == null) { 236 mSaveOnExit = false; 237 mCallback.abandonEdit(); 238 return; 239 } 240 mAccount.setDeletePolicy(refreshedAccount.getDeletePolicy()); 241 mAccountDirty = false; 242 } 243 } 244 245 @Override 246 public void onPause() { 247 if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { 248 Log.d(Email.LOG_TAG, "AccountSettingsFragment onPause"); 249 } 250 super.onPause(); 251 if (mSaveOnExit) { 252 saveSettings(); 253 } 254 } 255 256 /** 257 * Called when the Fragment is no longer started. 258 */ 259 @Override 260 public void onStop() { 261 if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { 262 Log.d(Email.LOG_TAG, "AccountSettingsFragment onStop"); 263 } 264 super.onStop(); 265 mStarted = false; 266 } 267 268 /** 269 * Called when the fragment is no longer in use. 270 */ 271 @Override 272 public void onDestroy() { 273 if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { 274 Log.d(Email.LOG_TAG, "AccountSettingsFragment onDestroy"); 275 } 276 super.onDestroy(); 277 278 Utility.cancelTaskInterrupt(mLoadAccountTask); 279 mLoadAccountTask = null; 280 } 281 282 @Override 283 public void onSaveInstanceState(Bundle outState) { 284 if (Email.DEBUG_LIFECYCLE && Email.DEBUG) { 285 Log.d(Email.LOG_TAG, "AccountSettingsFragment onSaveInstanceState"); 286 } 287 super.onSaveInstanceState(outState); 288 } 289 290 /** 291 * Activity provides callbacks here 292 */ 293 public void setCallback(Callback callback) { 294 mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback; 295 } 296 297 /** 298 * Start loading a single account in preparation for editing it 299 */ 300 public void startLoadingAccount(long accountId) { 301 Utility.cancelTaskInterrupt(mLoadAccountTask); 302 mLoadAccountTask = new LoadAccountTask().execute(accountId); 303 } 304 305 /** 306 * Async task to load account in order to view/edit it 307 */ 308 private class LoadAccountTask extends AsyncTask<Long, Void, Object[]> { 309 @Override 310 protected Object[] doInBackground(Long... params) { 311 long accountId = params[0]; 312 Account account = Account.restoreAccountWithId(mContext, accountId); 313 if (account != null) { 314 account.mHostAuthRecv = 315 HostAuth.restoreHostAuthWithId(mContext, account.mHostAuthKeyRecv); 316 account.mHostAuthSend = 317 HostAuth.restoreHostAuthWithId(mContext, account.mHostAuthKeySend); 318 if (account.mHostAuthRecv == null || account.mHostAuthSend == null) { 319 account = null; 320 } 321 } 322 long defaultAccountId = Account.getDefaultAccountId(mContext); 323 return new Object[] { account, Long.valueOf(defaultAccountId) }; 324 } 325 326 @Override 327 protected void onPostExecute(Object[] results) { 328 if (results != null && !isCancelled()) { 329 Account account = (Account) results[0]; 330 if (account == null) { 331 mSaveOnExit = false; 332 mCallback.abandonEdit(); 333 } else { 334 mAccount = account; 335 mDefaultAccountId = (Long) results[1]; 336 if (mStarted && !mLoaded) { 337 loadSettings(); 338 } 339 } 340 } 341 } 342 } 343 344 /** 345 * Load account data into preference UI 346 */ 347 private void loadSettings() { 348 // We can only do this once, so prevent repeat 349 mLoaded = true; 350 // Once loaded the data is ready to be saved, as well 351 mSaveOnExit = false; 352 353 PreferenceCategory topCategory = 354 (PreferenceCategory) findPreference(PREFERENCE_CATEGORY_TOP); 355 topCategory.setTitle(mContext.getString(R.string.account_settings_title_fmt)); 356 357 mAccountDescription = (EditTextPreference) findPreference(PREFERENCE_DESCRIPTION); 358 mAccountDescription.setSummary(mAccount.getDisplayName()); 359 mAccountDescription.setText(mAccount.getDisplayName()); 360 mAccountDescription.setOnPreferenceChangeListener( 361 new Preference.OnPreferenceChangeListener() { 362 public boolean onPreferenceChange(Preference preference, Object newValue) { 363 final String summary = newValue.toString(); 364 mAccountDescription.setSummary(summary); 365 mAccountDescription.setText(summary); 366 onPreferenceChanged(); 367 return false; 368 } 369 } 370 ); 371 372 mAccountName = (EditTextPreference) findPreference(PREFERENCE_NAME); 373 mAccountName.setSummary(mAccount.getSenderName()); 374 mAccountName.setText(mAccount.getSenderName()); 375 mAccountName.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 376 public boolean onPreferenceChange(Preference preference, Object newValue) { 377 final String summary = newValue.toString(); 378 mAccountName.setSummary(summary); 379 mAccountName.setText(summary); 380 onPreferenceChanged(); 381 return false; 382 } 383 }); 384 385 mAccountSignature = (EditTextPreference) findPreference(PREFERENCE_SIGNATURE); 386 mAccountSignature.setSummary(mAccount.getSignature()); 387 mAccountSignature.setText(mAccount.getSignature()); 388 mAccountSignature.setOnPreferenceChangeListener( 389 new Preference.OnPreferenceChangeListener() { 390 public boolean onPreferenceChange(Preference preference, Object newValue) { 391 String summary = newValue.toString(); 392 if (summary == null || summary.length() == 0) { 393 mAccountSignature.setSummary(R.string.account_settings_signature_hint); 394 } else { 395 mAccountSignature.setSummary(summary); 396 } 397 mAccountSignature.setText(summary); 398 onPreferenceChanged(); 399 return false; 400 } 401 }); 402 403 mCheckFrequency = (ListPreference) findPreference(PREFERENCE_FREQUENCY); 404 405 // Before setting value, we may need to adjust the lists 406 Store.StoreInfo info = Store.StoreInfo.getStoreInfo(mAccount.getStoreUri(mContext), 407 mContext); 408 if (info.mPushSupported) { 409 mCheckFrequency.setEntries(R.array.account_settings_check_frequency_entries_push); 410 mCheckFrequency.setEntryValues(R.array.account_settings_check_frequency_values_push); 411 } 412 413 mCheckFrequency.setValue(String.valueOf(mAccount.getSyncInterval())); 414 mCheckFrequency.setSummary(mCheckFrequency.getEntry()); 415 mCheckFrequency.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 416 public boolean onPreferenceChange(Preference preference, Object newValue) { 417 final String summary = newValue.toString(); 418 int index = mCheckFrequency.findIndexOfValue(summary); 419 mCheckFrequency.setSummary(mCheckFrequency.getEntries()[index]); 420 mCheckFrequency.setValue(summary); 421 onPreferenceChanged(); 422 return false; 423 } 424 }); 425 426 // Add check window preference 427 mSyncWindow = null; 428 if (info.mVisibleLimitDefault == -1) { 429 mSyncWindow = new ListPreference(mContext); 430 mSyncWindow.setTitle(R.string.account_setup_options_mail_window_label); 431 mSyncWindow.setEntries(R.array.account_settings_mail_window_entries); 432 mSyncWindow.setEntryValues(R.array.account_settings_mail_window_values); 433 mSyncWindow.setValue(String.valueOf(mAccount.getSyncLookback())); 434 mSyncWindow.setSummary(mSyncWindow.getEntry()); 435 mSyncWindow.setOrder(4); 436 mSyncWindow.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 437 public boolean onPreferenceChange(Preference preference, Object newValue) { 438 final String summary = newValue.toString(); 439 int index = mSyncWindow.findIndexOfValue(summary); 440 mSyncWindow.setSummary(mSyncWindow.getEntries()[index]); 441 mSyncWindow.setValue(summary); 442 onPreferenceChanged(); 443 return false; 444 } 445 }); 446 topCategory.addPreference(mSyncWindow); 447 } 448 449 mAccountDefault = (CheckBoxPreference) findPreference(PREFERENCE_DEFAULT); 450 mAccountDefault.setChecked(mAccount.mId == mDefaultAccountId); 451 mAccountDefault.setOnPreferenceChangeListener(mPreferenceChangeListener); 452 453 mAccountNotify = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY); 454 mAccountNotify.setChecked(0 != (mAccount.getFlags() & Account.FLAGS_NOTIFY_NEW_MAIL)); 455 mAccountNotify.setOnPreferenceChangeListener(mPreferenceChangeListener); 456 457 mAccountRingtone = (RingtonePreference) findPreference(PREFERENCE_RINGTONE); 458 mAccountRingtone.setOnPreferenceChangeListener(mPreferenceChangeListener); 459 460 // The following two lines act as a workaround for the RingtonePreference 461 // which does not let us set/get the value programmatically 462 SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences(); 463 prefs.edit().putString(PREFERENCE_RINGTONE, mAccount.getRingtone()).apply(); 464 465 // Set the vibrator value, or hide it on devices w/o a vibrator 466 mAccountVibrateWhen = (ListPreference) findPreference(PREFERENCE_VIBRATE_WHEN); 467 Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); 468 if (vibrator.hasVibrator()) { 469 boolean flagsVibrate = 0 != (mAccount.getFlags() & Account.FLAGS_VIBRATE_ALWAYS); 470 boolean flagsVibrateSilent = 471 0 != (mAccount.getFlags() & Account.FLAGS_VIBRATE_WHEN_SILENT); 472 mAccountVibrateWhen.setValue( 473 flagsVibrate ? PREFERENCE_VALUE_VIBRATE_WHEN_ALWAYS : 474 flagsVibrateSilent ? PREFERENCE_VALUE_VIBRATE_WHEN_SILENT : 475 PREFERENCE_VALUE_VIBRATE_WHEN_NEVER); 476 mAccountVibrateWhen.setOnPreferenceChangeListener(mPreferenceChangeListener); 477 } else { 478 PreferenceCategory notificationsCategory = (PreferenceCategory) 479 findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS); 480 notificationsCategory.removePreference(mAccountVibrateWhen); 481 } 482 483 findPreference(PREFERENCE_INCOMING).setOnPreferenceClickListener( 484 new Preference.OnPreferenceClickListener() { 485 public boolean onPreferenceClick(Preference preference) { 486 mAccountDirty = true; 487 mCallback.onIncomingSettings(mAccount); 488 return true; 489 } 490 }); 491 492 // Hide the outgoing account setup link if it's not activated 493 Preference prefOutgoing = findPreference(PREFERENCE_OUTGOING); 494 boolean showOutgoing = true; 495 try { 496 Sender sender = Sender.getInstance(mContext, mAccount.getSenderUri(mContext)); 497 if (sender != null) { 498 Class<? extends android.app.Activity> setting = sender.getSettingActivityClass(); 499 showOutgoing = (setting != null); 500 } 501 } catch (MessagingException me) { 502 // just leave showOutgoing as true - bias towards showing it, so user can fix it 503 } 504 if (showOutgoing) { 505 prefOutgoing.setOnPreferenceClickListener( 506 new Preference.OnPreferenceClickListener() { 507 public boolean onPreferenceClick(Preference preference) { 508 mAccountDirty = true; 509 mCallback.onOutgoingSettings(mAccount); 510 return true; 511 } 512 }); 513 } else { 514 PreferenceCategory serverCategory = (PreferenceCategory) findPreference( 515 PREFERENCE_CATEGORY_SERVER); 516 serverCategory.removePreference(prefOutgoing); 517 } 518 519 mSyncContacts = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_CONTACTS); 520 mSyncCalendar = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_CALENDAR); 521 mSyncEmail = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_EMAIL); 522 if (mAccount.mHostAuthRecv.mProtocol.equals("eas")) { 523 android.accounts.Account acct = new android.accounts.Account(mAccount.mEmailAddress, 524 Email.EXCHANGE_ACCOUNT_MANAGER_TYPE); 525 mSyncContacts.setChecked(ContentResolver 526 .getSyncAutomatically(acct, ContactsContract.AUTHORITY)); 527 mSyncContacts.setOnPreferenceChangeListener(mPreferenceChangeListener); 528 mSyncCalendar.setChecked(ContentResolver 529 .getSyncAutomatically(acct, Calendar.AUTHORITY)); 530 mSyncCalendar.setOnPreferenceChangeListener(mPreferenceChangeListener); 531 mSyncEmail.setChecked(ContentResolver 532 .getSyncAutomatically(acct, EmailContent.AUTHORITY)); 533 mSyncEmail.setOnPreferenceChangeListener(mPreferenceChangeListener); 534 } else { 535 PreferenceCategory serverCategory = (PreferenceCategory) findPreference( 536 PREFERENCE_CATEGORY_SERVER); 537 serverCategory.removePreference(mSyncContacts); 538 serverCategory.removePreference(mSyncCalendar); 539 serverCategory.removePreference(mSyncEmail); 540 } 541 542 // Temporary home for delete account 543 Preference prefDeleteAccount = findPreference(PREFERENCE_DELETE_ACCOUNT); 544 prefDeleteAccount.setOnPreferenceClickListener( 545 new Preference.OnPreferenceClickListener() { 546 public boolean onPreferenceClick(Preference preference) { 547 DeleteAccountFragment dialogFragment = DeleteAccountFragment.newInstance( 548 mAccount, AccountSettingsFragment.this); 549 FragmentTransaction ft = getFragmentManager().openTransaction(); 550 ft.addToBackStack(null); 551 dialogFragment.show(ft, DeleteAccountFragment.TAG); 552 return true; 553 } 554 }); 555 } 556 557 /** 558 * Generic onPreferenceChanged listener for the preferences (above) that just need 559 * to be written, without extra tweaks 560 */ 561 private Preference.OnPreferenceChangeListener mPreferenceChangeListener = 562 new Preference.OnPreferenceChangeListener() { 563 public boolean onPreferenceChange(Preference preference, Object newValue) { 564 onPreferenceChanged(); 565 return true; 566 } 567 }; 568 569 /** 570 * Called any time a preference is changed. 571 */ 572 private void onPreferenceChanged() { 573 mSaveOnExit = true; 574 } 575 576 /* 577 * Note: This writes the settings on the UI thread. This has to be done so the settings are 578 * committed before we might be killed. 579 */ 580 private void saveSettings() { 581 int newFlags = mAccount.getFlags() & 582 ~(Account.FLAGS_NOTIFY_NEW_MAIL | 583 Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_VIBRATE_WHEN_SILENT); 584 585 mAccount.setDefaultAccount(mAccountDefault.isChecked()); 586 mAccount.setDisplayName(mAccountDescription.getText()); 587 mAccount.setSenderName(mAccountName.getText()); 588 mAccount.setSignature(mAccountSignature.getText()); 589 newFlags |= mAccountNotify.isChecked() ? Account.FLAGS_NOTIFY_NEW_MAIL : 0; 590 mAccount.setSyncInterval(Integer.parseInt(mCheckFrequency.getValue())); 591 if (mSyncWindow != null) { 592 mAccount.setSyncLookback(Integer.parseInt(mSyncWindow.getValue())); 593 } 594 if (mAccountVibrateWhen.getValue().equals(PREFERENCE_VALUE_VIBRATE_WHEN_ALWAYS)) { 595 newFlags |= Account.FLAGS_VIBRATE_ALWAYS; 596 } else if (mAccountVibrateWhen.getValue().equals(PREFERENCE_VALUE_VIBRATE_WHEN_SILENT)) { 597 newFlags |= Account.FLAGS_VIBRATE_WHEN_SILENT; 598 } 599 SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences(); 600 mAccount.setRingtone(prefs.getString(PREFERENCE_RINGTONE, null)); 601 mAccount.setFlags(newFlags); 602 603 if (mAccount.mHostAuthRecv.mProtocol.equals("eas")) { 604 android.accounts.Account acct = new android.accounts.Account(mAccount.mEmailAddress, 605 Email.EXCHANGE_ACCOUNT_MANAGER_TYPE); 606 ContentResolver.setSyncAutomatically(acct, ContactsContract.AUTHORITY, 607 mSyncContacts.isChecked()); 608 ContentResolver.setSyncAutomatically(acct, Calendar.AUTHORITY, 609 mSyncCalendar.isChecked()); 610 ContentResolver.setSyncAutomatically(acct, EmailContent.AUTHORITY, 611 mSyncEmail.isChecked()); 612 } 613 614 // Commit the changes 615 // Note, this is done in the UI thread because at this point, we must commit 616 // all changes - any time after onPause completes, we could be killed. This is analogous 617 // to the way that SharedPreferences tries to work off-thread in apply(), but will pause 618 // until completion in onPause(). 619 ContentValues cv = AccountSettingsUtils.getAccountContentValues(mAccount); 620 mAccount.update(mContext, cv); 621 622 // Run the remaining changes off-thread 623 Email.setServicesEnabledAsync(mContext); 624 } 625 626 /** 627 * Dialog fragment to show "remove account?" dialog 628 */ 629 public static class DeleteAccountFragment extends DialogFragment { 630 private final static String TAG = "DeleteAccountFragment"; 631 632 // Argument bundle keys 633 private final static String BUNDLE_KEY_ACCOUNT_NAME = "DeleteAccountFragment.Name"; 634 635 /** 636 * Create the dialog with parameters 637 */ 638 public static DeleteAccountFragment newInstance(Account account, Fragment parentFragment) { 639 DeleteAccountFragment f = new DeleteAccountFragment(); 640 Bundle b = new Bundle(); 641 b.putString(BUNDLE_KEY_ACCOUNT_NAME, account.getDisplayName()); 642 f.setArguments(b); 643 f.setTargetFragment(parentFragment, 0); 644 return f; 645 } 646 647 @Override 648 public Dialog onCreateDialog(Bundle savedInstanceState) { 649 Context context = getActivity(); 650 final String name = getArguments().getString(BUNDLE_KEY_ACCOUNT_NAME); 651 652 return new AlertDialog.Builder(context) 653 .setIcon(android.R.drawable.ic_dialog_alert) 654 .setTitle(R.string.account_delete_dlg_title) 655 .setMessage(context.getString(R.string.account_delete_dlg_instructions_fmt, name)) 656 .setPositiveButton( 657 R.string.okay_action, 658 new DialogInterface.OnClickListener() { 659 public void onClick(DialogInterface dialog, int whichButton) { 660 Fragment f = getTargetFragment(); 661 if (f instanceof AccountSettingsFragment) { 662 ((AccountSettingsFragment)f).finishDeleteAccount(); 663 } 664 dismiss(); 665 } 666 }) 667 .setNegativeButton( 668 R.string.cancel_action, 669 new DialogInterface.OnClickListener() { 670 public void onClick(DialogInterface dialog, int whichButton) { 671 dismiss(); 672 } 673 }) 674 .create(); 675 } 676 } 677 678 /** 679 * Callback from delete account dialog - passes the delete command up to the activity 680 */ 681 private void finishDeleteAccount() { 682 mSaveOnExit = false; 683 mCallback.deleteAccount(mAccount); 684 } 685} 686