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