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 17 package com.android.email.activity.setup; 18 19 import com.android.email.Email; 20 import com.android.email.R; 21 import com.android.email.mail.MessagingException; 22 import com.android.email.mail.Sender; 23 import com.android.email.mail.Store; 24 import com.android.email.provider.EmailContent.Account; 25 import com.android.email.provider.EmailContent.AccountColumns; 26 import com.android.email.provider.EmailContent.HostAuth; 27 import com.android.exchange.Eas; 28 29 import android.app.Activity; 30 import android.content.ContentResolver; 31 import android.content.Intent; 32 import android.content.SharedPreferences; 33 import android.database.Cursor; 34 import android.os.Bundle; 35 import android.preference.CheckBoxPreference; 36 import android.preference.EditTextPreference; 37 import android.preference.ListPreference; 38 import android.preference.Preference; 39 import android.preference.PreferenceActivity; 40 import android.preference.PreferenceCategory; 41 import android.preference.RingtonePreference; 42 import android.provider.ContactsContract; 43 import android.util.Log; 44 import android.view.KeyEvent; 45 46 public class AccountSettings extends PreferenceActivity { 47 private static final String PREFERENCE_TOP_CATEGORY = "account_settings"; 48 private static final String PREFERENCE_DESCRIPTION = "account_description"; 49 private static final String PREFERENCE_NAME = "account_name"; 50 private static final String PREFERENCE_FREQUENCY = "account_check_frequency"; 51 private static final String PREFERENCE_DEFAULT = "account_default"; 52 private static final String PREFERENCE_NOTIFY = "account_notify"; 53 private static final String PREFERENCE_VIBRATE = "account_vibrate"; 54 private static final String PREFERENCE_RINGTONE = "account_ringtone"; 55 private static final String PREFERENCE_SERVER_CATERGORY = "account_servers"; 56 private static final String PREFERENCE_INCOMING = "incoming"; 57 private static final String PREFERENCE_OUTGOING = "outgoing"; 58 private static final String PREFERENCE_SYNC_CONTACTS = "account_sync_contacts"; 59 60 // NOTE: This string must match the one in res/xml/account_preferences.xml 61 public static final String ACTION_ACCOUNT_MANAGER_ENTRY = 62 "com.android.email.activity.setup.ACCOUNT_MANAGER_ENTRY"; 63 // NOTE: This constant should eventually be defined in android.accounts.Constants, but for 64 // now we define it here 65 private static final String ACCOUNT_MANAGER_EXTRA_ACCOUNT = "account"; 66 private static final String EXTRA_ACCOUNT_ID = "account_id"; 67 68 private long mAccountId = -1; 69 private Account mAccount; 70 private boolean mAccountDirty; 71 72 private EditTextPreference mAccountDescription; 73 private EditTextPreference mAccountName; 74 private ListPreference mCheckFrequency; 75 private ListPreference mSyncWindow; 76 private CheckBoxPreference mAccountDefault; 77 private CheckBoxPreference mAccountNotify; 78 private CheckBoxPreference mAccountVibrate; 79 private RingtonePreference mAccountRingtone; 80 private CheckBoxPreference mSyncContacts; 81 82 /** 83 * Display (and edit) settings for a specific account 84 */ actionSettings(Activity fromActivity, long accountId)85 public static void actionSettings(Activity fromActivity, long accountId) { 86 Intent i = new Intent(fromActivity, AccountSettings.class); 87 i.putExtra(EXTRA_ACCOUNT_ID, accountId); 88 fromActivity.startActivity(i); 89 } 90 91 @Override onCreate(Bundle savedInstanceState)92 public void onCreate(Bundle savedInstanceState) { 93 super.onCreate(savedInstanceState); 94 95 Intent i = getIntent(); 96 if (ACTION_ACCOUNT_MANAGER_ENTRY.equals(i.getAction())) { 97 // This case occurs if we're changing account settings from Settings -> Accounts 98 setAccountIdFromAccountManagerIntent(); 99 } else { 100 // Otherwise, we're called from within the Email app and look for our extra 101 mAccountId = i.getLongExtra(EXTRA_ACCOUNT_ID, -1); 102 } 103 104 // If there's no accountId, we're done 105 if (mAccountId == -1) { 106 finish(); 107 return; 108 } 109 110 mAccount = Account.restoreAccountWithId(this, mAccountId); 111 // Similarly, if the account has been deleted 112 if (mAccount == null) { 113 finish(); 114 return; 115 } 116 mAccount.mHostAuthRecv = HostAuth.restoreHostAuthWithId(this, mAccount.mHostAuthKeyRecv); 117 mAccount.mHostAuthSend = HostAuth.restoreHostAuthWithId(this, mAccount.mHostAuthKeySend); 118 // Or if HostAuth's have been deleted 119 if (mAccount.mHostAuthRecv == null || mAccount.mHostAuthSend == null) { 120 finish(); 121 return; 122 } 123 mAccountDirty = false; 124 125 addPreferencesFromResource(R.xml.account_settings_preferences); 126 127 PreferenceCategory topCategory = (PreferenceCategory) findPreference(PREFERENCE_TOP_CATEGORY); 128 topCategory.setTitle(getString(R.string.account_settings_title_fmt)); 129 130 mAccountDescription = (EditTextPreference) findPreference(PREFERENCE_DESCRIPTION); 131 mAccountDescription.setSummary(mAccount.getDisplayName()); 132 mAccountDescription.setText(mAccount.getDisplayName()); 133 mAccountDescription.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 134 public boolean onPreferenceChange(Preference preference, Object newValue) { 135 final String summary = newValue.toString(); 136 mAccountDescription.setSummary(summary); 137 mAccountDescription.setText(summary); 138 return false; 139 } 140 }); 141 142 mAccountName = (EditTextPreference) findPreference(PREFERENCE_NAME); 143 mAccountName.setSummary(mAccount.getSenderName()); 144 mAccountName.setText(mAccount.getSenderName()); 145 mAccountName.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 146 public boolean onPreferenceChange(Preference preference, Object newValue) { 147 final String summary = newValue.toString(); 148 mAccountName.setSummary(summary); 149 mAccountName.setText(summary); 150 return false; 151 } 152 }); 153 154 mCheckFrequency = (ListPreference) findPreference(PREFERENCE_FREQUENCY); 155 156 // Before setting value, we may need to adjust the lists 157 Store.StoreInfo info = Store.StoreInfo.getStoreInfo(mAccount.getStoreUri(this), this); 158 if (info.mPushSupported) { 159 mCheckFrequency.setEntries(R.array.account_settings_check_frequency_entries_push); 160 mCheckFrequency.setEntryValues(R.array.account_settings_check_frequency_values_push); 161 } 162 163 mCheckFrequency.setValue(String.valueOf(mAccount.getSyncInterval())); 164 mCheckFrequency.setSummary(mCheckFrequency.getEntry()); 165 mCheckFrequency.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 166 public boolean onPreferenceChange(Preference preference, Object newValue) { 167 final String summary = newValue.toString(); 168 int index = mCheckFrequency.findIndexOfValue(summary); 169 mCheckFrequency.setSummary(mCheckFrequency.getEntries()[index]); 170 mCheckFrequency.setValue(summary); 171 return false; 172 } 173 }); 174 175 // Add check window preference 176 mSyncWindow = null; 177 if (info.mVisibleLimitDefault == -1) { 178 mSyncWindow = new ListPreference(this); 179 mSyncWindow.setTitle(R.string.account_setup_options_mail_window_label); 180 mSyncWindow.setEntries(R.array.account_settings_mail_window_entries); 181 mSyncWindow.setEntryValues(R.array.account_settings_mail_window_values); 182 mSyncWindow.setValue(String.valueOf(mAccount.getSyncLookback())); 183 mSyncWindow.setSummary(mSyncWindow.getEntry()); 184 mSyncWindow.setOrder(4); 185 mSyncWindow.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 186 public boolean onPreferenceChange(Preference preference, Object newValue) { 187 final String summary = newValue.toString(); 188 int index = mSyncWindow.findIndexOfValue(summary); 189 mSyncWindow.setSummary(mSyncWindow.getEntries()[index]); 190 mSyncWindow.setValue(summary); 191 return false; 192 } 193 }); 194 topCategory.addPreference(mSyncWindow); 195 } 196 197 mAccountDefault = (CheckBoxPreference) findPreference(PREFERENCE_DEFAULT); 198 mAccountDefault.setChecked(mAccount.mId == Account.getDefaultAccountId(this)); 199 200 mAccountNotify = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY); 201 mAccountNotify.setChecked(0 != (mAccount.getFlags() & Account.FLAGS_NOTIFY_NEW_MAIL)); 202 203 mAccountRingtone = (RingtonePreference) findPreference(PREFERENCE_RINGTONE); 204 205 // XXX: The following two lines act as a workaround for the RingtonePreference 206 // which does not let us set/get the value programmatically 207 SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences(); 208 prefs.edit().putString(PREFERENCE_RINGTONE, mAccount.getRingtone()).commit(); 209 210 mAccountVibrate = (CheckBoxPreference) findPreference(PREFERENCE_VIBRATE); 211 mAccountVibrate.setChecked(0 != 212 (mAccount.getFlags() & Account.FLAGS_VIBRATE)); 213 214 findPreference(PREFERENCE_INCOMING).setOnPreferenceClickListener( 215 new Preference.OnPreferenceClickListener() { 216 public boolean onPreferenceClick(Preference preference) { 217 onIncomingSettings(); 218 return true; 219 } 220 }); 221 222 // Hide the outgoing account setup link if it's not activated 223 Preference prefOutgoing = findPreference(PREFERENCE_OUTGOING); 224 boolean showOutgoing = true; 225 try { 226 Sender sender = Sender.getInstance(getApplication(), mAccount.getSenderUri(this)); 227 if (sender != null) { 228 Class<? extends android.app.Activity> setting = sender.getSettingActivityClass(); 229 showOutgoing = (setting != null); 230 } 231 } catch (MessagingException me) { 232 // just leave showOutgoing as true - bias towards showing it, so user can fix it 233 } 234 if (showOutgoing) { 235 prefOutgoing.setOnPreferenceClickListener( 236 new Preference.OnPreferenceClickListener() { 237 public boolean onPreferenceClick(Preference preference) { 238 onOutgoingSettings(); 239 return true; 240 } 241 }); 242 } else { 243 PreferenceCategory serverCategory = (PreferenceCategory) findPreference( 244 PREFERENCE_SERVER_CATERGORY); 245 serverCategory.removePreference(prefOutgoing); 246 } 247 248 mSyncContacts = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_CONTACTS); 249 if (mAccount.mHostAuthRecv.mProtocol.equals("eas")) { 250 android.accounts.Account acct = 251 new android.accounts.Account(mAccount.mEmailAddress, Eas.ACCOUNT_MANAGER_TYPE); 252 mSyncContacts.setChecked(ContentResolver 253 .getSyncAutomatically(acct, ContactsContract.AUTHORITY)); 254 } else { 255 PreferenceCategory serverCategory = (PreferenceCategory) findPreference( 256 PREFERENCE_SERVER_CATERGORY); 257 serverCategory.removePreference(mSyncContacts); 258 } 259 } 260 setAccountIdFromAccountManagerIntent()261 private void setAccountIdFromAccountManagerIntent() { 262 // First, get the AccountManager account that we've been ask to handle 263 android.accounts.Account acct = 264 (android.accounts.Account)getIntent() 265 .getParcelableExtra(ACCOUNT_MANAGER_EXTRA_ACCOUNT); 266 // Find a HostAuth using eas and whose login is klthe name of the AccountManager account 267 Cursor c = getContentResolver().query(Account.CONTENT_URI, 268 new String[] {AccountColumns.ID}, AccountColumns.EMAIL_ADDRESS + "=?", 269 new String[] {acct.name}, null); 270 try { 271 if (c.moveToFirst()) { 272 mAccountId = c.getLong(0); 273 } 274 } finally { 275 c.close(); 276 } 277 } 278 279 @Override onResume()280 public void onResume() { 281 super.onResume(); 282 if (mAccountDirty) { 283 // if we are coming back from editing incoming or outgoing settings, 284 // we need to refresh them here so we don't accidentally overwrite the 285 // old values we're still holding here 286 mAccount.mHostAuthRecv = 287 HostAuth.restoreHostAuthWithId(this, mAccount.mHostAuthKeyRecv); 288 mAccount.mHostAuthSend = 289 HostAuth.restoreHostAuthWithId(this, mAccount.mHostAuthKeySend); 290 // Because "delete policy" UI is on edit incoming settings, we have 291 // to refresh that as well. 292 Account refreshedAccount = Account.restoreAccountWithId(this, mAccount.mId); 293 if (refreshedAccount == null || mAccount.mHostAuthRecv == null 294 || mAccount.mHostAuthSend == null) { 295 finish(); 296 return; 297 } 298 mAccount.setDeletePolicy(refreshedAccount.getDeletePolicy()); 299 mAccountDirty = false; 300 } 301 } 302 saveSettings()303 private void saveSettings() { 304 int newFlags = mAccount.getFlags() & 305 ~(Account.FLAGS_NOTIFY_NEW_MAIL | Account.FLAGS_VIBRATE); 306 307 mAccount.setDefaultAccount(mAccountDefault.isChecked()); 308 mAccount.setDisplayName(mAccountDescription.getText()); 309 mAccount.setSenderName(mAccountName.getText()); 310 newFlags |= mAccountNotify.isChecked() ? Account.FLAGS_NOTIFY_NEW_MAIL : 0; 311 mAccount.setSyncInterval(Integer.parseInt(mCheckFrequency.getValue())); 312 if (mSyncWindow != null) { 313 mAccount.setSyncLookback(Integer.parseInt(mSyncWindow.getValue())); 314 } 315 newFlags |= mAccountVibrate.isChecked() ? Account.FLAGS_VIBRATE : 0; 316 SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences(); 317 mAccount.setRingtone(prefs.getString(PREFERENCE_RINGTONE, null)); 318 mAccount.setFlags(newFlags); 319 320 if (mAccount.mHostAuthRecv.mProtocol.equals("eas")) { 321 android.accounts.Account acct = 322 new android.accounts.Account(mAccount.mEmailAddress, Eas.ACCOUNT_MANAGER_TYPE); 323 ContentResolver.setSyncAutomatically(acct, ContactsContract.AUTHORITY, 324 mSyncContacts.isChecked()); 325 326 } 327 AccountSettingsUtils.commitSettings(this, mAccount); 328 Email.setServicesEnabled(this); 329 } 330 331 @Override onKeyDown(int keyCode, KeyEvent event)332 public boolean onKeyDown(int keyCode, KeyEvent event) { 333 if (keyCode == KeyEvent.KEYCODE_BACK) { 334 saveSettings(); 335 } 336 return super.onKeyDown(keyCode, event); 337 } 338 onIncomingSettings()339 private void onIncomingSettings() { 340 try { 341 Store store = Store.getInstance(mAccount.getStoreUri(this), getApplication(), null); 342 if (store != null) { 343 Class<? extends android.app.Activity> setting = store.getSettingActivityClass(); 344 if (setting != null) { 345 java.lang.reflect.Method m = setting.getMethod("actionEditIncomingSettings", 346 android.app.Activity.class, Account.class); 347 m.invoke(null, this, mAccount); 348 mAccountDirty = true; 349 } 350 } 351 } catch (Exception e) { 352 Log.d(Email.LOG_TAG, "Error while trying to invoke store settings.", e); 353 } 354 } 355 onOutgoingSettings()356 private void onOutgoingSettings() { 357 try { 358 Sender sender = Sender.getInstance(getApplication(), mAccount.getSenderUri(this)); 359 if (sender != null) { 360 Class<? extends android.app.Activity> setting = sender.getSettingActivityClass(); 361 if (setting != null) { 362 java.lang.reflect.Method m = setting.getMethod("actionEditOutgoingSettings", 363 android.app.Activity.class, Account.class); 364 m.invoke(null, this, mAccount); 365 mAccountDirty = true; 366 } 367 } 368 } catch (Exception e) { 369 Log.d(Email.LOG_TAG, "Error while trying to invoke sender settings.", e); 370 } 371 } 372 } 373