AccountSetupOptions.java revision cd09545b87979fa6b4337f17b5a001f0ef7b5269
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.ExchangeUtils;
21import com.android.email.R;
22import com.android.email.SecurityPolicy.PolicySet;
23import com.android.email.activity.ActivityHelper;
24import com.android.email.mail.Store;
25import com.android.email.provider.EmailContent;
26import com.android.email.provider.EmailContent.Account;
27import com.android.email.service.MailService;
28
29import android.accounts.AccountManagerCallback;
30import android.accounts.AccountManagerFuture;
31import android.accounts.AuthenticatorException;
32import android.accounts.OperationCanceledException;
33import android.app.Activity;
34import android.app.AlertDialog;
35import android.content.DialogInterface;
36import android.content.Intent;
37import android.os.Bundle;
38import android.os.Handler;
39import android.util.Log;
40import android.view.Menu;
41import android.view.MenuItem;
42import android.view.View;
43import android.widget.ArrayAdapter;
44import android.widget.CheckBox;
45import android.widget.Spinner;
46
47import java.io.IOException;
48
49public class AccountSetupOptions extends AccountSetupActivity {
50
51    private Spinner mCheckFrequencyView;
52    private Spinner mSyncWindowView;
53    private CheckBox mDefaultView;
54    private CheckBox mNotifyView;
55    private CheckBox mSyncContactsView;
56    private CheckBox mSyncCalendarView;
57    private CheckBox mSyncEmailView;
58    private Handler mHandler = new Handler();
59    private boolean mDonePressed = false;
60
61    public static final int REQUEST_CODE_ACCEPT_POLICIES = 1;
62
63    /** Default sync window for new EAS accounts */
64    private static final int SYNC_WINDOW_EAS_DEFAULT = com.android.email.Account.SYNC_WINDOW_3_DAYS;
65
66    public static void actionOptions(Activity fromActivity) {
67        fromActivity.startActivity(new Intent(fromActivity, AccountSetupOptions.class));
68    }
69
70    @Override
71    public void onCreate(Bundle savedInstanceState) {
72        super.onCreate(savedInstanceState);
73        ActivityHelper.debugSetWindowFlags(this);
74        setContentView(R.layout.account_setup_options);
75
76        mCheckFrequencyView = (Spinner)findViewById(R.id.account_check_frequency);
77        mSyncWindowView = (Spinner) findViewById(R.id.account_sync_window);
78        mDefaultView = (CheckBox)findViewById(R.id.account_default);
79        mNotifyView = (CheckBox)findViewById(R.id.account_notify);
80        mSyncContactsView = (CheckBox) findViewById(R.id.account_sync_contacts);
81        mSyncCalendarView = (CheckBox) findViewById(R.id.account_sync_calendar);
82        mSyncEmailView = (CheckBox) findViewById(R.id.account_sync_email);
83        mSyncEmailView.setChecked(true);
84
85        // Generate spinner entries using XML arrays used by the preferences
86        int frequencyValuesId;
87        int frequencyEntriesId;
88        Account account = SetupData.getAccount();
89        Store.StoreInfo info = Store.StoreInfo.getStoreInfo(account.getStoreUri(this), this);
90        if (info.mPushSupported) {
91            frequencyValuesId = R.array.account_settings_check_frequency_values_push;
92            frequencyEntriesId = R.array.account_settings_check_frequency_entries_push;
93        } else {
94            frequencyValuesId = R.array.account_settings_check_frequency_values;
95            frequencyEntriesId = R.array.account_settings_check_frequency_entries;
96        }
97        CharSequence[] frequencyValues = getResources().getTextArray(frequencyValuesId);
98        CharSequence[] frequencyEntries = getResources().getTextArray(frequencyEntriesId);
99
100        // Now create the array used by the Spinner
101        SpinnerOption[] checkFrequencies = new SpinnerOption[frequencyEntries.length];
102        for (int i = 0; i < frequencyEntries.length; i++) {
103            checkFrequencies[i] = new SpinnerOption(
104                    Integer.valueOf(frequencyValues[i].toString()), frequencyEntries[i].toString());
105        }
106
107        ArrayAdapter<SpinnerOption> checkFrequenciesAdapter = new ArrayAdapter<SpinnerOption>(this,
108                android.R.layout.simple_spinner_item, checkFrequencies);
109        checkFrequenciesAdapter
110                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
111        mCheckFrequencyView.setAdapter(checkFrequenciesAdapter);
112
113        if (info.mVisibleLimitDefault == -1) {
114            enableEASSyncWindowSpinner();
115        }
116
117        // Note:  It is OK to use mAccount.mIsDefault here *only* because the account
118        // has not been written to the DB yet.  Ordinarily, call Account.getDefaultAccountId().
119        if (account.mIsDefault || SetupData.isDefault()) {
120            mDefaultView.setChecked(true);
121        }
122        mNotifyView.setChecked(
123                (account.getFlags() & EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL) != 0);
124        SpinnerOption.setSpinnerOptionValue(mCheckFrequencyView, account.getSyncInterval());
125
126        // Setup any additional items to support EAS & EAS flow mode
127        if ("eas".equals(info.mScheme)) {
128            // "also sync contacts" == "true"
129            mSyncContactsView.setVisibility(View.VISIBLE);
130            mSyncContactsView.setChecked(true);
131            mSyncCalendarView.setVisibility(View.VISIBLE);
132            mSyncCalendarView.setChecked(true);
133        }
134
135        if (SetupData.isAutoSetup()) {
136            onDone();
137        }
138    }
139
140    /**
141     * Add "Next" button when this activity is displayed
142     */
143    @Override
144    public boolean onCreateOptionsMenu(Menu menu) {
145        getMenuInflater().inflate(R.menu.account_setup_next_option, menu);
146        return super.onCreateOptionsMenu(menu);
147    }
148
149    /**
150     * Respond to clicks in the "Next" button
151     */
152    @Override
153    public boolean onOptionsItemSelected(MenuItem item) {
154        switch (item.getItemId()) {
155            case R.id.next:
156                // Don't allow this more than once (Exchange accounts call an async method
157                // before finish()'ing the Activity, which allows this code to potentially be
158                // executed multiple times
159                if (!mDonePressed) {
160                    onDone();
161                    mDonePressed = true;
162                }
163                return true;
164        }
165        return super.onOptionsItemSelected(item);
166    }
167
168
169
170    AccountManagerCallback<Bundle> mAccountManagerCallback = new AccountManagerCallback<Bundle>() {
171        public void run(AccountManagerFuture<Bundle> future) {
172            try {
173                Bundle bundle = future.getResult();
174                bundle.keySet();
175                mHandler.post(new Runnable() {
176                    public void run() {
177                        optionsComplete();
178                    }
179                });
180                return;
181            } catch (OperationCanceledException e) {
182                Log.d(Email.LOG_TAG, "addAccount was canceled");
183            } catch (IOException e) {
184                Log.d(Email.LOG_TAG, "addAccount failed: " + e);
185            } catch (AuthenticatorException e) {
186                Log.d(Email.LOG_TAG, "addAccount failed: " + e);
187            }
188            showErrorDialog(R.string.account_setup_failed_dlg_auth_message,
189                    R.string.system_account_create_failed);
190        }
191    };
192
193    private void showErrorDialog(final int msgResId, final Object... args) {
194        mHandler.post(new Runnable() {
195            public void run() {
196                new AlertDialog.Builder(AccountSetupOptions.this)
197                        .setIcon(android.R.drawable.ic_dialog_alert)
198                        .setTitle(getString(R.string.account_setup_failed_dlg_title))
199                        .setMessage(getString(msgResId, args))
200                        .setCancelable(true)
201                        .setPositiveButton(
202                                getString(R.string.account_setup_failed_dlg_edit_details_action),
203                                new DialogInterface.OnClickListener() {
204                                    public void onClick(DialogInterface dialog, int which) {
205                                       finish();
206                                    }
207                                })
208                        .show();
209            }
210        });
211    }
212
213    @Override
214    public void onActivityResult(int requestCode, int resultCode, Intent data) {
215        saveAccountAndFinish();
216    }
217
218    private void optionsComplete() {
219        // If we've got policies for this account, ask the user to accept.
220        Account account = SetupData.getAccount();
221        if ((account.mFlags & Account.FLAGS_SECURITY_HOLD) != 0) {
222            Intent intent = AccountSecurity.actionUpdateSecurityIntent(this, account.mId);
223            startActivityForResult(intent, AccountSetupOptions.REQUEST_CODE_ACCEPT_POLICIES);
224            return;
225        }
226        saveAccountAndFinish();
227    }
228
229    private void saveAccountAndFinish() {
230        // Clear the incomplete/security hold flag now
231        Account account = SetupData.getAccount();
232        account.mFlags &= ~(Account.FLAGS_INCOMPLETE | Account.FLAGS_SECURITY_HOLD);
233        AccountSettingsUtils.commitSettings(this, account);
234        Email.setServicesEnabled(this);
235        AccountSetupNames.actionSetNames(this);
236        // Start up ExchangeService (if it isn't already running)
237        ExchangeUtils.startExchangeService(this);
238        finish();
239    }
240
241    private void onDone() {
242        Account account = SetupData.getAccount();
243        account.setDisplayName(account.getEmailAddress());
244        int newFlags = account.getFlags() & ~(EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL);
245        if (mNotifyView.isChecked()) {
246            newFlags |= EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL;
247        }
248        account.setFlags(newFlags);
249        account.setSyncInterval((Integer)((SpinnerOption)mCheckFrequencyView
250                .getSelectedItem()).value);
251        if (mSyncWindowView.getVisibility() == View.VISIBLE) {
252            int window = (Integer)((SpinnerOption)mSyncWindowView.getSelectedItem()).value;
253            account.setSyncLookback(window);
254        }
255        account.setDefaultAccount(mDefaultView.isChecked());
256
257        // Setup up the AccountManager account
258        if (!account.isSaved() && account.mHostAuthRecv != null) {
259            // Set the incomplete flag here to avoid reconciliation issues in ExchangeService
260            account.mFlags |= Account.FLAGS_INCOMPLETE;
261            boolean calendar = false;
262            boolean contacts = false;
263            boolean email = mSyncEmailView.isChecked();
264            if (account.mHostAuthRecv.mProtocol.equals("eas")) {
265                // Set security hold if necessary to prevent sync until policies are accepted
266                PolicySet policySet = SetupData.getPolicySet();
267                if (policySet != null && policySet.getSecurityCode() != 0) {
268                    account.mSecurityFlags = policySet.getSecurityCode();
269                    account.mFlags |= Account.FLAGS_SECURITY_HOLD;
270                }
271                // Get flags for contacts/calendar sync
272                contacts = mSyncContactsView.isChecked();
273                calendar = mSyncCalendarView.isChecked();
274            }
275            AccountSettingsUtils.commitSettings(this, account);
276            MailService.setupAccountManagerAccount(this, account, email, calendar, contacts,
277                    mAccountManagerCallback);
278        } else {
279            optionsComplete();
280        }
281    }
282
283    /**
284     * Enable an additional spinner using the arrays normally handled by preferences
285     */
286    private void enableEASSyncWindowSpinner() {
287        // Show everything
288        findViewById(R.id.account_sync_window_label).setVisibility(View.VISIBLE);
289        mSyncWindowView.setVisibility(View.VISIBLE);
290
291        // Generate spinner entries using XML arrays used by the preferences
292        CharSequence[] windowValues = getResources().getTextArray(
293                R.array.account_settings_mail_window_values);
294        CharSequence[] windowEntries = getResources().getTextArray(
295                R.array.account_settings_mail_window_entries);
296
297        // Now create the array used by the Spinner
298        SpinnerOption[] windowOptions = new SpinnerOption[windowEntries.length];
299        int defaultIndex = -1;
300        for (int i = 0; i < windowEntries.length; i++) {
301            final int value = Integer.valueOf(windowValues[i].toString());
302            windowOptions[i] = new SpinnerOption(value, windowEntries[i].toString());
303            if (value == SYNC_WINDOW_EAS_DEFAULT) {
304                defaultIndex = i;
305            }
306        }
307
308        ArrayAdapter<SpinnerOption> windowOptionsAdapter = new ArrayAdapter<SpinnerOption>(this,
309                android.R.layout.simple_spinner_item, windowOptions);
310        windowOptionsAdapter
311                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
312        mSyncWindowView.setAdapter(windowOptionsAdapter);
313
314        SpinnerOption.setSpinnerOptionValue(mSyncWindowView,
315                SetupData.getAccount().getSyncLookback());
316        if (defaultIndex >= 0) {
317            mSyncWindowView.setSelection(defaultIndex);
318        }
319    }
320}
321