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