AccountSettings.java revision 56e48981f0093c737b38b7757410283be9ed823f
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;
27import com.android.exchange.Eas;
28
29import android.app.Activity;
30import android.content.ContentResolver;
31import android.content.Intent;
32import android.content.SharedPreferences;
33import android.database.Cursor;
34import android.os.Bundle;
35import android.preference.CheckBoxPreference;
36import android.preference.EditTextPreference;
37import android.preference.ListPreference;
38import android.preference.Preference;
39import android.preference.PreferenceActivity;
40import android.preference.PreferenceCategory;
41import android.preference.RingtonePreference;
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_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     */
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
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
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
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
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
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
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
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