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