AccountSettingsFragment.java revision bd29c3090305ce415fb29ba7af339a1359c746d3
1/*
2 * Copyright (C) 2010 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.Utility;
22import com.android.email.mail.MessagingException;
23import com.android.email.mail.Sender;
24import com.android.email.mail.Store;
25import com.android.email.provider.EmailContent;
26import com.android.email.provider.EmailContent.Account;
27import com.android.email.provider.EmailContent.HostAuth;
28
29import android.app.Activity;
30import android.app.AlertDialog;
31import android.app.Dialog;
32import android.app.DialogFragment;
33import android.app.Fragment;
34import android.app.FragmentTransaction;
35import android.content.ContentResolver;
36import android.content.Context;
37import android.content.DialogInterface;
38import android.content.SharedPreferences;
39import android.os.AsyncTask;
40import android.os.Bundle;
41import android.preference.CheckBoxPreference;
42import android.preference.EditTextPreference;
43import android.preference.ListPreference;
44import android.preference.Preference;
45import android.preference.PreferenceCategory;
46import android.preference.PreferenceFragment;
47import android.preference.RingtonePreference;
48import android.provider.Calendar;
49import android.provider.ContactsContract;
50import android.util.Log;
51
52/**
53 * Fragment containing the main logic for account settings.  This also calls out to other
54 * fragments for server settings.
55 *
56 * TODO: Move all "Restore" ops & other queries out of lifecycle methods and out of UI thread
57 * TODO: Can we defer calling addPreferencesFromResource() until after we load the account?  This
58 *       could reduce flicker.
59 *
60 * STOPSHIP: Find a permanent home for delete account
61 *
62 * STOPSHIP: Remove fragment lifecycle logging
63 */
64public class AccountSettingsFragment extends PreferenceFragment {
65
66    // Keys used for arguments bundle
67    private static final String BUNDLE_KEY_ACCOUNT_ID = "AccountSettingsFragment.AccountId";
68
69    private static final String PREFERENCE_TOP_CATEGORY = "account_settings";
70    private static final String PREFERENCE_DESCRIPTION = "account_description";
71    private static final String PREFERENCE_NAME = "account_name";
72    private static final String PREFERENCE_SIGNATURE = "account_signature";
73    private static final String PREFERENCE_FREQUENCY = "account_check_frequency";
74    private static final String PREFERENCE_DEFAULT = "account_default";
75    private static final String PREFERENCE_NOTIFY = "account_notify";
76    private static final String PREFERENCE_VIBRATE_WHEN = "account_settings_vibrate_when";
77    private static final String PREFERENCE_RINGTONE = "account_ringtone";
78    private static final String PREFERENCE_SERVER_CATEGORY = "account_servers";
79    private static final String PREFERENCE_INCOMING = "incoming";
80    private static final String PREFERENCE_OUTGOING = "outgoing";
81    private static final String PREFERENCE_SYNC_CONTACTS = "account_sync_contacts";
82    private static final String PREFERENCE_SYNC_CALENDAR = "account_sync_calendar";
83    private static final String PREFERENCE_SYNC_EMAIL = "account_sync_email";
84    private static final String PREFERENCE_DELETE_ACCOUNT_CATEGORY = "category_delete_account";
85    private static final String PREFERENCE_DELETE_ACCOUNT = "delete_account";
86
87    // These strings must match account_settings_vibrate_when_* strings in strings.xml
88    private static final String PREFERENCE_VALUE_VIBRATE_WHEN_ALWAYS = "always";
89    private static final String PREFERENCE_VALUE_VIBRATE_WHEN_SILENT = "silent";
90    private static final String PREFERENCE_VALUE_VIBRATE_WHEN_NEVER = "never";
91
92    private EditTextPreference mAccountDescription;
93    private EditTextPreference mAccountName;
94    private EditTextPreference mAccountSignature;
95    private ListPreference mCheckFrequency;
96    private ListPreference mSyncWindow;
97    private CheckBoxPreference mAccountDefault;
98    private CheckBoxPreference mAccountNotify;
99    private ListPreference mAccountVibrateWhen;
100    private RingtonePreference mAccountRingtone;
101    private CheckBoxPreference mSyncContacts;
102    private CheckBoxPreference mSyncCalendar;
103    private CheckBoxPreference mSyncEmail;
104
105    private Context mContext;
106    private Account mAccount;
107    private boolean mAccountDirty;
108    private Callback mCallback = EmptyCallback.INSTANCE;
109    private boolean mStarted;
110    private boolean mLoaded;
111    private boolean mSaveOnExit;
112
113    // Async Tasks
114    private AsyncTask<?,?,?> mLoadAccountTask;
115
116    /**
117     * Callback interface that owning activities must provide
118     */
119    public interface Callback {
120        public void onIncomingSettings(Account account);
121        public void onOutgoingSettings(Account account);
122        public void abandonEdit();
123        public void deleteAccount(Account account);
124    }
125
126    private static class EmptyCallback implements Callback {
127        public static final Callback INSTANCE = new EmptyCallback();
128        @Override public void onIncomingSettings(Account account) { }
129        @Override public void onOutgoingSettings(Account account) { }
130        @Override public void abandonEdit() { }
131        @Override public void deleteAccount(Account account) { };
132    }
133
134    /**
135     * If launching with an arguments bundle, use this method to build the arguments.
136     * @param accountId The account being modified
137     */
138    public static Bundle buildArguments(long accountId) {
139        Bundle b = new Bundle();
140        b.putLong(BUNDLE_KEY_ACCOUNT_ID, accountId);
141        return b;
142    }
143
144    /**
145     * Called when a fragment is first attached to its activity.
146     * {@link #onCreate(Bundle)} will be called after this.
147     */
148    @Override
149    public void onAttach(Activity activity) {
150        super.onAttach(activity);
151
152        mContext = activity;
153
154        // Notify the activity that we're here.
155        if (activity instanceof AccountSettingsXL) {
156            ((AccountSettingsXL)activity).onAttach(this);
157        }
158    }
159
160    /**
161     * Called to do initial creation of a fragment.  This is called after
162     * {@link #onAttach(Activity)} and before {@link #onActivityCreated(Bundle)}.
163     */
164    @Override
165    public void onCreate(Bundle savedInstanceState) {
166        if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
167            Log.d(Email.LOG_TAG, "AccountSettingsFragment onCreate");
168        }
169        super.onCreate(savedInstanceState);
170
171        // Load the preferences from an XML resource
172        addPreferencesFromResource(R.xml.account_settings_preferences);
173
174        // Start loading the account data, if provided in the arguments
175        // If not, activity must call startLoadingAccount() directly
176        Bundle b = getArguments();
177        if (b != null) {
178            long accountId = b.getLong(BUNDLE_KEY_ACCOUNT_ID, -1);
179            if (accountId >= 0 && !mLoaded) {
180                startLoadingAccount(accountId);
181            }
182        }
183
184        mAccountDirty = false;
185    }
186
187    @Override
188    public void onActivityCreated(Bundle savedInstanceState) {
189        if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
190            Log.d(Email.LOG_TAG, "AccountSettingsFragment onActivityCreated");
191        }
192        super.onActivityCreated(savedInstanceState);
193    }
194
195    /**
196     * Called when the Fragment is visible to the user.
197     */
198    @Override
199    public void onStart() {
200        if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
201            Log.d(Email.LOG_TAG, "AccountSettingsFragment onStart");
202        }
203        super.onStart();
204        mStarted = true;
205
206        // If the loaded account is ready now, load the UI
207        if (mAccount != null && !mLoaded) {
208            loadSettings();
209        }
210    }
211
212    /**
213     * Called when the fragment is visible to the user and actively running.
214     */
215    @Override
216    public void onResume() {
217        if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
218            Log.d(Email.LOG_TAG, "AccountSettingsFragment onResume");
219        }
220        super.onResume();
221
222        if (mAccountDirty) {
223            // if we are coming back from editing incoming or outgoing settings,
224            // we need to refresh them here so we don't accidentally overwrite the
225            // old values we're still holding here
226            mAccount.mHostAuthRecv =
227                HostAuth.restoreHostAuthWithId(mContext, mAccount.mHostAuthKeyRecv);
228            mAccount.mHostAuthSend =
229                HostAuth.restoreHostAuthWithId(mContext, mAccount.mHostAuthKeySend);
230            // Because "delete policy" UI is on edit incoming settings, we have
231            // to refresh that as well.
232            Account refreshedAccount = Account.restoreAccountWithId(mContext, mAccount.mId);
233            if (refreshedAccount == null || mAccount.mHostAuthRecv == null
234                    || mAccount.mHostAuthSend == null) {
235                mSaveOnExit = false;
236                mCallback.abandonEdit();
237                return;
238            }
239            mAccount.setDeletePolicy(refreshedAccount.getDeletePolicy());
240            mAccountDirty = false;
241        }
242    }
243
244    @Override
245    public void onPause() {
246        if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
247            Log.d(Email.LOG_TAG, "AccountSettingsFragment onPause");
248        }
249        super.onPause();
250    }
251
252    /**
253     * Called when the Fragment is no longer started.
254     */
255    @Override
256    public void onStop() {
257        if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
258            Log.d(Email.LOG_TAG, "AccountSettingsFragment onStop");
259        }
260        super.onStop();
261        mStarted = false;
262    }
263
264    /**
265     * Called when the fragment is no longer in use.
266     */
267    @Override
268    public void onDestroy() {
269        if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
270            Log.d(Email.LOG_TAG, "AccountSettingsFragment onDestroy");
271        }
272        super.onDestroy();
273
274        Utility.cancelTaskInterrupt(mLoadAccountTask);
275        mLoadAccountTask = null;
276
277        // If there is good account data and we have not abandoned it, save it now
278        if (mSaveOnExit) {
279            saveSettings();
280            mSaveOnExit = false;
281        }
282    }
283
284    @Override
285    public void onSaveInstanceState(Bundle outState) {
286        if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
287            Log.d(Email.LOG_TAG, "AccountSettingsFragment onSaveInstanceState");
288        }
289        super.onSaveInstanceState(outState);
290    }
291
292    /**
293     * Activity provides callbacks here
294     */
295    public void setCallback(Callback callback) {
296        mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback;
297    }
298
299    /**
300     * Start loading a single account in preparation for editing it
301     */
302    public void startLoadingAccount(long accountId) {
303        Utility.cancelTaskInterrupt(mLoadAccountTask);
304        mLoadAccountTask = new LoadAccountTask().execute(accountId);
305    }
306
307    /**
308     * Async task to load account in order to view/edit it
309     */
310    private class LoadAccountTask extends AsyncTask<Long, Void, Account> {
311        @Override
312        protected Account doInBackground(Long... params) {
313            long accountId = params[0];
314            Account account = Account.restoreAccountWithId(mContext, accountId);
315            if (account != null) {
316                account.mHostAuthRecv =
317                    HostAuth.restoreHostAuthWithId(mContext, account.mHostAuthKeyRecv);
318                account.mHostAuthSend =
319                    HostAuth.restoreHostAuthWithId(mContext, account.mHostAuthKeySend);
320                if (account.mHostAuthRecv == null || account.mHostAuthSend == null) {
321                    account = null;
322                }
323            }
324            return account;
325        }
326
327        @Override
328        protected void onPostExecute(Account account) {
329            if (!isCancelled()) {
330                if (account == null) {
331                    mSaveOnExit = false;
332                    mCallback.abandonEdit();
333                } else {
334                    mAccount = account;
335                    if (mStarted && !mLoaded) {
336                        loadSettings();
337                    }
338                }
339            }
340        }
341    }
342
343    /**
344     * Load account data into preference UI
345     */
346    private void loadSettings() {
347        // We can only do this once, so prevent repeat
348        mLoaded = true;
349        // Once loaded the data is ready to be saved, as well
350        mSaveOnExit = true;
351
352        PreferenceCategory topCategory =
353            (PreferenceCategory) findPreference(PREFERENCE_TOP_CATEGORY);
354        topCategory.setTitle(mContext.getString(R.string.account_settings_title_fmt));
355
356        mAccountDescription = (EditTextPreference) findPreference(PREFERENCE_DESCRIPTION);
357        mAccountDescription.setSummary(mAccount.getDisplayName());
358        mAccountDescription.setText(mAccount.getDisplayName());
359        mAccountDescription.setOnPreferenceChangeListener(
360            new Preference.OnPreferenceChangeListener() {
361                public boolean onPreferenceChange(Preference preference, Object newValue) {
362                    final String summary = newValue.toString();
363                    mAccountDescription.setSummary(summary);
364                    mAccountDescription.setText(summary);
365                    return false;
366                }
367            }
368        );
369
370        mAccountName = (EditTextPreference) findPreference(PREFERENCE_NAME);
371        mAccountName.setSummary(mAccount.getSenderName());
372        mAccountName.setText(mAccount.getSenderName());
373        mAccountName.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
374            public boolean onPreferenceChange(Preference preference, Object newValue) {
375                final String summary = newValue.toString();
376                mAccountName.setSummary(summary);
377                mAccountName.setText(summary);
378                return false;
379            }
380        });
381
382        mAccountSignature = (EditTextPreference) findPreference(PREFERENCE_SIGNATURE);
383        mAccountSignature.setSummary(mAccount.getSignature());
384        mAccountSignature.setText(mAccount.getSignature());
385        mAccountSignature.setOnPreferenceChangeListener(
386                new Preference.OnPreferenceChangeListener() {
387                    public boolean onPreferenceChange(Preference preference, Object newValue) {
388                        String summary = newValue.toString();
389                        if (summary == null || summary.length() == 0) {
390                            mAccountSignature.setSummary(R.string.account_settings_signature_hint);
391                        } else {
392                            mAccountSignature.setSummary(summary);
393                        }
394                        mAccountSignature.setText(summary);
395                        return false;
396                    }
397                });
398
399        mCheckFrequency = (ListPreference) findPreference(PREFERENCE_FREQUENCY);
400
401        // Before setting value, we may need to adjust the lists
402        Store.StoreInfo info = Store.StoreInfo.getStoreInfo(mAccount.getStoreUri(mContext),
403                mContext);
404        if (info.mPushSupported) {
405            mCheckFrequency.setEntries(R.array.account_settings_check_frequency_entries_push);
406            mCheckFrequency.setEntryValues(R.array.account_settings_check_frequency_values_push);
407        }
408
409        mCheckFrequency.setValue(String.valueOf(mAccount.getSyncInterval()));
410        mCheckFrequency.setSummary(mCheckFrequency.getEntry());
411        mCheckFrequency.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
412            public boolean onPreferenceChange(Preference preference, Object newValue) {
413                final String summary = newValue.toString();
414                int index = mCheckFrequency.findIndexOfValue(summary);
415                mCheckFrequency.setSummary(mCheckFrequency.getEntries()[index]);
416                mCheckFrequency.setValue(summary);
417                return false;
418            }
419        });
420
421        // Add check window preference
422        mSyncWindow = null;
423        if (info.mVisibleLimitDefault == -1) {
424            mSyncWindow = new ListPreference(mContext);
425            mSyncWindow.setTitle(R.string.account_setup_options_mail_window_label);
426            mSyncWindow.setEntries(R.array.account_settings_mail_window_entries);
427            mSyncWindow.setEntryValues(R.array.account_settings_mail_window_values);
428            mSyncWindow.setValue(String.valueOf(mAccount.getSyncLookback()));
429            mSyncWindow.setSummary(mSyncWindow.getEntry());
430            mSyncWindow.setOrder(4);
431            mSyncWindow.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
432                public boolean onPreferenceChange(Preference preference, Object newValue) {
433                    final String summary = newValue.toString();
434                    int index = mSyncWindow.findIndexOfValue(summary);
435                    mSyncWindow.setSummary(mSyncWindow.getEntries()[index]);
436                    mSyncWindow.setValue(summary);
437                    return false;
438                }
439            });
440            topCategory.addPreference(mSyncWindow);
441        }
442
443        mAccountDefault = (CheckBoxPreference) findPreference(PREFERENCE_DEFAULT);
444        mAccountDefault.setChecked(mAccount.mId == Account.getDefaultAccountId(mContext));
445
446        mAccountNotify = (CheckBoxPreference) findPreference(PREFERENCE_NOTIFY);
447        mAccountNotify.setChecked(0 != (mAccount.getFlags() & Account.FLAGS_NOTIFY_NEW_MAIL));
448
449        mAccountRingtone = (RingtonePreference) findPreference(PREFERENCE_RINGTONE);
450
451        // The following two lines act as a workaround for the RingtonePreference
452        // which does not let us set/get the value programmatically
453        SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences();
454        prefs.edit().putString(PREFERENCE_RINGTONE, mAccount.getRingtone()).apply();
455
456        mAccountVibrateWhen = (ListPreference) findPreference(PREFERENCE_VIBRATE_WHEN);
457        boolean flagsVibrate = 0 != (mAccount.getFlags() & Account.FLAGS_VIBRATE_ALWAYS);
458        boolean flagsVibrateSilent = 0 != (mAccount.getFlags() & Account.FLAGS_VIBRATE_WHEN_SILENT);
459        mAccountVibrateWhen.setValue(
460                flagsVibrate ? PREFERENCE_VALUE_VIBRATE_WHEN_ALWAYS :
461                flagsVibrateSilent ? PREFERENCE_VALUE_VIBRATE_WHEN_SILENT :
462                    PREFERENCE_VALUE_VIBRATE_WHEN_NEVER);
463
464        findPreference(PREFERENCE_INCOMING).setOnPreferenceClickListener(
465                new Preference.OnPreferenceClickListener() {
466                    public boolean onPreferenceClick(Preference preference) {
467                        mAccountDirty = true;
468                        mCallback.onIncomingSettings(mAccount);
469                        return true;
470                    }
471                });
472
473        // Hide the outgoing account setup link if it's not activated
474        Preference prefOutgoing = findPreference(PREFERENCE_OUTGOING);
475        boolean showOutgoing = true;
476        try {
477            Sender sender = Sender.getInstance(mContext, mAccount.getSenderUri(mContext));
478            if (sender != null) {
479                Class<? extends android.app.Activity> setting = sender.getSettingActivityClass();
480                showOutgoing = (setting != null);
481            }
482        } catch (MessagingException me) {
483            // just leave showOutgoing as true - bias towards showing it, so user can fix it
484        }
485        if (showOutgoing) {
486            prefOutgoing.setOnPreferenceClickListener(
487                    new Preference.OnPreferenceClickListener() {
488                        public boolean onPreferenceClick(Preference preference) {
489                            mAccountDirty = true;
490                            mCallback.onOutgoingSettings(mAccount);
491                            return true;
492                        }
493                    });
494        } else {
495            PreferenceCategory serverCategory = (PreferenceCategory) findPreference(
496                    PREFERENCE_SERVER_CATEGORY);
497            serverCategory.removePreference(prefOutgoing);
498        }
499
500        mSyncContacts = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_CONTACTS);
501        mSyncCalendar = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_CALENDAR);
502        mSyncEmail = (CheckBoxPreference) findPreference(PREFERENCE_SYNC_EMAIL);
503        if (mAccount.mHostAuthRecv.mProtocol.equals("eas")) {
504            android.accounts.Account acct = new android.accounts.Account(mAccount.mEmailAddress,
505                    Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
506            mSyncContacts.setChecked(ContentResolver
507                    .getSyncAutomatically(acct, ContactsContract.AUTHORITY));
508            mSyncCalendar.setChecked(ContentResolver
509                    .getSyncAutomatically(acct, Calendar.AUTHORITY));
510            mSyncEmail.setChecked(ContentResolver
511                    .getSyncAutomatically(acct, EmailContent.AUTHORITY));
512        } else {
513            PreferenceCategory serverCategory = (PreferenceCategory) findPreference(
514                    PREFERENCE_SERVER_CATEGORY);
515            serverCategory.removePreference(mSyncContacts);
516            serverCategory.removePreference(mSyncCalendar);
517            serverCategory.removePreference(mSyncEmail);
518        }
519
520        // Temporary home for delete account
521        Preference prefDeleteAccount = findPreference(PREFERENCE_DELETE_ACCOUNT);
522        prefDeleteAccount.setOnPreferenceClickListener(
523                new Preference.OnPreferenceClickListener() {
524                    public boolean onPreferenceClick(Preference preference) {
525                        DeleteAccountFragment dialogFragment = DeleteAccountFragment.newInstance(
526                                mAccount, AccountSettingsFragment.this);
527                        FragmentTransaction ft = getFragmentManager().openTransaction();
528                        ft.addToBackStack(null);
529                        dialogFragment.show(ft, DeleteAccountFragment.TAG);
530                        return true;
531                    }
532                });
533    }
534
535    /*
536     * TODO: Should collect the data in the UI thread, but should spin out a thread to write
537     * to sync settings, provider, and service enabler.
538     */
539    public void saveSettings() {
540        int newFlags = mAccount.getFlags() &
541                ~(Account.FLAGS_NOTIFY_NEW_MAIL |
542                        Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_VIBRATE_WHEN_SILENT);
543
544        mAccount.setDefaultAccount(mAccountDefault.isChecked());
545        mAccount.setDisplayName(mAccountDescription.getText());
546        mAccount.setSenderName(mAccountName.getText());
547        mAccount.setSignature(mAccountSignature.getText());
548        newFlags |= mAccountNotify.isChecked() ? Account.FLAGS_NOTIFY_NEW_MAIL : 0;
549        mAccount.setSyncInterval(Integer.parseInt(mCheckFrequency.getValue()));
550        if (mSyncWindow != null) {
551            mAccount.setSyncLookback(Integer.parseInt(mSyncWindow.getValue()));
552        }
553        if (mAccountVibrateWhen.getValue().equals(PREFERENCE_VALUE_VIBRATE_WHEN_ALWAYS)) {
554            newFlags |= Account.FLAGS_VIBRATE_ALWAYS;
555        } else if (mAccountVibrateWhen.getValue().equals(PREFERENCE_VALUE_VIBRATE_WHEN_SILENT)) {
556            newFlags |= Account.FLAGS_VIBRATE_WHEN_SILENT;
557        }
558        SharedPreferences prefs = mAccountRingtone.getPreferenceManager().getSharedPreferences();
559        mAccount.setRingtone(prefs.getString(PREFERENCE_RINGTONE, null));
560        mAccount.setFlags(newFlags);
561
562        if (mAccount.mHostAuthRecv.mProtocol.equals("eas")) {
563            android.accounts.Account acct = new android.accounts.Account(mAccount.mEmailAddress,
564                    Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
565            ContentResolver.setSyncAutomatically(acct, ContactsContract.AUTHORITY,
566                    mSyncContacts.isChecked());
567            ContentResolver.setSyncAutomatically(acct, Calendar.AUTHORITY,
568                    mSyncCalendar.isChecked());
569            ContentResolver.setSyncAutomatically(acct, EmailContent.AUTHORITY,
570                    mSyncEmail.isChecked());
571        }
572        AccountSettingsUtils.commitSettings(mContext, mAccount);
573        Email.setServicesEnabled(mContext);
574    }
575
576    /**
577     * Dialog fragment to show "remove account?" dialog
578     */
579    public static class DeleteAccountFragment extends DialogFragment {
580        private final static String TAG = "DeleteAccountFragment";
581
582        // Argument bundle keys
583        private final static String BUNDLE_KEY_ACCOUNT_NAME = "DeleteAccountFragment.Name";
584
585        /**
586         * Create the dialog with parameters
587         */
588        public static DeleteAccountFragment newInstance(Account account, Fragment parentFragment) {
589            DeleteAccountFragment f = new DeleteAccountFragment();
590            Bundle b = new Bundle();
591            b.putString(BUNDLE_KEY_ACCOUNT_NAME, account.getDisplayName());
592            f.setArguments(b);
593            f.setTargetFragment(parentFragment, 0);
594            return f;
595        }
596
597        @Override
598        public Dialog onCreateDialog(Bundle savedInstanceState) {
599            Context context = getActivity();
600            final String name = getArguments().getString(BUNDLE_KEY_ACCOUNT_NAME);
601
602            return new AlertDialog.Builder(context)
603                .setIcon(android.R.drawable.ic_dialog_alert)
604                .setTitle(R.string.account_delete_dlg_title)
605                .setMessage(context.getString(R.string.account_delete_dlg_instructions_fmt, name))
606                .setPositiveButton(
607                        R.string.okay_action,
608                        new DialogInterface.OnClickListener() {
609                            public void onClick(DialogInterface dialog, int whichButton) {
610                                Fragment f = getTargetFragment();
611                                if (f instanceof AccountSettingsFragment) {
612                                    ((AccountSettingsFragment)f).finishDeleteAccount();
613                                }
614                                dismiss();
615                            }
616                        })
617                .setNegativeButton(
618                        R.string.cancel_action,
619                        new DialogInterface.OnClickListener() {
620                            public void onClick(DialogInterface dialog, int whichButton) {
621                                dismiss();
622                            }
623                        })
624                .create();
625        }
626    }
627
628    /**
629     * Callback from delete account dialog - passes the delete command up to the activity
630     */
631    private void finishDeleteAccount() {
632        mSaveOnExit = false;
633        mCallback.deleteAccount(mAccount);
634    }
635}
636